0
点赞
收藏
分享

微信扫一扫

数据结构-C语言-排序(3)

写心之所想 2024-07-24 阅读 23

mudou网络库思想理解

Reactor与多线程

服务器构建过程中,不仅仅使用一个Reactor,而是使用多个Reactor,每个Reactor执行自己专属的任务,从而提高响应效率。

首先Reactor是一种事件驱动处理模式,其主要通过IO多路复用机制统一监听想要关心的事件,如果关心的事件有响应后,则将该响应事件分发给进程或者线程去处理,从而提高网络服务器的性能。简单可以理解为服务器利用该模式处理多路请求,然后将它们同步的分发给线程或者进程去处理。

其次构建服务器可以使用多个Reactor,从而来提高服务器对事件的响应效率。将负责连接与客户端通信监控分离开,则是一个Reactor专门负责连处理新连接的请求事件,如果发现有新的连接,则将其分发给子Reactor中去监控,另一个Reactor则主要负责监控客户端是否发送了请求或者其他事件,如果有事件触发,则将其交给线程池处理

最后,Reactor需要将待处理的任务交付给线程或者进程去处理,如果想要使得服务器效率高,肯定要避免线程或者进程的频繁的创建销毁,这样会占用服务器的性能。所以构建线程池与Reactor配合,有助于减少性能消耗

任务线程池的主要作用则是分配独立的线程去执行Reactor中需要处理的任务,最后将处理好的数据交给Reactor线程,让其完成对客户端的响应。

One Loop Per One Thread

主Reactor负责获取连接,获取新连接后,将新连接分发给子Reactor进行网络通信的事件处理。子Reactor监控各个描述符下的读写等事件,当事件响应的时候分发给线程池中的线程去处理。

主要思想是将某一事件所有的操作放在一个线程中进行,即一个线程对应着一种事件的处理,而每个 Reactor都可以使用线程池让其为自己服务,从而可以并发的实现请求的响应。(每个线程与一个独立的事件循环绑定)

项目改进架构思路

服务器架构通过多线程和事件驱动的架构来高效的处理大量并发请求。服务器同时采用非阻塞I/O模式,避免了阻塞操作带来的性能瓶颈,从而让服务器可以高效的处理大量并发请求。

主要模块功能逻辑 

 代码架构设计

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三者结合

 新连接创建后其文件描述符作用

进程与线程关系梳理/新连接文件描述符管理问题 

线程池和和任务队列的处理

 请求到响应流程分析

举报

相关推荐

0 条评论