Linux_网络项目_WEB服务器 处理服务器写入失败后sigpipe信号导致服务器崩溃退出问题,引入线程池缓解大量请求,服务器组件化重构,在线计算机业务测试

文章目录

  • 1. 处理服务器写入管道出错
  • 2. 引入线程池缓解大量请求导致服务器崩溃
    • 设计线程任务类
    • 单例线程池组件设计
  • 3.代码位置
  • 4. 在线计算机业务运行截图

1. 处理服务器写入管道出错

经过测试,服务器在读取报文时如果出错可以选择直接关闭这个TCP里链接来节省资源。这个问题好解决不在赘述

此外如果服务器使用CGI时,向管道写入数据失败时,服务器进程会收到sigpipe信号直接崩溃。所以这里选择直接忽视这个信号。

class HttpSever
{
private:int port;TcpSever *tcp_sever;bool states; // 标记服务器运行状态void InitSever(){// 信号SIGPIPE需要进行忽略,防止服务器写入管道时失败服务器崩溃signal(SIGPIPE, SIG_IGN);tcp_sever = TcpSever::GetInstance(port);}public:HttpSever(int _port = PORT){port = _port;tcp_sever = nullptr;states = true;InitSever();}~HttpSever() {}void Loop(){LOG(INFO, "---http sever loop begin---");int listen_socket = tcp_sever->GetLinstenSocket();while (states != false){struct sockaddr_in client; // 客户端信息socklen_t len = sizeof(client);int sock = accept(listen_socket, (struct sockaddr *)&client, &len);if (sock < 0){// 套接字监听失败continue;}LOG(INFO, "get a new link");int *_sock = new int(sock);pthread_t tid = 0;pthread_create(&tid, nullptr, Entrance::HanderReq, _sock);pthread_detach(tid); // 线程分离}}
};

2. 引入线程池缓解大量请求导致服务器崩溃

设计线程任务类

#pragma once#include <iostream>
#include "../Protocol.hpp"// 设计线程任务队列
class Task
{
private:int sock;CallBack callback; // 设置回调
public:Task() {}Task(int _sock){sock = _sock;}void ProcessOn(){callback(sock);}
};

服务器在收到链接时不创建线程,而是构建线程任务,然后将线程任务放入到线程任务队列上,最后线程池从任务队列上拿去任务处理即可,线程拿到任务后,通过任务里的CallBack回调函数执行不同的任务

线程任务CallBack设计紧贴前面重构前的代码,将Entrance类更改成CallBack即可,这里设计仿函数,线程回调函数通过()直接访问解析请求函数

// 线程工作入口
class CallBack
{
public:void operator()(int sock)//仿函数{HanderReq(sock);}// 处理HTTP请求static void HanderReq(int _sock){LOG(INFO, "http request hander begin");EndPoint *endpoint = new EndPoint(_sock);endpoint->ReadRequest();if (endpoint->Stop() != true){LOG(INFO, "recv success! build request begin");endpoint->BuildResponse();endpoint->SendResponse();}else{LOG(WARNING, "recv error! please try again");}delete endpoint;LOG(INFO, "http request hander end");}
};

单例线程池组件设计

ThreadPool

#pragma once
#include <iostream>
#include "task.hpp"
#include <queue>
#include <pthread.h>
#include "../log/log.hpp"
#define THREAD_NUM 6
// 单例模式
class ThreadPool
{
private:// 生产者消费者模型std::queue<Task> task_queue; // 临界资源int thread_count;            // 线程数bool stop;                   // 线程池是否停止pthread_mutex_t mutex;pthread_cond_t cond;static ThreadPool *instance;bool init_threadPool() // 初始化线程池{for (int i = 0; i < thread_count; i++){pthread_t thread_id;if (0 != pthread_create(&thread_id, NULL, thread_routine, this)){// 创建线程失败LOG(FATAL, "init threadpool error!");return false;}}LOG(INFO, "http sever init threadpool success");return true;}static void *thread_routine(void *args) // 线程执行函数 static 删除类的this指针,对象通过线程的参数传递{ThreadPool *pool = (ThreadPool *)args;while (!pool->stop){Task task;pthread_mutex_lock(&pool->mutex);while (pool->task_queue.empty()) // while 不能换成if{pool->thread_wait(); // 线程唤醒后一定占有互斥锁}task = pool->task_queue.front();pool->task_queue.pop();pthread_mutex_unlock(&pool->mutex);task.ProcessOn();}return NULL;}void thread_wait() // 任务队列无任务,线程休眠{pthread_cond_wait(&cond, &mutex);}void thread_wakeup() // 任务队列有任务,线程唤醒{pthread_cond_signal(&cond); // 唤醒一个线程即可}ThreadPool(int thread_num = THREAD_NUM){thread_count = thread_num;stop = false;pthread_mutex_init(&mutex, nullptr);pthread_cond_init(&cond, nullptr);init_threadPool();}ThreadPool(const ThreadPool &) = delete;public:static ThreadPool *GetInstance(){static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; // 静态锁直接初始化,不需要释放if (instance == nullptr){pthread_mutex_lock(&lock);if (instance == nullptr){instance = new ThreadPool();}pthread_mutex_unlock(&lock);}return instance;}~ThreadPool(){pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);}void push_task(const Task &task){pthread_mutex_lock(&mutex);task_queue.push(task);pthread_mutex_unlock(&mutex);thread_wakeup();}bool is_stop(){return stop;}
};ThreadPool *ThreadPool::instance = nullptr;

HttpSever函数更换为线程池同时组件化

#pragma once
#include "./TcpSever/TcpSever.hpp"
#include "Protocol.hpp"
#include "./log/log.hpp"
#include <signal.h>
#include <pthread.h>
#include "./ThreadPool/task.hpp"
#include "./ThreadPool/threadpool.hpp"
#define PORT 8080class HttpSever
{
private:int port;TcpSever *tcp_sever;bool states; // 标记服务器运行状态ThreadPool threadpool;void InitSever(){// 信号SIGPIPE需要进行忽略,防止服务器写入管道时失败服务器崩溃signal(SIGPIPE, SIG_IGN);tcp_sever = TcpSever::GetInstance(port);}public:HttpSever(int _port = PORT){port = _port;tcp_sever = nullptr;states = true;InitSever();}~HttpSever() {}void Loop(){LOG(INFO, "---http sever loop begin---");int listen_socket = tcp_sever->GetLinstenSocket();while (states != false){struct sockaddr_in client; // 客户端信息socklen_t len = sizeof(client);int sock = accept(listen_socket, (struct sockaddr *)&client, &len);if (sock < 0){// 套接字监听失败continue;}LOG(INFO, "get a new link");// 构建任务Task task(sock);threadpool.push_task(task);}}
};

测试运行结果如下:线程池创建6个线程,初始化线程池正确。同时用户报文发送错误,日志级别WARING级别
在这里插入图片描述

3.代码位置

Github
Gitee

4. 在线计算机业务运行截图

在这里插入图片描述
在这里插入图片描述
除0错误等其他错误会导致子进程错误退出,服务器捕捉到后跳转到错误页面即404.html
在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

langchain+chatglm3+BGE+Faiss Linux环境安装依赖

前言 本篇默认读者已经看过之前windows版本&#xff0c;代码就不赘述&#xff0c;本次讲述是linux环境配置 超短代码实现&#xff01;&#xff01;基于langchainchatglm3BGEFaiss创建拥有自己知识库的大语言模型(准智能体)本人python版本3.11.0&#xff08;windows环境篇&…

Find My游戏机|苹果Find My技术与游戏机结合,智能防丢,全球定位

游戏机&#xff0c;又名电子游乐器是使用游戏软件进行玩乐的机器。依照进行游戏的方式的不同&#xff0c;又分为家用游戏机及掌上游戏机。游戏机也可以说是属于电脑的一种&#xff0c;电子游戏机针对影像、音效与操作机能进行特别的强化&#xff0c;也有各种的软件和硬件可供安…

Scala第四章节(分支结构的格式和用法、for循环和while循环、控制跳转语句以及循环案例)

Scala第四章节 章节目标 掌握分支结构的格式和用法掌握for循环和while循环的格式和用法掌握控制跳转语句的用法掌握循环案例理解do.while循环的格式和用法 1. 流程控制结构 1.1 概述 在实际开发中, 我们要编写成千上万行代码, 代码的顺序不同, 执行结果肯定也会受到一些影响…

2.26回顾章节主体线索脉络,课程要求(评分)

3)翻译程序、汇编程序、编译程序、解释程序有什么差别&#xff1f;各自的特性是什么&#xff1f; 翻译程序是指把高级语言源程序翻译成机器语言程序&#xff08;目标代码&#xff09;的软件。 翻译程序有两种&#xff1a;一种是编译程序&#xff0c;它将高级语言源程序一次全部…

紫色星空月亮404网页模板源码

紫色星空月亮404网页模板源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面 源码下载 紫色星空月亮404网页模板源码

zookeeper快速入门二:zookeeper基本概念

本文是zookeeper系列之快速入门中的第二篇&#xff0c;欢迎大家观看与指出不足。 目录 一、zookeeper的存储结构 二、什么是znode 三、znode节点的四种类型 四、权限控制ACL&#xff08;Access Control List&#xff09; 五、事件监听watcher 一、zookeeper的存储结构 z…

练习8 Web [GYCTF2020]Blacklist

这道题其实不是堆叠注入&#xff0c;但是我在联合查询无效后&#xff0c;试了一下堆叠&#xff0c;最后一步发现被过滤的sql语句太多了&#xff0c;完全没法 查阅其他wp的过程[GYCTF2020]Blacklist 1&#xff08;详细做题过程&#xff09; 是用的handler语句&#xff0c;只能用…

控制学习_正弦波无刷直流力矩电机建模、控制带宽讨论与选择

无刷电机通过电子换向器实现定子的磁场旋转&#xff0c;去电刷后使用寿命大幅提升&#xff0c;是现在更流行的选择。三相无刷电机则是无刷电机中比较流行的一款。三相无刷电机的驱动方式有多种&#xff0c;最简单的被称为梯形波驱动、方波驱动或正弦波驱动。而正弦波驱动技术可…

【工具】一键生成动态歌词字幕

那眼神如此熟悉 让人着迷无力抗拒 一次又一次相遇 在眼前却遥不可及 命运总爱淘气 将一切都藏匿 曾有你的回忆 无痕迹 若不是心心相吸 又怎么会一步一步靠近 &#x1f3b5; 董真《思如雪》 下载LRC歌词 https://www.musicenc.com/article/50287.htmlhttp…

这次玩个猛的,复现 2000 年前碳化卷轴

公元79年10月24日&#xff0c;意大利的维苏威火山爆发&#xff0c;一天之内就毁灭了两万多人的庞贝古城。 火山灰掩盖了整座城市&#xff0c;其中有一栋房子存放了各种书籍。直到18世纪&#xff0c;这栋房子才重新被发现&#xff0c;下面是考古学家的建筑复原图。 房子里面的1…

本地用AIGC生成图像与视频

最近AI界最火的话题&#xff0c;当属Sora了。遗憾的是&#xff0c;Sora目前还没开源或提供模型下载&#xff0c;所以没法在本地跑起来。但是&#xff0c;业界有一些开源的图像与视频生成模型。虽然效果上还没那么惊艳&#xff0c;但还是值得我们体验与学习下的。 Stable Diffu…

基于粒子群算法的分布式电源配电网重构优化matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1基本PSO算法原理 4.2配电网重构的目标函数 5.完整工程文件 1.课题概述 基于粒子群算法的分布式电源配电网重构优化。通过Matlab仿真&#xff0c;对比优化前后 1.节点的电压值 2.线路的损耗,这里计…

阿里二面:什么情况会发生Full GC?如何避免频繁Full GC?

阿里二面&#xff1a;什么情况会发生Full GC&#xff1f;如何避免频繁Full GC&#xff1f; Minor GC、Major GC 和 Full GC区别&#xff1f; Minor GC、Major GC和Full GC是垃圾回收中的三个重要概念&#xff0c;它们描述了垃圾回收的不同阶段和范围&#xff1a; Minor GC&am…

【leetcode热题】 分数到小数

给定两个整数&#xff0c;分别表示分数的分子 numerator 和分母 denominator&#xff0c;以 字符串形式返回小数 。 如果小数部分为循环小数&#xff0c;则将循环的部分括在括号内。 如果存在多个答案&#xff0c;只需返回 任意一个 。 对于所有给定的输入&#xff0c;保证 …

【SQL Server】实验七 数据完整性

1 实验目的 掌握实体完整性、参照完整性和用户自定义完整性约束的创建方法。掌握完整性约束的运行检查机制。掌握参照完整性的级联删除和修改方法。掌握正确设计关系模式完整性约束的方法。 2 实验内容 2.1 掌握实体完整性约束的创建和使用方法 创建表时定义由一个属性组成…

【蓝桥杯选拔赛真题38】C++判断数字 第十四届蓝桥杯青少年创意编程大赛 算法思维 C++编程选拔赛真题解析

目录 C判断数字 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、推荐资料 C判断数字 第十四届蓝桥杯青少年创意编程大赛C选拔赛真题 一、题目要求 1、编程实现 给定一个正整数N(100≤N<100000)…

特殊内齿轮加工的另一种选择

内齿轮加工普遍采用插齿或拉削&#xff0c;但对于一些特殊齿廓的内齿轮来说&#xff0c;插齿可能会有一定的困难&#xff0c;或者成本较高。在这种情况下&#xff0c;线切割加工不失为一种不错的选择。那么什么样的零件需要选择这种加工方式呢&#xff1f;一起来看看&#xff1…

【Java】常用类和基础API

文章目录 一、String的特性二、String的内存结构2.1 拼接2.2 new 三、String的常用API-13.1 构造器 四、String的常用API-24.1 常用方法4.2 查找4.3 字符串截取4.4 和字符/字符数组相关4.5 开头与结尾4.6 替换 五、StringBuffer、StringBuilder5.1 StringBuilder、StringBuffer…

【RS422】基于未来科技FT4232HL芯片的多波特率串口通信收发实现

功能简介 串行通信接口常常用于在计算机和低速外部设备之间传输数据。串口通信存在多种标准&#xff0c;以RS422为例&#xff0c;它将数据分成多个位&#xff0c;采用异步通信方式进行传输。   本文基于Xilinx VCU128 FPGA开发板&#xff0c;对RS422串口通信进行学习。   根…

sqlite 常见命令 表结构

在 SQLite 中&#xff0c;将表结构保存为 SQL 具有一定的便捷性和重要性&#xff0c;原因如下 便捷性&#xff1a; 备份和恢复&#xff1a;将表结构保存为 SQL 可以方便地进行备份。如果需要还原或迁移数据库&#xff0c;只需执行保存的 SQL 脚本&#xff0c;就可以重新创建表…