原文:http://blog.csdn.net/everlastinging/article/details/10894493

注:如果用此服务器做变长data的传输,请在业务处理函数中为input buffer增加清空功能(一行memset搞定;也可以在mariotcp核心代码mario_network.c的read功能中增加,mariotcp为了追求性能极限没做此设置)。

mario_network.c 文件的 on_conn_read()函数中:

memset(c->in_buf,'\0',sizeof(c->in_buf_len));
c->in_buf_len=0;

MrioTCP,超级马里奥,顾名思义,他不仅高效,而且超级简易和好玩。同时他可以是一个很简洁的Linux C 开发学习工程。毫不夸张的说,如果全部掌握这一个工程,你会成为一个Linux C的牛人;当然,你也可以通过源码包的mario.c(maritcp服务器示例程序)来学习,可以很快入门上手进行Linux C开发。

经过两个多月的测试(编写c++客户端测试及调优系统参数),测试结果得到单机最大带宽吞吐1000M,测试最高TCP长连接100万,每秒处理连接数达4万,此时系统压力load值很低。总之,它可以发挥一台服务器的最大极限以提供最高性能的服务;而且经过完备测试,运行稳定且占用系统资源非常少。

他是建立在Sourceforge上的一个开源项目,由源码的作者冯建华(JohnFong)发起。源码可以在Sourceforge上下载。

sourceforge下载:https://sourceforge.net/projects/mariotcp/files/latest/download

csdn下载:http://download.csdn.net/detail/everlastinging/6195605

51cto下载:http://down.51cto.com/data/935913

Getting Started

用MarioTCP来建立一个性能强大的TCP服务器非常简易!

  工程源码包就是一个非常简洁的例子,生成了一个tcp服务器程序:maritcp。
  源码包中:
  mario.c是简易例子的main程序,直接make可以编译出maritcp,一个tcp服务器,业务逻辑只有一个功能:统计同时在线socket数、每隔1分钟输出一次。
  mario文件夹,MarioTCP的核心代码,make可以直接编译出静态的libmario.a。MarioTCP核心架构后续会介绍。
  test文件夹,是一个稍显简陋的客户端测试程序,通过与服务器建立连接、发送LOGIN包登陆服务器,此时maritcp服务器会使同时在线加1,客户端断开时服务器在线数减1。

现在讲一下如何定制一个自己业务逻辑的tcp服务器,只需五步:
  1、初始化SERVER
  SERVER *server = init_server(conf->port, conf->workernum, conf->connnum, conf->timeout, conf->timeout);
  传入参数分别是:
  服务器Listen端口,工作线程数,每个线程支持的连接数,读超时时间,写超时时间。
  workernum * connum 就是服务器支持的长连接数,一个worker可以轻松支持10万长连接。

2、实现业务逻辑函数并注册
  具体业务逻辑函数请见Function模块。可通过mario.h中定义的名为“regist_*”的函数来注册。

/*
  *  注册业务处理函数
  /
  void regist_akg_func(uint16 id, FUNC_PTR func);
  id可以是0-65535的任意数,此id封装在MarioTCP的协议中(见本文最后)。
  id的范围,可以根据业务逻辑来定制,例如maritcp通过protocol.h中定义的CMD结构体来设定:
  typedef enum _CMD {
  CMD_FUNCTION_BASE = 0x6100,
  CMD_FUNCTION_LOGIN = 0x6101
  } CMD;

如果你想为maritcp增加一个"say_hello"的服务,可以这么做:
  1)在CMD中增加:CMD_FUNCTION_SAY_HELLO = 0x602
  2) 在function中增加函数:
  sint32 say_hello(CONN c) {
  I)通过CONN来解析客户端发过来请求的参数
  II)将“hello”设定到c->out_buf
  III)bufferevent_write(c->bufev, c->out_buf, hrsp->pkglen);
  IV)return 0;
  }
  3)在mario.c中增加:regist_akg_func(CMD_FUNCTION_SAY_HELLO, say_hello);

怎么样?自己定制业务逻辑,还是很简单高效吧!

3、启动日志线程start_log_thread()
  MarioTCP的日志功能封装还不够好,在“go on 1.0.0”页面中继续讨论...

4、启动服务器start_server((void*) server);
  OK,一个可以支持100万甚至更多长连接的TCP服务器,诞生了!

Go On 1.0.0

第一个发布版本为0.9.9,尽管用这个包,通过几分钟就可以实现一个定制了你的业务逻辑的、稳定高效的TCP服务器,但是MarioTCP还有很多有待完善的地方,让我们一起尽快解决如下问题,让MarioTCP-1.0.0尽快发布!

1、MarioTCP协议如何优化
  为了使MarioTCP足够安全,规定了一个简易的MarioTCP协议,经过三次握手连接到MarioTCP的client,接下来发的包要求格式必须是“HEAD+Data”的形式,而HEAD结构体定义在mario_akg.h中:
  typedef struct _HEAD {
  uint32 stx;
  uint16 pkglen;
  uint16 akg_id;
  } HEAD;
  pkglen是整个包的长度,即“HEAD+Data”。
  akg_id及自定义的业务逻辑函数对应的id,例如“Getting Started”页面中的CMD_FUNCTION_SAY_HELLO
  stx是你自定义的协议密文,通过regist_stx(uint32 stx)来注册(见mario.c)

尽管MarioTCP的协议足够简单了,而且协议最开头的密文可以自定义,但是是否可以更简单或者无协议,以最大程度的方便开发使用,需要大家的建议和帮助!

2、日志系统过于死板
  MarioTCP有一套自成系统的日志功能,但是比较晦涩难懂。
  接下来再展开...

3、业务逻辑稳定性支持
  MarioTCP对于网络连接和读写,非常高效和稳定。
  但是MarioTCP的线程池是固定个数的,且是全局唯一初始化的,死掉的线程不可再重启;分配网络任务的Master线程不具备监听worker的功能,一个线程死掉了、任务却还会一直分配过来,造成服务堆积且不处理。如果业务逻辑如果非常复杂和低效,就会出现这个问题。
  在大型线上项目中,用到MarioTCP的地方,都会通过业务逻辑模块的监听、告警及程序自动处理来避免上述问题。由于时间问题还没有把此功能抽象到MarioTCP中。

  这件事情,近期我会抓紧处理。也希望有朋友建议和帮助!!

Why Supper

一、为什么超级高效
  1、网络服务用到的所有结构体和内存都是启动程序时初始化的,无销毁,无回收。
  无销毁好理解,不解释。
  无回收,是指所有内存单元拿来即用,用完及可,不用做reset操作。
  2、一个master线程进行accept
  经过测试发现多进程或线程进行accept和一个进程或线程accept,在极限压力下区别不大。
  一个master比多个master好在不用再通过锁来解决同步问题。
  3、master与worker时单一生产者消费者模式,完全无锁通信
  不光accept无锁,分配connection、后续的conncetion处理都是无锁的。
  甚至业务逻辑(见示例maritcp的统计在线数功能)、MarioTCP的日志系统(这也是日志系统抽象不够的一个原因,之前的设计太依赖于整体架构了)都是无锁处理的!
  4、一个worker一套libevent环境
  libevent处理10万长连接的网络读写事件,其性能达到最大化了。
  每个worker都独立一套libevent,这个结构经过测试,发现开销很小、性能很高。

二、单机百万长连接、四万cps(连接每秒)如何做测试得来
  1、设置系统最大文件数为unlimited
  2、设置系统的tcp内存内核参数到256M以上
  3、设置系统的ip到15个,那么可服务的长连接数理论上最少15*(65535-1024)个
  4、用epoll或libevent开一个可同时连接5w的客户端程序;程序还要实现每秒随机挑选1000个连接断掉,并再新创建1000个连接。另外在随机挑选几千连接发包。
  同时再多台机器上开启20个客户端,那么就是100w长连接,每秒2w个连接断掉、2w个新连接加入进来,并且有若干包发过来。
  5、设置服务端可重用SYN_WAIT的连接;客户端断连接的方式是主动断掉(防止客户端程序端口堆积)
  总之很折腾的一个测试,前前后后大约2个多月才测试完毕。

  以上内容凭记忆写的,怕有错误或疏漏,回头为了公布测试代码和测试结果给大家,会再次开发、测试并调整补过上述内容。

解决:

错误1:

mario/mario_conn.h:22:19: 错误:event.h:没有那个文件或目录
In file included from mario/mario.h:22,
from mario.c:15:
mario/mario_network.h:44: 错误:字段 ‘notify_event’ 的类型不完全
mario/mario_network.h:61: 错误:字段 ‘listen_event’ 的类型不完全
在包含自 mario/mario.h:21 的文件中,
从 config.h:4,
从 config.c:5:
mario/mario_conn.h:22:19: 错误:event.h:没有那个文件或目录
mario/mario_network.h:61: 错误:字段 ‘listen_event’ 的类型不完全
在包含自 mario/mario.h:21 的文件中,
从 function.h:14,
从 function.c:10:
mario/mario_conn.h:22:19: 错误:event.h:没有那个文件或目录
In file included from mario/mario.h:22,
from function.h:14,
from function.c:10:
mario/mario_network.h:44: 错误:字段 ‘notify_event’ 的类型不完全
mario/mario_network.h:61: 错误:字段 ‘listen_event’ 的类型不完全
在包含自 mario/mario.h:21 的文件中,
从 collect.c:11:
mario/mario_conn.h:22:19: 错误:event.h:没有那个文件或目录
make: *** [maritcp] 错误 1

解决1:

当前系统可能没有libevent库等,请依次安装:

yum install libevent libevent-devel

yum install libevent gcc gcc-c++

MarioTCP:一个单机可日30亿的百万并发长连接服务器的更多相关文章

  1. HttpAsyncClient 做并发长连接的一个实例

    HttpAsyncClient 做并发长连接的一个实例 import java.util.concurrent.CountDownLatch; import org.apache.http.HttpR ...

  2. [NewLife.Net]单机400万长连接压力测试

    目标 对网络库NewLife.Net进行单机百万级长连接测试,并持续收发数据,检测网络库稳定性. [2020年8月1日晚上22点] 先上源码:https://github.com/NewLifeX/N ...

  3. 如何快速判断一个key是否存在在亿级数据中(bloomFilters)

    面试题 现在有一个非常庞大的数据(亿级),假设全是 int 类型.现在我给你一个数,你需要告诉我它是否存在其中(尽量高效) 分析 采用bloomFilters进行实现(时间&空间尽可能的有效) ...

  4. 单机千万级MQTT连接服务器测试报告

    目标:测试创建1000万客户端连接到服务器端,服务器操作系统 Linux(任意一款发行版服务器版本).分别在两台硬件一样的服务器,其中一台用于服务器端运行,另一台用于创建千万客户端连接客户端机器.在硬 ...

  5. 【网络】高性能网络编程--下一个10年,是时候考虑C10M并发问题了

    转载:http://www.52im.net/thread-568-1-1.html 1.前言 在本系列文章的上篇中我们回顾了过云的10年里,高性能网络编程领域著名的C10K问题及其成功的解决方案(上 ...

  6. IM服务器:开发一个高并发的IM服务器难在哪

    IM服务器要实现的最基本功能就是消息的转发.--好像是一句废话! 这就意味着IM服务器要为每个登录用户创建一个与该用户信息相关的内存上下文,为方便描述我们在这里称之为:user_context.use ...

  7. 30行自己写并发工具类(Semaphore, CyclicBarrier, CountDownLatch)是什么体验?

    30行自己写并发工具类(Semaphore, CyclicBarrier, CountDownLatch)是什么体验? 前言 在本篇文章当中首先给大家介绍三个工具Semaphore, CyclicBa ...

  8. 分享一个基于长连接+长轮询+原生的JS及AJAX实现的多人在线即时交流聊天室

    实现网页版的在线聊天室的方法有很多,在没有来到HTML5之前,常见的有:定时轮询.长连接+长轮询.基于第三方插件(如FLASH的Socket),而如果是HTML5,则比较简单,可以直接使用WebSoc ...

  9. 你想建设一个能承受500万PV/每天的网站吗?服务器每秒要处理多少个请求才能应对?

    你想建设一个能承受500万PV/每天的网站吗?服务器每秒要处理多少个请求才能应对? 你想建设一个能承受500万PV/每天的网站吗? 500万PV是什么概念?服务器每秒要处理多少个请求才能应对?如果计算 ...

随机推荐

  1. Android使用shape制作圆形控件及添加弹跳动画

    --------本来为作者原创,未经同意禁止转载 前言:我们在很多时候都需要在res/drawable文件夹下创建相应的xml文件来为控件添加一些样式效果,比如按钮按下时的按钮样式变化.或者指定按钮的 ...

  2. 理解 Linux 的硬链接与软链接

    Linux 的文件与目录 现代操作系统为解决信息能独立于进程之外被长期存储引入了文件,文件作为进程创建信息的逻辑单元可被多个进程并发使用.在 UNIX 系统中,操作系统为磁盘上的文本与图像.鼠标与键盘 ...

  3. 剑指Offer——京东校招笔试题+知识点总结

    剑指Offer--京东校招笔试题+知识点总结 笔试感言 经过一系列的笔试,发觉自己的基础知识还是比较薄弱的,尤其是数据结构和网络,还有操作系统.工作量还是很大的.做到精确制导的好方法就是在网上刷题,包 ...

  4. JQuery之动画与特效

    显示与隐藏 show(spped,[callback])与hide(spped,[callback]) speed可选填slow.normal.fast,对应的速度分别为600ms.400ms.200 ...

  5. 开源项目——小Q聊天机器人V1.2

    小Q聊天机器人V1.0 http://blog.csdn.net/baiyuliang2013/article/details/51386281 小Q聊天机器人V1.1 http://blog.csd ...

  6. Objective-C实现常用的4种排序算法

    OC实现的4种排序又来了! 4种排序分别是:快速排序.冒泡排序.选择排序.插入排序,其他的我就不写了,因为OC里的数组中不能存放基本数据类型,如int不能存放,只能放对象,所以所有的数据我用了NSNu ...

  7. Java初级面试题

    //1.请问执行下面的程序大致会输出类似什么内容? public class TestThisToString{ public String toString(){ return "my m ...

  8. UNIX环境高级编程——文件I/O

    一.文件描述符 对于Linux而言,所有对设备或文件的操作都是通过文件描述符进行的.当打开或者创建一个文件的时候,内核向进程返回一个文件描述符(非负整数).后续对文件的操作只需通过该文件描述符,内核记 ...

  9. python安装json的方法;以及三种json库的区别

    python中的json解释库有好几个,不同版本使用方法不同. 常用有 json-py 与smiplejson 两个包 其中,json-py 包含json.py外,还有一个minjson,两者用法上有 ...

  10. 【Android 应用开发】Android 图表绘制 achartengine 示例解析

    作者 : 韩曙亮 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/38420197 一. AChartEngine 简介 1. 项 ...