使用C++构建高性能网络服务

本文介绍了如何使用C++基于epoll和线程池构建高性能网络服务,避免惊群效应并实现异步日志。讨论了线程池替代多进程的优缺点,详细阐述了kingpin框架的架构设计,包括Server和Client的API设计,以及epoll+线程池的网络服务模型。同时,展示了异步日志的实现和相关示例。
摘要由CSDN通过智能技术生成

基于epoll与线程池实现的C++网络库,其中服务端采用线程间共享互斥锁避免惊群效应。详解架构设计、异步日志、支持非阻塞IO的缓冲。阅读时长约20min。

从Nginx说起

Nginx是使用多进程与IO多路复用实现的高性能C++服务端,但是Nginx为什么要使用多进程,而不是多线程呢?

子线程与子进程的主要区别在于子进程有独立的PID与地址空间,独立PID在并发编程时使得信号的处理更加方便,因为信号根据种类不同,作用于线程组时的行为也有很大的不一样。但由于父子进程各自的地址空间是独立的,所以nginx在避免惊群效应时使用了进程锁,分析源代码底层有两种实现:

①基于CAS(Compare and Swap)与共享内存,其中CAS需要CPU硬件支持。②使用fcntl系统调用实现记录锁。

进程锁的实现相对麻烦,以前甚至碰到过fcntl系统调用对记录锁的实现有BUG。

作者尝试使用posix线程库实现线程池以替换多进程,同样可以实现高性能,框架命名为kingpin。

架构设计

对于一个库而言,设计者最开始就要想清楚的是,想要解决的问题、针对的业务场景、怎样设计API?

King

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.1 什么是Herm Herm是一套快速开发高性能网络应用的C++库。比如开发网络游戏、即时通信、流媒体、文件下载、P2P等基于TCP/IP网络应用。 Herm包括三个组件: (1)Utilities 最基础的组件,提供线程、一读一写线程不加锁的ring buffer、二进制消息解析器、支持多态的对象管理器等。 (2)Socket 用面向对象和泛型的方法抽象了TCP/UDP的Socket IOs;抽象了Win32 Select、Linux epoll和FreeBSD kqueue的多路复用API。统一了三者水平模式(Level Triggered)的语义(一套代码在Win32/Linux/FreeBSD运行结果是一样的),Linux上也支持了边缘模式(Edge Triggered)。 (3)Framework 基于Utilities和Socket的简化开发网络应用的框架,抽象出Peer和Session对象。Peer和Session对象以及Framework实现的功能将在第2章介绍。 Herm目前仅支持Linux/Windows/FreeBSD 32bits平台。调用者可以基于不同的需求使用不用的组件。 1.2 最简单的例子 本节给出两个分别用Framework和Socket组件实现的简单TCP Server的例子。所有的例子可以参考examples frameworks和multiplexors目录。 1.2.1 用Framework实现TCP Server 首先,实现一个Listener, class Listener : public Herm::Listener { virtual void Accept(Herm::Session* session) { // 在这里得到一个于客户端通信的Session // 注册用于处理收到的消息的handler // 用Session::Push将数据写到发送buffer,最终数据传给client } }; 实现一个App, class App : public Herm::App { virtual bool Init() { // 1. 创建Network Herm::Network* net = CreateNetwork(); // 2. 创建一个TCP Server Peer,将Listener注册到Peer,进行监听 Herm::Peer* peer = net->CreateTCPServer(addr, new Listener); } }; 1.2.2 用Socket实现TCP Server 用Socket实现TCP Server更灵活,但实现者要做一些额外的工作,比如tcp stream解析,缓冲队列处理等等。 首先实现一个AcceptHandler,处理Client连接, class AcceptHandler : public Herm::EventHandler { virtual int Receive(int) { m_acceptor->Accept(streamHandler->GetStream()); g_reactor->Register(streamHandler, Herm::READ_MASK); ... } private: Herm::Acceptor* m_acceptor; }; 实现StreamHandler, 处理数据收发, class StreamHandler : public Herm::EventHandler { // Handle onle int param on FreeBSD, pls see the example of FreeBSD_tcp_server virtual int Receive(int) { m_stream->Recieve(buf, .......); ..... } private: Herm::Stream* m_stream; }; 最后,在一个线程里把上面Handler执行起来, while (true) g_reactor->Run(); 1.3 Herm地址 https://sourceforge.net/projects/speed/ 1.4 下一章话题 下章将较详细地介绍Framework组件,主要介绍如何用Framework实现真实可用的网络游戏的接入网关Server(gated)和逻辑Server(zoned)。 转这个主要是看代码质量不错. 转自CSDN的herm_lib http://hi.csdn.net/herm_lib
/****************************************************************************** Module: VC-Logger Purpose: 记录程序日志。 1. 把日志信息输出到指定文件 2. 对于 GUI 程序,可以把日志信息发送到指定窗口 3. 对于Console应用程序,可以把日志信息发往标准输出 (std::cout) Desc: 1、功能: -------------------------------------------------------------------------------------- a) 把日志信息输出到指定文件 b) 每日生成一个日志文件 c) 对于 GUI 程序,可以把日志信息发送到指定窗口 d) 对于Console应用程序,可以把日志信息发往标准输出 (std::cout) e) 支持 MBCS / UNICODE,Console / GUI,win32 / x64 程序 f) 支持动态加载和静态加载日志组件 DLL g) 支持 DEBUG/TRACE/INFO/WARN/ERROR/FATAL 等多个日志级别 2、可用性: -------------------------------------------------------------------------------------- a) 简单纯净:不依赖任何程序库或框架 b) 使用接口简单,不需复杂的配置或设置工作 c) 提供 CStaticLogger 和 CDynamicLogger 包装类用于静态或动态加载以及操作日志组件,用户无需关注加载细节 d) 程序如果要记录多个日志文件只需为每个日志文件创建相应的 CStaticLogger 或 CDynamicLogger 对象 e) 只需调用 Log()/Debug()/Trace()/Info()/Warn()/Error()/Fatal() 等方法记录日志 f) 日志记录方法支持可变参数 g) 日志输出格式: 3、性能: -------------------------------------------------------------------------------------- a) 支持多线程同时发送写日志请求 b) 使用单独线程在后台写日志,不影响工作线程的正常执行 c) 采用批处理方式批量记录日志 Usage: 方法一:(静态加载 Logger DLL) -------------------------------------------------------------------------------------- 0. 应用程序包含 StaticLogger.h 头文件 1. 创建 CStaticLogger 对象(通常为全局对象) 2. 调用 CStaticLogger->Init(...) 初始化日志组件 3. 使用 CStaticLogger->Log()/Debug()/Trace()/Info()/Warn()/Error()/Fatal() 等方法写日志 4. 调用 CStaticLogger->UnInit(...) 清理日志组件(CStaticLogger 对象析构时也会自动清理日志组件) 方法二:(动态加载 Logger DLL) -------------------------------------------------------------------------------------- 0. 应用程序包含 DynamicLogger.h 头文件 1. 创建 CDynamicLogger 对象(通常为全局对象) 2. 调用 CDynamicLogger->Init(...) 初始化日志组件 3. 使用 CDynamicLogger->Log()/Debug()/Trace()/Info()/Warn()/Error()/Fatal() 等方法写日志 4. 调用 CDynamicLogger->UnInit(...) 清理日志组件(CDynamicLogger 对象析构时也会自动清理日志组件) 方法三:(直接用导出函数加载 Logger DLL) -------------------------------------------------------------------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值