MarioTCP:一个单机可百万并发长连接服务器
转载自:https://blog.csdn.net/abcd1f2/article/details/42350863
注:如果用此服务器做变长data的传输,请在业务处理函数中为input buffer增加清空功能(一行memset搞定;也可以在mariotcp核心代码mario_network.c的read功能中增加,mariotcp为了追求性能极限没做此设置)。
mario_network.c 文件的 on_conn_read()函数中:
[cpp] view plaincopy
- 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:一个单机可百万并发长连接服务器相关推荐
- MarioTCP:一个单机可日30亿的百万并发长连接服务器
原文:http://blog.csdn.net/everlastinging/article/details/10894493 注:如果用此服务器做变长data的传输,请在业务处理函数中为input ...
- 物联网 长连接 服务器_为什么物联网还有很长的路要走
物联网 长连接 服务器 It's IoT Week at SitePoint! All week we're publishing articles focused on the intersecti ...
- 一个简单的高并发的回应服务器(5万并发)
一个简单的高并发的回应服务器,主要是使用boost的库! 自己测试过可以达到5万个并发! 程序的下载地址:http://download.csdn.net/detail/guanyijun123/83 ...
- 用Netty实现单机百万TCP长连接
一 服务实现模型 单机百万连接有多种方式, 这里采用一个netty server 占用8888 端口,用客户端机器模拟百万客户端连接 模拟实现的方式 以下是示意图 如果一台客户端模拟3万个连接,那么 ...
- 一文读懂 Linux 下单机实现百万并发的内核黑科技:连接跟踪(Conntrack)
公众号关注 「奇妙的 Linux 世界」 设为「星标」,每天带你玩转 Linux ! 本文介绍连接跟踪(connection tracking,conntrack,CT)的原理,应用,及其在 Linu ...
- 微信 短连接 长连接服务器,Socket,http长连接与短连接
TCP/IP TCP/IP是个协议组,可分为三个层次:网络层,传输层和应用层. 在网络层有IP协议,ICMP协议,ARP协议,RARP协议和BOOTP协议. 在传输层中有:TCP协议与UDP协议. 在 ...
- 无线时长连接服务器,ESP8266无线NTP Stratum1服务器的制作
第1步:所需组件 以下是该项目所需组件的列表,价格绝对最低!如果您发现某个地方便宜一些,请给我留言! ESP8266-01►(http://goo.gl/o4fAfJ) GPS模块►(http://g ...
- [NewLife.Net]单机400万长连接压力测试
目标 对网络库NewLife.Net进行单机百万级长连接测试,并持续收发数据,检测网络库稳定性. [2020年8月1日晚上22点] 先上源码:https://github.com/NewLifeX/N ...
- Android通过WebSocket建立一个长连接(带心跳检测)从服务器端接收消息
最近公司要做一款内部使用的工具类app,方便销售部门打电话(其实就是在后台有好多用户数据,之前销售部门同事拨打电话,需要自己从销售后台查看用户手机号等信息,然后自己拿自己手机拨号,然后打出去.现在想实 ...
最新文章
- C六:指针可以比较大小
- 基于ServletJsp的网上书店设计(一)
- springboot使用j2cache框架和aspectj自定义缓存
- spring boot 配置动态刷新
- 计算机软件应用控制程序,一种计算机应用程序实时控制软件的制作方法
- rocketMq双master集群模式下故障演练
- 狗狗手机壁纸|爱宠必备
- Listview 的应用 Day04 2014-0605
- 使用Mysql 5.5数据库Hibernate自动建表创建表出错table doesn't exist
- jstat命令查看jvm的GC情况 (以Linux为例)
- Python爬虫书籍推荐
- 2016 年数学真题
- Jedis远程连接阿里云 Failed to create socket
- 独木舟上的旅行java_贪心算法--独木舟上的旅行
- 怀旧服服务器怎么调整显卡性能,魔兽世界怀旧服排队显卡问题太高怎么回事 显卡温度高解决办法...
- 微信公众号文章采集思路
- java 选项卡放左边_java-JTabbedPane:选项卡位置设置为LEFT但图标...
- Creator 使用代码编辑九宫格
- wow服务器合并信息,《魔兽世界》一区合并服务器正式通告
- 王姨劝我学HarmonyOS鸿蒙2.0系列教程之一环境搭建跑起来模拟器!
热门文章
- 手机python3.8.5软件_Python|Python v3.8.7 for Linux下载_网站源码_站长下载
- stm32单片机c语言入门 pdf,STM32学习笔记(初学者快速入门).pdf
- python短信平台_Python短信接口demo
- 细粒度,图片上传,POI技术
- PythonC++相互混合调用编程全面实战-13C++ 调用Python的环境准备和项目初始化
- 极智嘉Geek+赋能英国零售巨头ASDA,实现突飞猛进的业务拓展
- 【ReLU】Rectified Linear Units, 线性修正单元激活函数
- 面向对象程序设计__Task3_Calculator
- npy转image图像并保存
- android 源码下载备忘