首页 > 其他分享 >负载均衡式在线OJ

负载均衡式在线OJ

时间:2024-09-07 09:51:46浏览次数:10  
标签:负载 return OJ 在线 filename static 模块 const string

个人主页:Lei宝啊 

愿所有美好如期而遇


目录

一、所用技术与开发环境

所用技术

开发环境

二、准备及库的安装

1. 升级gcc   (gcc -v查看gcc版本, 超过7就不用看本条升级gcc)

2. 安装 jsoncpp

3. 安装 cpp-httplib 

4. 安装boost库

5. 安装ctemplate

 三、项目宏观结构

1. leetcode结构

2. 项目宏观结构

3. 编写思路

四、compiler服务设计

1. 日志模块

2. 公共方法模块

3. 编译模块

4. 运行模块

5. 整合模块 

6. 主函数

7. 使用Postman进行调试

五、oj_server服务设计

第一个功能:用户请求的服务器路由功能

第二个功能:完成model,提供对数据的操作

第三个功能:control模块,逻辑控制模块

第四个功能:view模块,进行数据渲染

完成control模块,加入负载均衡 

六、效果演示 


一、所用技术与开发环境

所用技术

  • C++ STL 标准库
  • Boost 准标准库(字符串切割)
  • cpp-httplib 第三方开源网络库
  • ctemplate 第三方开源前端网页渲染库
  • jsoncpp 第三方开源序列化、反序列化库
  • 负载均衡设计
  • 多进程、多线程

开发环境

  • ubuntu 5云服务器
  • vscode

二、准备及库的安装

1. 升级gcc   (gcc -v查看gcc版本, 超过7就不用看本条升级gcc)

对于cpp-httplib库来说,用老的编译器,要么编译不通过,要么运行报错。

安装scl来升级gcc

sudo yum install centos-release-scl scl-utils-build

sudo yum install -y devtoolset-7-gcc devtoolset-7-gcc-c++ (这里的7可以是8或者9)

scl enable devtoolset-7 bash (启动,只在本会话有效)

如果想每次登陆的时候,都是较新的gcc,需要把上面的命令添加到你的~/.bash_profile中

添加:scl enable devtoolset-7 bash

2. 安装 jsoncpp

sudo yum install -y jsoncpp-devel

3. 安装 cpp-httplib 

建议:cpp-httplib 0.7.15, 码云上去找。

4. 安装boost库

sudo apt update 更新软件包

sudo apt install libboost-all-dev(博主是unbuntu)

5. 安装ctemplate

这个资源可以在这里找:https://hub.fastgit.xyz/OlafvdSpek/ctemplate 

接着将资源放到服务器上,执行如下命令

./autogen.sh

./configure

make //编译

make install //安装到系统中 如果报错,加上sudo

 三、项目宏观结构

  1. comm 模块
  2. compiler模块
  3. oj_server模块

1. leetcode结构

本项目只实现了leetcode的题目列表和刷题功能。

2. 项目宏观结构

B/S模式:浏览器-服务器(Browser-Server, B/S)模式

3. 编写思路

先写compiler服务器,接着写oj_server,最后是前端页面设计,直接copy。

四、compiler服务设计

1. 日志模块

其他模块都会引用这个模块,这个模块我们之前的文章有详细代码和讲解,我们这里不多赘述,贴出链接:日志介绍及简单实现

2. 公共方法模块

这个模块可以先直接跳过不看,当后面模块用到这个模块中的方法时返回来看。

这里介绍几个函数:gettimeofday获取时间戳,stat获取文件属性(能获取就能说明文件存在,获取不到就说明文件不存在);C++11及以上版本,支持在atomic头文件中,我们使用atomic_int类型定义的变量,有原子加、原子减、原子比较并交换、原子自增、原子自减等操作。

#pragma once
#include <iostream>
#include <string>
#include <unistd.h>
#include <atomic>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
using namespace std;

namespace ns_commfunc
{
    const string temp = "./temp/";

    // 将文件名变为文件路径,并且添加后缀
    class PathUtil
    {

    public: 
        static string AddSuffix(const string filename, const string suffix)
        {
            string ret = temp + filename + suffix;
            return ret;
        }

        //编译模块
        static string filepath_src(const string& filename)
        {
            return AddSuffix(filename, ".cpp");
        }

        static string filepath_exe(const string& filename)
        {
            return AddSuffix(filename, ".exe");
        }

        static string filepath_stderr(const string& filename)
        {
            return AddSuffix(filename, ".compile_err");
        }

        //运行模块
         static string filepath_stdin(const string& filename)
        {
            return AddSuffix(filename, ".stdin");
        }

        static string filepath_stdout(const string& filename)
        {
            return AddSuffix(filename, ".stdout");
        }

        static string filepath_stderr_runner(const string& filename)
        {
            return AddSuffix(filename, ".stderr");
        }

    
    };

    class TimeUtil
    {
    public:
        static string Gettimeofms()
        {
            struct timeval tv;
            gettimeofday(&tv, nullptr);
            string ret = to_string(tv.tv_sec * 1000 + tv.tv_usec / 1000);

            return ret;
        }
    };

    class FileUtil
    {
    public:

        static bool Isexist_file(const string filename)
        {
            struct stat temp;
            int ret = stat(filename.c_str(), &temp);

            return ret == 0 ? true : false;
        }

        static string UniqueFilename()
        {
            static atomic_uint id(0);
            id++;

            return TimeUtil::Gettimeofms() + "_" + to_string(id);
        }

        static bool WritecodeToFile(const string filename, const string& content)
        {
            ofstream out(filename);
            if(!out.is_open()) return false;

            out.write(content.c_str(), content.size());
            return true;
        }

        static bool Readfile(const string& filename, string& content, bool keep)
        {
            ifstream in(filename);
            if(!in.is_open()) return false;

            string line;
            while(getline(in, line))
            {
                content += line;
                content += keep ? "\n" : "";
            }

            return true;
        }

        static string CodeTodesc(int status, string filename)
        {
            string ret = "";

            switch (status)
            {
            case 0:
                ret = "运行正常";
                break;
            case -1:
                ret = "代码为空";
                break;
            case -2:
                ret = "未知错误";
                break;
            case -3:
                // ret = "编译错误";
                FileUtil::Readfile(filename, ret, true);
                break;
            case 24:
                ret = "超时";
            default:
                ret = "待填充";
                break;
            }

            return ret;
        }


    };
}

3. 编译模块

1. 创建编译类Compile,封装在命名空间ns_compile中:

namespace ns_compile
{
    class Compile
    {
    private:
    public:
        Compile()
        {}

        ~Compile()
        {}
    };
}

2. 写一个方法,完成编译功能,那么这个方法的参数和返回值我们如何设置?我们要明白,外面有一个整合模块来接收请求,并且从请求中提取代码并解析成字符串形成源文件,也就是说,我们的编译方法,参数为这个文件名,也就是字符串类型。返回值可以设置为bool类型,表示是否编译成功。

       /*
            @return val: 编译结果是否成功
            @pragma    : 文件名
        */
        static bool compile(const string& filename)
        {}

接下来就可以创建子进程,按照我们上面的逻辑写代码了:

其中,我们在comm文件夹下,创建了一个公共方法文件,这个文件中我们写不同模块需要使用的公共方法,这些方法封在ns_commfunc中的不同类中,有Path类,这个类中的方法用来形成文件路径;文件类,这个类中的方法用来对文件进行操作。

static bool compile(const string& filename)
        {
            int id = fork();
            if(id < 0)
            {
                Log(ERROR, "子进程创建失败");
                return false;
            } 
            else if(id == 0)
            {
                //子进程

                //重定向
                umask(0);
                i

标签:负载,return,OJ,在线,filename,static,模块,const,string
From: https://blog.csdn.net/m0_74824254/article/details/141898224

相关文章

  • 基于java ssm jsp mysql在线心理评测与咨询系统毕业设计项目实战
    前言......
  • 基于nodejs+vue电商网站在线客服[程序+论文+开题] 计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展和电子商务的普及,电商网站已成为消费者购物的主要渠道之一。在这一背景下,用户对于购物体验的需求日益提升,其中,高效、便捷的客服服......
  • springboot古典舞在线交流平台的设计与实现
      运行环境环境说明:开发语言:java框架:springboot,vueJDK版本:JDK1.8数据库:mysql5.7+(推荐5.7,8.0也可以)数据库工具:Navicat11+开发软件:idea/eclipse(推荐idea)Maven包:Maven3.3.9+系统的实现用户功能模块的实现系统主界面用户进入本系统可查看系统信息,主要包......
  • 大数据新视界--大数据大厂之MySQL数据库课程设计:MySQL集群架构负载均衡故障排除与解决
           ......
  • C++vector类相关OJ练习
    个人主页:C++忠实粉丝欢迎点赞......
  • 【机器学习实战】用随机森林预测在线购物者的购买意向
    一、数据介绍1、背景与来源本次数据集来自UCI机器学习库中的在线购物者购买意向数据集。该数据集是从某个在线零售商数据库中随机收集的。数据都来自于一年期间的不同用户,以避免对特定活动、特殊日子、用户档案或时间段的任何倾向性。通过收集用户行为数据、选择关键特征、......
  • 基于Python+Vue的在线家具家居销售购物商城系统
    文末获取资源,收藏关注不迷路文章目录一、项目介绍二、主要使用技术三、研究内容四、核心代码五、文章目录一、项目介绍该HomeF家居系统采用B/S架构、前后端分离以及MVC模型进行设计,并采用Python语言以及django框架进行开发。本系统主要设计并完成了用户注册、登......
  • D20 kubernetes 工作负载资源对象-Deployment
    1、Deployment简介 Deployment是kubernetes中最常用的工作负载资源,具有以下特点和功能-副本管理:确保指定数量的pod副本在集群中运行。如果pod副本数小于期望值,则会自动创建pod;如果pod的副本数多余期望值,则删除多余的pod-滚动更新:采用滚动更新策略,逐步进行新旧版本pod的替换......
  • 基础篇:到底应该怎么理解“平均负载”
    root@Test-MySQL:/home/zoom/test#uptime08:41:38up3days,5:40,2users,loadaverage:0.00,0.03,0.02我相信你对前⾯的⼏列⽐较熟悉,它们分别是当前时间、系统运⾏时间以及正在登录⽤户数。⽽最后三个数字呢,依次则是过去1分钟、5分钟、15分钟的平均负载(LoadAvera......
  • postgresql java jdbc 负载均衡解决方案
    在PostgreSQL和JavaJDBC的环境中实现负载均衡,可以有效提升数据库性能和可用性。以下是一个基于PostgreSQL和JavaJDBC的负载均衡解决方案,包括主从复制、连接池、以及负载均衡器的集成。1.PostgreSQL主从复制PostgreSQL的主从复制是实现读写分离的重要前提。主节点(Ma......