电影网站怎么做seo,怎样建设单位网站,wordpress 购物模板,django做的购物网站mudou网络库思想理解
Reactor与多线程
服务器构建过程中#xff0c;不仅仅使用一个Reactor#xff0c;而是使用多个Reactor#xff0c;每个Reactor执行自己专属的任务#xff0c;从而提高响应效率。
首先Reactor是一种事件驱动处理模式#xff0c;其主要通过IO多路复用…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.hclass Channel;
class EventLoop;class Epoller {
private:int _epollFd;std::vectorepoll_event _events;public:Epoller();~Epoller();void UpdateChannel(Channel* channel);void RemoveChannel(Channel* channel);void Poll(std::vectorChannel* activeChannels);
};class Channel {
private:EventLoop* _loop;const int _fd;uint32_t _events;uint32_t _revents;std::functionvoid() _readCallback;std::functionvoid() _writeCallback;public:Channel(EventLoop* loop, int fd);void SetReadCallback(const std::functionvoid() cb);void SetWriteCallback(const std::functionvoid() 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::vectorChannel* _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::functionvoid(int) _newConnectionCallback;public:Acceptor(EventLoop* loop, int port);void SetAcceptCallback(const std::functionvoid(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::vectorSubReactor* _subReactors;int _nextReactor;public:MainReactor(int port, int subReactorCount);void NewConnection(int fd);void Run();void JoinSubReactors();
};#endif // SERVER_HPPHTTP
#ifndef HTTP_HPP
#define HTTP_HPP#include server.hpp
#include unordered_map
#include functional
#include stringclass HttpRequest {
public:std::string _method;std::string _path;std::string _version;std::unordered_mapstd::string, std::string _params;std::unordered_mapstd::string, std::string _headers;std::string _body;// 解析请求
};class HttpResponse {
public:int _status;std::unordered_mapstd::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_mapstd::string, std::functionvoid(const HttpRequest, HttpResponse*) _handlers;public:HttpServer(int port);void RegisterHandler(const std::string path, const std::functionvoid(const HttpRequest, HttpResponse*) handler);void OnMessage(const PtrConnection conn, const std::string message);
};#endif // HTTP_HPPmain
#include http.hpp#define WWWROOT ./wwwroot/int main() {HttpServer server(8888);server.Start();return 0;
}细节问题梳理
Reactor、Channel|、epoll三者结合 多Reactor模型中三者结合分析 每个Reactor都拥有自己的epoll实例具体也就是每个EventLoopReactor都拥有自己属于自己的epoll实例来管理文件描述符和就绪事件每个Channel对象与一个文件描述符和一个ReactorEventLoop关联新连接到来时主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对象同时设置响应内容发送响应 将生成的响应转换为字符串格式发送给客户端关闭连接 处理请求和响应后将连接放入到连接池中备用