网站建设时怎么赚钱的/二级域名注册
mudou网络库思想理解
Reactor与多线程
服务器构建过程中,不仅仅使用一个Reactor,而是使用多个Reactor,每个Reactor执行自己专属的任务,从而提高响应效率。
首先Reactor是一种事件驱动处理模式,其主要通过IO多路复用机制统一监听想要关心的事件,如果关心的事件有响应后,则将该响应事件分发给进程或者线程去处理,从而提高网络服务器的性能。简单可以理解为服务器利用该模式处理多路请求,然后将它们同步的分发给线程或者进程去处理。
其次构建服务器可以使用多个Reactor,从而来提高服务器对事件的响应效率。将负责连接与客户端通信监控分离开,则是一个Reactor专门负责连处理新连接的请求事件,如果发现有新的连接,则将其分发给子Reactor中去监控,另一个Reactor则主要负责监控客户端是否发送了请求或者其他事件,如果有事件触发,则将其交给线程池处理。
主线Reactor处理新连接 ---->交给子Reactor进行监控 ——>事件发生交给线程处理
最后,Reactor需要将待处理的任务交付给线程或者进程去处理,如果想要使得服务器效率高,肯定要避免线程或者进程的频繁的创建销毁,这样会占用服务器的性能。所以构建线程池与Reactor配合,有助于减少性能消耗。
任务线程池的主要作用则是分配独立的线程去执行Reactor中需要处理的任务,最后将处理好的数据交给Reactor线程,让其完成对客户端的响应。
One Loop Per One Thread
主Reactor负责获取连接,获取新连接后,将新连接分发给子Reactor进行网络通信的事件处理。子Reactor监控各个描述符下的读写等事件,当事件响应的时候分发给线程池中的线程去处理。
主要思想是将某一事件所有的操作放在一个线程中进行,即一个线程对应着一种事件的处理,而每个 Reactor都可以使用线程池让其为自己服务,从而可以并发的实现请求的响应。(每个线程与一个独立的事件循环绑定)
核心思想分析
- 事件驱动
- 每个线程都绑定一个事件循环,处理一系列非阻塞的IO事件
- 事件循环,则是通过事件队列接收事件,同事根据事件类型和回调函数执行该事件对应的操作
- 线程与事件绑定
- 线程间独立运行自己的事件循环,而不会与其他线程共享事件循环
- 这样的好处在于,避免了线程竞争,从而提高并发效率
- 非阻塞I/O
- 事件循环的过程中,I/O操作都是非阻塞的,这样一来,线程就不会因为等待I/O操作,而阻塞等待
- 实现一个线程在同一时间内,可以处理多个I/O请求,从而提高系统的吞吐量
- 任务调度与并发
- 任务被分发到不同的线程,各个线程可以独立处理自己的任务序列
- 通过该方式,可以借助负载均衡机制,确保各个线程的工作量均衡,从而防止某个线程过载。
- 编程简化
- 一个线程对应一个事件循环,所以并发程序的设计过程中,无需考虑线程同步与锁的机制
- 只需要关注如何处理事件以及回调函数即可
一个线程绑定的事件在服务器中通常都是I/O事件
- 连接事件
- 建立连接:客户端尝试连接服务器的时候,服务器的监听线程会收到一个连接建立的事件(Accept)。
- 服务器接收这个连接后,将其分配一个工作线程去处理。(在该网络库的思想中,服务器接收连接后,会将其交给子Reactor监控,子Reactor监控到事件发生后,再从线程池中调取线程去执行)
- 读事件
- 数据到达:客户端发送请求数据到达服务器的时候,服务器的线程收到一个读事件,此时监控读事件的Reactor开始响应。从线程池中调用线程去读取数据,解析HTTP请求,并根据请求的内容做出对应处理
- 写事件
- 数据可写事件:服务器准备好响应数据,并准备将该响应数据发送给客户端的时候,服务器此时会触发写事件,表示可以将数据写入到客户端的连接中。
- 关闭事件
- 连接关闭事件:客户端或者服务端关闭连接的时候,触发这个关闭事件,服务器需要清理相应的资源,确保连接正常关闭,避免该连接浪费服务器资源。
项目改进架构思路
服务器架构通过多线程和事件驱动的架构来高效的处理大量并发请求。服务器同时采用非阻塞I/O模式,避免了阻塞操作带来的性能瓶颈,从而让服务器可以高效的处理大量并发请求。
主要模块功能逻辑
Main Reactor
- 初始化
- 创建EventLoop实例
- 创建并初始化Acceptor,设置监听端口和回调函数
- 接受新连接
- Acceptor中,监听新连接请求
- 使用accept系统调用,同时调用回调函数,为新连接进行对应封装
- 分发新连接
- 主Reactor将新连接分配给Reactor,创建Channel对象管理连接
Sub Reactor
- 初始化
- 创建EventLoop对象
- 创建独立线程去运行EventLoop(一个线程一个Reactor思想)
- 处理I/O事件
- EventLoop中通过EPOLL等待关心事件发生
- 将发生的事件分配给Channel对象
- 事件处理
- Channel根据事件的类型,调用注册的回调函数
- 读事件处理:读取数据并解析HTTP请求
- 写事件处理:发送HTTP响应
Epoller逻辑
- 初始化
- 创建EPOLL实例
- 管理文件描述符
- 添加、更新和删除文件描述符
- 等待监控事件发生
- 利用epoll_wait 等待事件的发生
HttpServer逻辑
- 初始化
- 创建HttpServer实例,同时继承TcpServer的功能
- 注册HTTP请求处理函数
- 处理HTTP请求
- 解析HTTP请求,生成HttpRequsest对象
- 根据请求的路径调用相应的处理函数
- 生成并发送响应
- 调用处理函数后生成HttpResponse对象
- 将响应转化为字符串的形式发送给客户端
Main逻辑
- 注册处理函数
- 注册URL路径以及对应的处理函数
- 处理具体业务逻辑
- 根据具体的需求,处理HTTP请求并生成响应
代码架构设计
Server
#ifndef SERVER_HPP
#define SERVER_HPP#include <vector>
#include <functional>
#include <memory>
#include <sys/epoll.h>
#include <unistd.h>class Channel;
class EventLoop;class Epoller {
private:int _epollFd;std::vector<epoll_event> _events;public:Epoller();~Epoller();void UpdateChannel(Channel* channel);void RemoveChannel(Channel* channel);void Poll(std::vector<Channel*>& activeChannels);
};class Channel {
private:EventLoop* _loop;const int _fd;uint32_t _events;uint32_t _revents;std::function<void()> _readCallback;std::function<void()> _writeCallback;public:Channel(EventLoop* loop, int fd);void SetReadCallback(const std::function<void()>& cb);void SetWriteCallback(const std::function<void()>& cb);void EnableReading();void EnableWriting();void DisableWriting();void DisableAll();void Remove();void HandleEvent();void Update();int Fd() const;uint32_t Events() const;uint32_t Revents() const;void SetRevents(uint32_t revents);
};class EventLoop {
private:bool _quit;std::vector<Channel*> _activeChannels;Epoller _poller;public:EventLoop();void Loop();void Quit();void UpdateChannel(Channel* channel);void RemoveChannel(Channel* channel);
};class Acceptor {
private:EventLoop* _loop;int _listenFd;std::function<void(int)> _newConnectionCallback;public:Acceptor(EventLoop* loop, int port);void SetAcceptCallback(const std::function<void(int)>& cb);void Listen();void HandleRead();
};class SubReactor {
private:EventLoop _loop;std::thread _thread;public:SubReactor();void Run();EventLoop* GetLoop();void Join();
};class MainReactor {
private:EventLoop _loop;Acceptor _acceptor;std::vector<SubReactor*> _subReactors;int _nextReactor;public:MainReactor(int port, int subReactorCount);void NewConnection(int fd);void Run();void JoinSubReactors();
};#endif // SERVER_HPP
HTTP
#ifndef HTTP_HPP
#define HTTP_HPP#include "server.hpp"
#include <unordered_map>
#include <functional>
#include <string>class HttpRequest {
public:std::string _method;std::string _path;std::string _version;std::unordered_map<std::string, std::string> _params;std::unordered_map<std::string, std::string> _headers;std::string _body;// 解析请求
};class HttpResponse {
public:int _status;std::unordered_map<std::string, std::string> _headers;std::string _body;void SetContent(const std::string& content, const std::string& type) {_body = content;_headers["Content-Type"] = type;}// 响应
};class HttpServer : public TcpServer {
private:std::unordered_map<std::string, std::function<void(const HttpRequest&, HttpResponse*)>> _handlers;public:HttpServer(int port);void RegisterHandler(const std::string& path, const std::function<void(const HttpRequest&, HttpResponse*)>& handler);void OnMessage(const PtrConnection& conn, const std::string& message);
};#endif // HTTP_HPP
main
#include "http.hpp"#define WWWROOT "./wwwroot/"int main() {HttpServer server(8888);server.Start();return 0;
}
细节问题梳理
Reactor、Channel|、epoll三者结合
多Reactor模型中三者结合分析
- 每个Reactor都拥有自己的epoll实例:具体也就是每个EventLoop(Reactor)都拥有自己属于自己的epoll实例来管理文件描述符和就绪事件
- 每个Channel对象与一个文件描述符和一个Reactor(EventLoop)关联:新连接到来时,主Reactor接受新连接请求后,将文件描述符分配给子Reactor,子Reactor创建一个Channel对象来管理文件描述符
- 事件循环独立运行:每个EventLoop都是独立运行,用于管理文件描述符上关心的事件
新连接创建后其文件描述符作用
- 主Reactor接收新连接后,accept会返回这个连接的文件描述符,然后将其分发给对应的子Reactor中
- 子Reactor管理连接:Channel类负责将文件描述符上的(读写)事件通知到对应的处理函数
进程与线程关系梳理/新连接文件描述符管理问题
- 首先,服务器启动后作为一个进程运行,多个Reactor则是该进程下的线程
- 主Reactor和子Reactor都是在服务器下作为线程执行
- 每个Reactor线程有自己的文件描述符,管理客户端连接(自己需要关心的特定事件)
- 新连接到来后,内核又会为新连接创建一个新的文件描述符
- 主Reactor又会将这个新获取的文件描述符分发给子Reactor中进行管理和处理
线程池和和任务队列的处理
- 主Reactor接收新连接后,将新连接分发给子Reactor中进行管理和处理
- 子Reactor处理I/O事件后,将其放入任务队列
- 线程池中的线程取出任务并执行任务
- 线程池与事件循环放在一起,子Reactor线程将任务交给线程池处理即可
请求到响应流程分析
- 服务器初始化
- 监听端口;设置线程数量(Reactor数量)注册处理函数
- 启动服务器接口
- 接收新连接
- 主Reactor监听新连接,新连接到达后通过NewConnetion方法将连接分发给从Reactor中进行管理
- 分发连接
- 主Reactor借助LoopThreadPool将新连接交给子Reactor中的EventLoop中进行处理
- 处理请求
- 子Reactor线程的EventLoop处理分配到的连接
- 读取请求数据,同时将其解析为HttpRequest对象
- 调用注册的处理函数对请求进行处理
- 生成响应
- 处理数据,根据传入的请求,生成HttpResponse对象,同时设置响应内容
- 发送响应
- 将生成的响应,转换为字符串格式,发送给客户端
- 关闭连接
- 处理请求和响应后,将连接放入到连接池中备用
相关文章:

HTTPServer改进思路2(mudou库核心思想融入)
mudou网络库思想理解 Reactor与多线程 服务器构建过程中,不仅仅使用一个Reactor,而是使用多个Reactor,每个Reactor执行自己专属的任务,从而提高响应效率。 首先Reactor是一种事件驱动处理模式,其主要通过IO多路复用…...

Kubernetes Secret 详解
Kubernetes Secret 是一种用于存储和管理敏感信息的对象,如密码、OAuth 令牌和 SSH 密钥等。使用 Secret 可以避免将机密数据直接放在 Pod 规约或容器镜像中,从而增加了应用程序的安全性。 Secret 的类型 Kubernetes 支持多种类型的 Secret,包括: Opaque:默认的…...

docker笔记4-部署
docker笔记4-部署 一、部署nginx二、部署Tomcat三、部署ESKibana3.1 部署ES3.2 部署kibana 一、部署nginx docker search nginx #搜索nginx的最新版本docker pull nginx #这里可以指定nginx版本,如果不指定,那么就拉取最新版本latestdocker run -d --na…...

有监督学习基础
基本概念 给定输入有为(x,y),其中x表示学习特征,y表示输出,m表示输入总数,有监督学习旨在根据输入建立能够预测可能输出的模型,大致可以分为回归和分类两种,代表可能输出是无限的或…...

揭开 AI 绘画提示词的神秘密码!
前言 ** 揭秘AI 绘画 ** 提示词的神秘密码 亲爱的朋友们,今天我们要一起探索 AI 绘画世界中那神秘的“密码”——提示词。 在 AI 绘画的奇妙领域里,提示词就像是一把神奇的钥匙,能够开启无尽的创意之门。它是我们与 AI 进行心灵对话的桥…...

macOS 10.15中屏蔽Microsoft Edge浏览器的更新提示
文章目录 1.效果对比2.安装描述文件3.停用描述文件4.高级操作(可选)参考文献 最近在macOS10.15系统,打开Microsoft Edge浏览器,每次打开都有个烦人的提示“ 要获取将来的 microsoft edge 更新,需要 macos 10.15 或更高…...

Qt 实战(3)数据类型 | 3.2、QVariant
文章目录 一、QVariant1、存储数据1.1、存储Qt内置数据1.2、存储自定义数据 2、获取数据3、判断数据类型4、清空数据5、总结 前言: QVariant是Qt框架中一个非常强大且灵活的类,它提供了一种通用的方式来存储和转换几乎任何类型的数据。无论是基本数据类型…...

Docker中安装的postgresql14在启用vector扩展的时候,找不到该扩展的控制文件。
ERROR: could not open extension control file “/usr/share/postgresql/14/extension/vector.control”: No such file or directory 进入容器 docker exec -it CONTAINER ID /bin/bash 1.更新 apt-get apt-get update 2.安装插件 #不同版本对应修改数字即可 apt-get i…...

JS防抖和节流
一、防抖和节流的适用场景 防抖(Debounce): 适合在输入框输入时的实时搜索、窗口大小调整时的resize事件等。节流(Throttle): 适合如页面滚动时的scroll事件、按钮点击时的请求发送等需要控制频率的场景。 …...

OpenWrt 为软件包和docker空间扩容
参考资料 【openwrt折腾日记】解决openwrt固件刷入后磁盘空间默认小的问题,关联openwrt磁盘扩容空间扩容【openwrt分区扩容】轻松解决空间可用不足的尴尬丨老李一瓶奶油的YouTube 划分空间 参考一瓶奶油的YouTube 系统 -> 磁盘管理 -> 磁盘 -> 修改 格…...

重要的工作任务,怎么在电脑桌面设置倒计时?
在日常工作中,我们总是面临着众多工作任务,如何高效地管理和完成这些任务成为了每个职场人的必备技能。为任务设置倒计时,不仅能让我们清晰地看到任务的先后顺序,还能帮助我们更好地把握时间,提高工作效率。想象一下&a…...

Failed to build get_cli:get:的解决方案
项目场景: 今天安装Getx命令行的时候,输入这面文档报了一个错: dart pub global activate get_cli 问题描述 提示:这里描述项目中遇到的问题: 例如:数据传输过程中数据不时出现丢失的情况,偶尔…...

短视频矩阵源码技术分享
在当今数字媒体时代,短视频已成为吸引观众和传递信息的重要手段。对于开发者而言,掌握短视频矩阵源码技术不仅是提升自身技能的需要,更是把握行业发展趋势的必然选择。本文将深入探讨短视频矩阵源码的关键技术要点及其实现方法,帮…...

轮播图自定义内容
官网:Swiper演示 - Swiper中文网 下载: npm i swiper Vue3示例代码: <template><div class"swiper mySwiper"><div class"swiper-wrapper"><div class"swiper-slide"><div>…...

大数据-44 Redis 慢查询日志 监视器 慢查询测试学习
点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…...

Istio_01_Istio初识
文章目录 IstioService Mesh Istio Istio: 以服务网格形态用于服务治理的开放平台和基础设施 本质: 以非侵入式治理服务之间的访问和调用服务治理: 流量管理、可观测性、安全性可同时管理多类基础设施(多种网络方案) 如: Istio和Kubernetes架构的结合 Istio通过Kubernetes的域…...

leetcode日记(47)螺旋矩阵Ⅱ
这题思路不难,就是找规律太难了。 我首先的思路是一行一行来,根据规律填入下一行的数组,第i行是由前i个数字(n-2*i)个增序数列后i个数字组成,后来觉得太难找规律了就换了一种思路。 思路大致是先计算出需…...

centos系统mysql主从复制(一主一从)
文章目录 mysql80主从复制(一主一从)一、环境二、服务器master1操作1.开启二进制日志2. 创建复制用户3. 服务器 slave1操作4. 在主数据库中添加数据 mysql80主从复制(一主一从) 一、环境 准备两台服务器,都进行以下操…...

IEDA怎么把springboot项目 启动多个
利用Idea提供的Edit Configurations配置应用参数。 点击Modify Options进行添加应用参数: 确保这里勾选...

Vue 3项目安装Element-Plus
Element Plus 是一个基于 Vue 3 的现代前端UI框架,它旨在提升开发体验,并为开发者提供高效、优雅的组件。如果你正在使用 Vue 3 进行项目开发,那么安装和集成 Element Plus 是一个不错的选择。在本文中,博主将详细介绍如何在 Vue …...

Git下载安装
一、介绍 Git是一个分布式版本控制系统,最初由Linus Torvalds创建,用于管理和跟踪代码的变化。它可以轻松地处理个人项目和大型团队项目的版本控制需求。 Git的主要特点包括: 分布式:每个开发者都可以拥有自己的本地仓库&#x…...

linux中的目录操作函数
参考 【Linux系统编程】Linux 文件系统探究:深入理解 struct dirent、DIR 和 struct stat结构 stat函数 C标准库提供了访问linux的目录的函数接口现对目录的操作。 一、libc接口 libc访问目录的流程为:打开目录,访问目录,关闭目…...

JSON 文件第一段飘红
问题 原因 这个问题通常发生在尝试用 ESLint 去解析 JSON 文件时。ESLint 主要设计用于检查 JavaScript 代码的语法和风格,而JSON是一种数据交换格式,不包含 JavaScript 的逻辑结构,如函数、变量声明等。 解释报错原因 当ESLint遇到它不能识…...

go使用gjson操作json数据
gjson使用 gjson介绍安装gjson库解析 JSON 字符串路径语法复杂查询遍历和修改结论 gjson介绍 gjson 是一个 Go 语言库,用于快速解析 JSON 数据。它提供了非常简洁的 API 来查询 JSON 数据,无需预先定义 Go 结构体或映射(map)来匹…...

Mac 下华为鸿蒙 :DevEco Studio 开发工具下载
1.登录:华为开发者中心--开发--下载工具DevEco Studio 2.下载完成后 ,安装,并创建一个新项目。 3.Tools --点击SDK Manager 下载SDK: 如果报:淘宝镜像源错误: npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_H…...

C进阶—动态内存管理
这里写目录标题 动态内存分配的原因动态内存函数mallocfreecallocrealloc C/C内存开辟柔性数组柔性数组特点 动态内存分配的原因 常见的内存开辟方式: int a 10;//在栈空间上开辟4个字节 char arr[10] {0};//在栈空间上开辟连续的10个字节上述开辟的空间问题&am…...

QT表格显示MYSQL数据库源码分析(七)
一. 连接MySQL数据库 首先,创建了一个QSqlDatabase对象,并设置数据库类型为"QMYSQL"。然后,它设置了数据库的主机名,端口号,数据库名,用户名和密码。最后,尝试打开数据库连接&#x…...

excel系列(三) - 利用 easyexcel 快速实现 excel 文件导入导出
一、介绍 在上篇文章中,我们介绍了 easypoi 工具实现 excel 文件的导入导出。 本篇我们继续深入介绍另一款更优秀的 excel 工具库:easyexcel 。 二、easyexcel easyexcel 是阿里巴巴开源的一款 excel 解析工具,底层逻辑也是基于 apache p…...

探索前后端数据传输模式:Java、Go与Python的实践20240719
深入解析前后端数据传输:Java、Go与Python的实践 引言 在当今的互联网时代,用户对Web应用的性能和交互体验有着越来越高的要求。无论是信息展示型网站还是复杂的企业应用,前后端数据传输的效率和模式选择都至关重要。本文将深入探讨三种主流…...

【YashanDB知识库】yac修改参数后关闭数据库hang住
【标题】yac修改参数后关闭数据库hang住 【问题分类】性能优化 【关键词】YashanDB, yac, shutdown hang 【问题描述】修改yac参数后执行shutdown immediate,数据库hang住。 【问题原因分析】 Shutdown操作时,线程在获取gInstance->trigger->s…...