C++项目 -- 负载均衡OJ(一)compile_server

C++项目 – 负载均衡OJ(二)compile_server

文章目录

  • C++项目 -- 负载均衡OJ(二)compile_server
  • 一、compile_server设计
    • 1.总体服务流程
  • 二、compiler.hpp
  • 三、runner.hpp
  • 四、compile_run.hpp
  • 五、compile_server.cc
    • 5.1.编译功能调试:
    • 5.2.CompileAndRun功能调试
    • 5.3.熟悉cpp-httplib库
    • 5.4.将CompileAndRun服务打包成一个网络服务
    • 5.5.使用Postman测试网络请求服务


一、compile_server设计

1.总体服务流程

在这里插入图片描述

  • 远端代码提交上来后,形成一份临时文件用于编译;
  • fork出一个子进程,让子进程执行编译(使用程序替换的功能调用g++进行编译),如果编译通过,标准输出没有结果;如果编译出错,需要行程临时文件来保存出错的结果,方便返回给客户端;
  • 主进程继续接收代码;

二、compiler.hpp

  • 该hpp文件主要提供编译文件的方法;
  • Compiler中的Compile函数用于将源cpp文件进行编译,源文件保存在现在目录下的temp子目录,如1234.cpp,我们需要根据源文件生成可执行文件.exe,当编译错误时需要生成标准错误文件.stderr;
    在这里插入图片描述
    • Compile函数使用util.hppPathUtil类中的方法来获取源文件对应的可执行文件名和标准错误文件名;
    • Compile函数创建子进程,在子进程中使用程序替换接口execlp,调用g++对文件进行编译,并将错误信息重定向到临时的错误信息文件.stderr中;
    • execlp第一个参数是替换调用哪个程序,后面的参数才是如何调用;
    • 程序替换并不会影响进程的文件描述符,因此重定向stderr针对子进程替换运行的程序依然生效
    • 在编译之前,需要将标准错误文件重定向到我们定义的临时错误文件中保存下来;
    • 父进程用来判断最后是否编译成功,使用comm模块中的IsFileExists函数来进行判断;
#pragma once#include "../Comm/util.hpp"namespace ns_compiler
{using namespace ns_util;class Compiler{// 该类只提供方法public:Compiler(){}~Compiler(){}static bool Compile(const string &file_name){pid_t pid = fork();if (pid < 0){return false;}else if (pid == 0){// 子进程,负责调用g++编译器进行编译// 在编译之前,需要打开保存错误信息的临时文件,并将stderr重定向到该文件int _stderr = open(PathUtil::Stderr(file_name).c_str(), O_CREAT | O_WRONLY, 0644);if(_stderr < 0){exit(0);}//重定向标准错误到_stderrdup2(_stderr, 2);//调用g++完成编译工作//g++ -o target src -std=c++11//最后一个参数后面一定要跟一个nullptrexeclp("g++", "-o", PathUtil::Exe(file_name).c_str(),\PathUtil::Src(file_name).c_str(), "-std=c++11", nullptr);//程序替换失败exit(2);}else{// 父进程waitpid(pid, nullptr, 0);//编译是否成功,看对应的文件夹下有没有生成对应的可执行程序if(FileUtil::IsFileExists(PathUtil::Exe(file_name))){return true;}return false;}}};
}

三、runner.hpp

  • runner.hpp文件主要用于编译成功的用户代码的运行功能的编写;
  • Run函数用于运行编译成功的用户代码生成的可执行程序;
    • 输入参数指明文件名即可,不需要带后缀和路径;输入参数还需要指定子进程的资源占用限制,方便出题者来指定该题的限制;
    • 返回值用于标定该程序的运行情况:
      返回值>0:程序异常,退出时收到了信号,返回值就是对应的信号编号;
      返回值==0:正常运行完毕的,结果保存到了对应的临时文件中;
      返回值<0,内部错误;
    • 该函数无需判断用户的可执行程序的运行结果正确与否,只需考虑是否正确运行完毕;
    • 在程序运行期间,我们需要将标准输入、标准输出、标准错误三个文件全部打开并重定向,以便读取输入数据、保存运行结果和运行时的错误信息;
    • 文件打开后,文件描述符是可以被子进程继承下去的
    • 由于我们替换的程序是在tmp文件夹里面的,因此在选择程序替换接口的时候,我们不能选择不带路径的接口(直接去环境变量列表里面查询),需要选择指定路径的接口
      在这里插入图片描述
    • 我们需要限制子进程运行用户程序所占用的系统资源,避免系统资源的过度占用,可以通过SetProcLimit接口设置;
    • 最后通过信号判断程序运行是否异常,如果没有异常,子进程的状态信息status返回0,如果有异常,一定返回大于0的值;
  • SetProcLimit函数用于设置进程占用的资源大小
    • 输入参数用来指定cpu运行时间和内存空间的占用限制,内存空间使用KB为单位;
    • 使用sertlimit接口来对进程的资源进行限制:
      在这里插入图片描述
    • resource是限制资源的类型:
      在这里插入图片描述
    • rlim是一个结构体,软限制为一般进程设置的限制,硬限制为我们所能设置的最大资源的上限值,一般设为无限制;
      在这里插入图片描述

四、compile_run.hpp

  • 该文件主要实现的功能是:
    • 适配用户需求,定制通信协议;
    • 正确调用compile and run;
    • 形成唯一文件名;
  • CompileAndRun类中的Start函数主要完成的功能有:
    • 接受客户端传来的序列化的字符串,并完成反序列化;
      在这里插入图片描述
    • 序列化工具使用jsoncpp库中的接口,
      在这里插入图片描述
      编译时需要链接库:
      在这里插入图片描述
      形成的是序列化的kv值的字符串:
      在这里插入图片描述
      json的作用:将结构化的数据转化成为一个字符串;
    • 在完成反序列化后,调用FileUtil类中的UniqueFileName方法生成唯一的代码源文件,然后调用WriteFile将代码写入该文件中;
    • reader.parse接口用于完成反序列化;asString是将json中的v作为字符串;
    • 形成用户代码源文件后,对其进行编译和运行操作,返回运行的信息;
    • 使用goto语句进行统一的差错处理,一旦上面的创建源文件、编译、运行出错,先赋值错误代码给status_code,然后goto到END处进行错误代码解析,并通过jsoncpp工具完成序列化;
    • goto语句之间不允许有任何的变量定义
    • 最后删除临时文件;
  • CodeToDesc函数主要完成返回错误代码对应的错误原因功能:
    在这里插入图片描述
    • RemoveTempFile函数主要完成清理临时文件的功能:
      使用unlink接口删除文件
      在这里插入图片描述

五、compile_server.cc

5.1.编译功能调试:

#include "compiler.hpp"using namespace ns_compiler;int main() 
{std::string file = "code";Compiler::Compile(file);return 0;
}

在现路径temp文件夹下创建code.cpp文件,测试编译功能:
在这里插入图片描述
在这里插入图片描述
编译运行compile_server.cc:
在这里插入图片描述
在这里插入图片描述
生成.exe和.stderr文件,此时.stderr文件是没有内容的;

  • 如果code.cpp中有错误:
    日志报错:
    在这里插入图片描述
    只会生成.stderr文件,里面保存报错信息:
    在这里插入图片描述

5.2.CompileAndRun功能调试

  • R"()"是c++11的raw string原生字符串,如果出现特殊字符,保持原貌
#include "compile_run.hpp"using namespace ns_compiler;
using namespace ns_runner;
using namespace ns_compile_and_run;int main() 
{//充当客户端请求的json串string in_json;Json::Value in_value;//c++11原生字符串:R"()"in_value["code"] = R"(#include<iostream>int main(){std::cout << "hello world" << std::endl;return 0;})";in_value["input"] = "";in_value["cpu_limit"] = 1;in_value["mem_limit"] = 10240 * 3;Json::FastWriter writer;in_json = writer.write(in_value);cout << in_json << endl;string out_json;CompileAndRun::Start(in_json, out_json);cout << out_json << endl;return 0;
}
  • 编译并运行成功;
    在这里插入图片描述成功在路径下生成文件名;
    在这里插入图片描述
  • 编译失败,得到失败原因
    在这里插入图片描述
  • CPU运行超时:
    在这里插入图片描述
  • 超出内存限制:
    在这里插入图片描述
  • 除0错误:
    在这里插入图片描述

5.3.熟悉cpp-httplib库

  • 接入cpp-httplib只需将httplib.h拷贝至项目中并包含,就可以使用;
  • cpp-httplib需使用高版本的gcc进行编译,最好在gcc 7以上;
  • cpp-httplib是阻塞式多线程的一个网络http库;
  • erver类中Get函数是接受请求并响应,第一个参数是根目录下的服务名称,第二个参数是响应的回调函数,用户访问更目录下的响应服务,服务器就会调用回调函数并返回响应;
  • Request是请求类,Responce是响应类;
  • content-type中text/explain是文本
  • 当用户请求hello服务时,就响应相应的文本
#include "compile_run.hpp"
#include "../Comm/httplib.h"using namespace ns_compiler;
using namespace ns_runner;
using namespace ns_compile_and_run;
using namespace httplib;int main() 
{Server svr;//用户如果请求根目录下的hello服务,服务器就会调用回调函数并返回响应svr.Get("/hello", [](const Request &req, Response &resp){//content-type中text/plain表示文本格式//编码格式设置为为utf-8resp.set_content("hello httplib!", "text/plain;charset=utf-8");});svr.listen("0.0.0.0", 8080);return 0;
}

在这里插入图片描述

  • 设置根目录与首页:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

5.4.将CompileAndRun服务打包成一个网络服务

  • 用户使用Post进行请求CompileAndRun服务;
  • 用户的请求存在Request中的body;
  • 服务器给用户的响应是json格式的,因此content-type要设置成applocation/json;
  • 从命令行参数获取端口号;
#include "compile_run.hpp"
#include "../Comm/httplib.h"using namespace ns_compiler;
using namespace ns_runner;
using namespace ns_compile_and_run;
using namespace httplib;void Usage(const string proc)
{std::cerr << "Usage: " << "\n\t" << proc << "port" << endl;
}int main(int argc, char *argv[]) 
{if(argc != 2){Usage(argv[0]);return 1;}Server svr;svr.Post("/compile_and_run", [](const Request &req, Response &resp){//用户请求的服务正文是我们想要的json stringstring in_json = req.body;string out_json;if(!in_json.empty()){CompileAndRun::Start(in_json, &out_json);resp.set_content(out_json, "application/json;charset=utf-8");}});svr.listen("0.0.0.0", atoi(argv[1]));return 0;
}return 0;
}

5.5.使用Postman测试网络请求服务

  • 设置Postman的请求为POST,请求的Body中内容为Row的Json格式,内容如下:
    在这里插入图片描述
  • 然后运行CompileServer服务,并建立向云服务器的8080号端口的请求:
    在这里插入图片描述
    在这里插入图片描述
  • Postman端收到了服务端返回的Json串,表明服务运行成功;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/280517.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【CNN轻量化】ParameterNet: Parameters Are All You Need 参数就是你所需要的

论文链接&#xff1a;http://arxiv.org/abs/2306.14525 代码链接&#xff1a;https://github.com/huawei-noah/Efficient-AI-Backbones 一、摘要 现有的低FLOPs模型&#xff08;轻量化模型&#xff09;无法从大规模预训练中受益。本文旨在增加大规模视觉预训练模型中的参数数量…

责任链模式(处理逻辑解耦)

前言 使用设计模式的主要目的之一就是解耦&#xff0c;让程序易于维护和更好扩展。 责任链则是将处理逻辑进行解耦&#xff0c;将独立的处理逻辑抽取到不同的处理者中&#xff0c;每个处理者都能够单独修改而不影响其他处理者。 使用时&#xff0c;依次调用链上的处理者处理…

从零到一构建短链接系统(八)

1.git上传远程仓库&#xff08;现在才想起来&#xff09; git init git add . git commit -m "first commit" git remote add origin OLiyscxm/shortlink git push -u origin "master" 2.开发全局异常拦截器之后就可以简化UserController 拦截器可以…

Jackson 2.x 系列【3】解析器 JsonParser

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Jackson 版本 2.17.0 源码地址&#xff1a;https://gitee.com/pearl-organization/study-seata-demo 文章目录 1. 前言2. 解析原理3. 案例演示3.1 创建 JsonParser3.2 解析3.3 读取3.4 测试 1. 前…

C语言 指针练习

一、 a、b是两个浮点型变量&#xff0c;给a、b赋值&#xff0c;建立两个指针分别指向a的地址和b的地址&#xff0c;输出两个指针的值。 #include<stdio.h> int main() {float a,b,*p1,*p2;a10.2;b2.3;p1&a;p2&b;printf("a%f,b%f\n",a,b);printf("…

U-Net代码复现--更新中

本文记录自己的学习过程&#xff0c;内容包括&#xff1a; 代码解读&#xff1a;Pytorch-UNet 深度学习编程基础&#xff1a;Pytorch-深度学习&#xff08;新手友好&#xff09; UNet论文解读&#xff1a;医学图像分割&#xff1a;U_Net 论文阅读 数据&#xff1a;https://hack…

Java与Go:指针

在计算机内存中&#xff0c;每个变量都有一个唯一的地址&#xff0c;指针就是用来保存这个地址的变量。通过指针&#xff0c;我们可以间接地访问和修改存储在该地址处的数据。今天我们来聊一聊Java和Go指针&#xff0c;预告一下&#xff0c;我们需要借助C语言做一些小小的比较。…

基于cnn深度学习的yolov5+pyqt+分类+resnet+骨龄检测系统

往期热门博客项目回顾&#xff1a; 计算机视觉项目大集合 改进的yolo目标检测-测距测速 路径规划算法 图像去雨去雾目标检测测距项目 交通标志识别项目 yolo系列-重磅yolov9界面-最新的yolo 姿态识别-3d姿态识别 深度学习小白学习路线 YOLOv5与骨龄识别 YOLOv5&a…

容器中的大模型(三)| 利用大语言模型:容器化高效地部署 PDF 解析器实践...

作者&#xff1a;宋文欣&#xff0c;智领云科技联合创始人兼CTO 01 简介 大语言模型&#xff08;LLMs&#xff09;正逐渐成为人工智能领域的一颗璀璨明星&#xff0c;它们的强大之处在于能够理解和生成自然语言&#xff0c;为各种应用提供了无限可能。为了让这些模型更好地服务…

网络编程:数据库

一、作业 1> 创建一个工人信息库&#xff0c;包含工号&#xff08;主键&#xff09;、姓名、年龄、薪资。 2> 添加三条工人信息&#xff08;可以完整信息&#xff0c;也可以非完整信息&#xff09; 3> 修改某一个工人的薪资&#xff08;确定的一个&#xff09; 4> …

[C++]20:unorderedset和unorderedmap结构和封装。

unorderedset和unorderedmap结构和封装 一.哈希表&#xff1a;1.直接定址法&#xff1a;2.闭散列的开放定址法&#xff1a;1.基本结构&#xff1a;2.insert3.find4.erase5.补充&#xff1a;6.pair<k,v> k的数据类型&#xff1a; 3.开散列的拉链法/哈希桶&#xff1a;1.基…

【计算机网络】计算机网络概述

文章目录 一、计算机网络的概念二、 计算机网络的功能1. 数据通信2. 资源共享3. 分布式处理4. 提高可靠性5. 负载均衡 补充&#xff1a; 计算机的发展阶段小结三、计算机网络的组成1. 组成部分2. 工作方式3. 功能组成 四、 计算机网络的分类1. 按分布范围2. 按使用者3. 按交换技…

零拷贝原理+kafka中的零拷贝

零拷贝原理kafka中的零拷贝 kafka性能之零拷贝传统IO零拷贝mmp优化sendfile优化sendfile DMA scatter/gather优化Kafka是怎么使用零拷贝的 kafka性能之零拷贝 kafka中的零拷贝并不是说完全避免了上下文切换与cpu拷贝的次数, 而是减少这种拷贝次数 传统IO 传统的一次IO流程 rea…

学习开发小程序的起航日记

2024年3月16日 不知不觉中三月份还只剩了一半的光景&#xff0c;我想写的内容还很多没有写&#xff0c;或者更应该说&#xff0c;是想积累的还有很多。现在最应该去完善Java的内容&#xff0c;可还是想先等等。想等搞清楚小程序部分&#xff0c;想等积累完小程序的内容。 这几…

华为综合案例-普通WLAN全覆盖配置(2)

组网图 结果验证 在AC_1和AC_2上执行display ap all命令&#xff0c;检查当前AP的状态&#xff0c;显示以下信息表示AP上线成功。[AC_1] display ap all Total AP information: nor : normal [1] ExtraInfo : Extra information P : insufficient power supply ---…

冒泡排序的原理及其实现

✨✨✨学习的道路很枯燥&#xff0c;希望我们能并肩走下来! 目录 前言 一、冒泡排序的原理 二、代码实现 总结 前言 本篇详细介绍了冒泡排序的原理及其实现&#xff0c;让使用者对冒泡排序的原理及其实现有进一步认识&#xff0c;而不是仅仅停留在表面&#xff0c;更好的模…

xercesc库保存XML功能实现

目录 一 参考链接 二 运行结果 三 代码 一 参考链接 DOM Programming Guide (apache.org) Xerces-c DOM XML文件的构造_xerces-c domimplementation-CSDN博客 Xerces-c库的使用-CSDN博客 二 运行结果 三 代码 #if 1//参考链接&#xff1a; https://blog.csdn.net/RGBMa…

流畅的 Python 第二版(GPT 重译)(九)

第四部分&#xff1a;控制流 第十七章&#xff1a;迭代器、生成器和经典协程 当我在我的程序中看到模式时&#xff0c;我认为这是一个麻烦的迹象。程序的形状应该只反映它需要解决的问题。代码中的任何其他规律性对我来说都是一个迹象&#xff0c;至少对我来说&#xff0c;这表…

【数据可视化】Echarts中的其它图表

个人主页 &#xff1a; zxctscl 如有转载请先通知 文章目录 1. 前言2. 绘制散点图2.1 绘制基本散点图2.2 绘制两个序列的散点图2.3 绘制带涟漪特效的散点图 3. 绘制气泡图3.1 绘制标准气泡图3.2 绘制各国人均寿命与GDP气泡图3.3 绘制城市A、城市B、城市C三个城市空气污染指数气…

Tech Talks技术讲座中文培训-报名学习LPWAN、Matter、蓝牙和Wi-Fi最新开发技能!

Silicon Labs&#xff08;亦称“芯科科技”&#xff09;主办新一轮2024年“亚太区Tech Talks在线技术讲座”即将在5月9日至8月8日&#xff08;中文系列场次&#xff09;&#xff0c;以及4月24日至8月7日&#xff08;英文系列场次&#xff09;正式展开&#xff0c;现正热烈报名中…