使用libevent实现简单http服务(二)

《使用libevent实现简单http服务(一)》使用libevent实现了一个简单的http服务,但性能比较差,假设处理一个请求需要1ms,单个服务每秒最多也就能够处理1000个请求。为了提高单个服务的处理能力,可以通过多线程并发或多进程并发实现。

多线程源码如下:

#define MAX_THREAD_NUM 2
bool exit_flag = false;

void sigterm(int sig)
{
    fprintf(stdout, "INFO recv term signal !\n");
    exit_flag = true;
}

void http_server_thread(std::shared_ptr<simple_httpserver<simple_listener, simple_processor>> &ptr)
{
    ptr->run();
}

int main(int argc, char **argv)
{
    signal(SIGTERM, sigterm);
    auto listener_ptr = std::make_shared<simple_listener>("0.0.0.0", 8080);
    if (!listener_ptr->start()) {
        fprintf(stderr, "ERROR failed to start listener !\n");
        return -1;
    }
    
    std::vector<std::shared_ptr<simple_processor>> procssors;
    std::vector<std::shared_ptr<simple_httpserver<simple_listener, simple_processor>>> httpservers;
    std::vector<std::shared_ptr<std::thread>> threads;
    int i = 0;
    for (; i < MAX_THREAD_NUM; ++i) {
        auto processor_ptr = std::make_shared<simple_processor>(i);
        auto httpserver_ptr = std::make_shared<simple_httpserver<simple_listener, simple_processor>>(listener_ptr, processor_ptr);
        if (!httpserver_ptr->start()) {
            fprintf(stderr, "ERROR failed to start http server, index : %d !\n", i);
            return -1;
        }
        procssors.push_back(processor_ptr);
        httpservers.push_back(httpserver_ptr);
        auto func = std::bind(http_server_thread, httpserver_ptr);
        auto thread_ptr = std::make_shared<std::thread>(func);
        threads.push_back(thread_ptr);
    }
    
    if (i == MAX_THREAD_NUM) {
        while (!exit_flag) {
            sleep(10);
        }
    }
    
    fprintf(stdout, "INFO before server stop !\n");
    for (auto &httpserver_ptr : httpservers)
        httpserver_ptr->stop();
    fprintf(stdout, "INFO after server stop !\n");
    
    for (auto &thread : threads) {
        if (thread->joinable()) {
            thread->join();
        }
    }
    
    fprintf(stdout, "INFO process exit !\n");
    return 0;
    
}

多进程源码如下:

std::shared_ptr<simple_listener> g_listener_ptr; //监听对象
std::shared_ptr<simple_processor> g_processor_ptr; //请求处理对象
std::shared_ptr<simple_httpserver<simple_listener, simple_processor>> g_httpserver_ptr; //http服务对象
#define MAX_PROCESS_NUM  2
bool exit_flag = false;
pid_t sub_pids[MAX_PROCESS_NUM] = {0};

void sigterm_main(int sig)
{
    fprintf(stdout, "INFO main process %d recv term signal !\n", getpid());
    exit_flag = true;
}

void sigterm(int sig)
{
    fprintf(stdout, "INFO sub process %d recv term signal !\n", getpid());
    if (g_httpserver_ptr.get() != nullptr) {
        fprintf(stdout, "INFO sub process %d httpserver before stop !\n", getpid());
        g_httpserver_ptr->stop();
        fprintf(stdout, "INFO sub process %d httpserver after stop !\n", getpid());
    }
}

int main(int argc, char **argv)
{
    signal(SIGTERM, sigterm_main);
    g_listener_ptr = std::make_shared<simple_listener>("0.0.0.0", 8080);
    if (!g_listener_ptr->start()) {
        fprintf(stderr, "ERROR failed to open listener\n");
        return -1;
    }

    bool main_process = true;
    for (int i = 0; i < MAX_PROCESS_NUM; ++i) {
        pid_t pid = fork();
        if (pid == 0) { //子进程
            signal(SIGTERM, sigterm);
            main_process = false;
            g_processor_ptr = std::make_shared<simple_processor>((int)getpid());
            g_httpserver_ptr = std::make_shared<simple_httpserver<simple_listener, simple_processor>>(g_listener_ptr, g_processor_ptr);
            if (!g_httpserver_ptr->start()) {
                fprintf(stderr, "ERROR failed to start http server\n");
                return -1;
            }
            g_httpserver_ptr->run();
            printf("sub process %d leave\n", getpid());
            return 0;
        }
        else { //记录子进程pid
            sub_pids[i] = pid;
        }
    }

    //主进程等待退出
    if (main_process) {
        while (!exit_flag) {
            sleep(20);
        }

        for (int i = 0; i < MAX_PROCESS_NUM; ++i) {
            kill(sub_pids[i], SIGTERM);
        }

        int status = 0;
        wait(&status);
    }

    printf("process %d leave\n", getpid());
    
	return 0;
}

以上两种方案都可以明显提高单机服务的处理能力。两种方案各有优缺点:对于多进程,安全性较高,但资源共享效率比较低,而多线程则相反。因此对于计算密集型的服务,适合使用多进程,而而对于以资源下载为主的服务,则适合使用多线程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值