一  服务实现模型

单机百万连接有多种方式, 这里采用一个netty server 占用8888 端口,用客户端机器模拟百万客户端连接 模拟实现的方式

以下是示意图

如果一台客户端模拟3万个连接,那么100万连接,大致需要33台主机,找到33台主机的确是个困难,但是这种模型定下来,能够先实现若干台主机模拟连接也行,毕竟模型定了,剩下的只是客户主机数量的问题。

二 服务端编码

server.java

package com.jacklearn.server;import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;public class Server
{public static void main( String[] args ){    EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup(4);ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(bossGroup, workerGroup);bootstrap.channel(NioServerSocketChannel.class);bootstrap.childOption(ChannelOption.SO_REUSEADDR, true);bootstrap.childHandler(new ChannelInitializer<SocketChannel>(){@Overridepublic void initChannel(SocketChannel ch)throws Exception{ch.pipeline().addLast(new EchoServerHandler());}});bootstrap.bind(8888).addListener((ChannelFutureListener) future -> {System.out.println("bind success in port: " + 8888);});System.out.println("server started!");}}
每当客户端连接上之后,则向客户发送“hello” 消息
package com.jacklearn.server;import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;@ChannelHandler.Sharable
public class EchoServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelActive(ChannelHandlerContext ctx){System.out.println("new client arrvie");ctx.writeAndFlush(Unpooled.copiedBuffer("hello", CharsetUtil.UTF_8));  //激活后立即发送hello 消息}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception{ByteBuf in = (ByteBuf) msg;ctx.writeAndFlush(in);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause){ctx.close();}
}

三  客户端编码

package com.jacklearn.client;import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;public class Client {private static final String SERVER_HOST = "a.b.c.d"; // 请注意用实际地址替换a.b.c.dpublic static void main(String[] args) {System.out.println("client starting....");EventLoopGroup eventLoopGroup = new NioEventLoopGroup(4);final Bootstrap bootstrap = new Bootstrap();bootstrap.group(eventLoopGroup);bootstrap.channel(NioSocketChannel.class);bootstrap.option(ChannelOption.SO_REUSEADDR, true);bootstrap.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) {ch.pipeline().addLast(new IdleStateHandler(0, 0, 120)).addLast(new EchoClientHandler());}});// 创建30000个客户端连接for (int i = 0;  i < 30000; i++) {try {ChannelFuture channelFuture = bootstrap.connect(SERVER_HOST, 8888);channelFuture.addListener((ChannelFutureListener) future -> {if (!future.isSuccess()) {System.out.println("connect failed, exit!");}});channelFuture.get();} catch (Exception e) {e.printStackTrace();}}try{System.in.read();}catch (Exception e){}}
}
package com.jacklearn.client;import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.CharsetUtil;import java.nio.charset.Charset;public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {}@Overrideprotected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {ByteBuf buf = msg.readBytes(msg.readableBytes());System.out.println("Client received:" + ByteBufUtil.hexDump(buf) + "; The value is:" + buf.toString(Charset.forName("utf-8")));}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {if (evt instanceof IdleStateEvent) {IdleStateEvent e = (IdleStateEvent) evt;switch (e.state()) {case READER_IDLE:break;case WRITER_IDLE:break;case ALL_IDLE: //如果规定时内没有读写时间,则触发一个 消息ctx.writeAndFlush(Unpooled.copiedBuffer("hello", CharsetUtil.UTF_8));  //激活后立即发送hello 消息break;default:break;}}}}

这里之所以创建3万个连接,而不是创建5万连接,是因为在实测过程中,如果创建5万连接,CPU使用率会很高,影响其他程序。因此我们只创建3万个连接。

利用 IdleStateHandler ,如果120秒内客户端检测和服务器之间没有读写消息, userEventTriggered 会被触发, 此时我们向服务器发送 "hello"消,利用这种机制,我们就可以客户端和服务器之间的长连接

三  服务器和客户端配置

1. 修改server 的配置

1.1 突破局部文件句柄的限制

ulimit -n

这里一般显示的是65535,代表一个进程能够打开的最大文件数,一条TCP连接,对应Linux系统里面是一个文件,最大连接数会受限于这个数字,我们要做百万连接,所以需要修改这个值。 打开 /etc/security/limits.conf文件中配置如下两行:

hard nofile 1000000
soft nofile  1000000
soft和hard为两种限制方式,其中soft表示警告的限制,hard表示真正限制,nofile表示打开的最大文件数。

1.2 突破全局文件句柄的限制

[root@database 100W]# cat /proc/sys/fs/file-max
1610630
vi /etc/sysctl.conf

1.3 启动 server

2. 启动客户端

2.1 修改客户机设置

cat /proc/sys/net/ipv4/ip_local_port_range
值为32768 61000
  • 大概也就是共61000-32768=28232个端可用,单个IP对外只能发送28232个TCP请求。
  • 以管理员身份,把端口的范围区间增到最大
echo "1024 65535"> /proc/sys/net/ipv4/ip_local_port_range 

现在有64511个端口可用.

  • 以上做法只是临时,系统下次重启,会还原。 需要做永久修改, vi  /etc/sysctl.conf文件,增加一行内容
net.ipv4.ip_local_port_range= 1024 65535
sysctl -p

2.2  启动客户端程序

依次在N台服务器上部署客户端程序,并启动程序

四. 观察和验证

我启动了11台客户端机器,理论上每台机器应该有3万个连接,服务器有33万个连接

实际情形是,11台客户机器几乎同时启动,耗时半个小时左右, 服务器上总计有324699个连接, cpu 占用率不超过7%

[root@server 100W]# lsof -i:8888 | wc -l
324699

抽查了部分客户端机器,基本都是3万个长连接

[root@client1 ~]#  lsof -i:8888 | wc -l
30001

经过长时间的原型服务器基本稳定维持在32万长连接,客户机维持3万长连接 ,理论和实际相符

本次实验,服务端只实现了32万个长连接,但 这是由于客户机数量不足的原因,如果再能增加20台客户机,相信在服务器程序不做任何改变的情况下,也能完好支持,完全能够实现单台服务器百万长连接。

五 后记

其实一般情况下,大规模连接并不是一个特别复杂的问题,以上只是采用了很简单的编程方法就能实现。 当然某些情况下的高并发的确是有难度的,例如春晚,瞬间可能有几百万的连接进来,而不是像上文那种,半个小时才有百万连接,上面这种编程肯定是不能应对的。

用Netty实现单机百万TCP长连接相关推荐

  1. 使用netty实现并维护TCP长连接

    使用netty实现并维护TCP长连接 Netty是什么 Netty的优点 Netty为什么并发高 创建TCP长连接实例 Netty是什么 Netty 是一个利用 Java 的高级网络的能力,隐藏其背后 ...

  2. MarioTCP:一个单机可日30亿的百万并发长连接服务器

    原文:http://blog.csdn.net/everlastinging/article/details/10894493 注:如果用此服务器做变长data的传输,请在业务处理函数中为input ...

  3. MarioTCP:一个单机可百万并发长连接服务器

    转载自:https://blog.csdn.net/abcd1f2/article/details/42350863 注:如果用此服务器做变长data的传输,请在业务处理函数中为input buffe ...

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

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

  5. 【TCP长连接】使用TCP长连接提升服务性能

    1.概述 在<性能优化篇-理论基础>中,我们知道了提升服务性能的两个思路,分别是提升服务并发能力和降低请求的响应时间(RT).一个请求的响应时间包括两部分,等待时间和执行时间.在<性 ...

  6. 亿级流量架构演进实战 | 架构演进构建TCP长连接网关 04

    这不是一个讲概念的专栏,而且我也不擅长讲概念,每一篇文章都是一个故事,我希望你可以通过这些故事了解我当时在实际工作中遇到问题和背后的思考,架构设计是种经验,我有幸参与到多个亿级系统的架构设计中,有所收 ...

  7. python使用socket实现协议TCP长连接框架

    点击上方↑↑↑蓝字[协议分析与还原]关注我们 " 使用python实现协议中常见的TCP长连接框架." 分析多了协议就会发现,很多的应用,特别是游戏类和IM类应用,它们的协议会使用 ...

  8. 通da信TCP长连接数据算法分析

    点击上方↑↑↑蓝字[协议分析与还原]关注我们 " 分析通da信TCP长连接内部分数据的算法." 作为一款老牌的炒股软件,通da信里面的数据是相当的丰富,免费的也很丰富,准确性也很好 ...

  9. TCP长连接与短链接

    1. TCP连接 当网络通信时采用TCP协议时,在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,连接的建立是需要三次 ...

最新文章

  1. 【OpenCV 4开发详解】可分离滤波
  2. 记一次TrustAnchor with subject异常解决
  3. [转]double free or corruption (!prev): 0x080644c8 ***
  4. linux下php远程连接mysql_Linux下PHP远程连接Oracle数据库 | 系统运维
  5. error while loading shared libraries: libatomic.so.1
  6. jtree和mysql_Jtable和JTree的写法示例代码
  7. IntObjectHashMap和HashMap的区别?
  8. 【微型计算机原理与接口技术】计算机系统的基本组成
  9. 百亿级日访问量的应用如何做缓存架构设计?
  10. java堆排序递归代码,无原理版,比较好理解
  11. 微型计算机主机的组成不包括______,微型计算机主机的主要组成部分是什么
  12. 手机怎么设置腾达路由器后显示远端服务器,教你如何用手机快速设置腾达路由器...
  13. 我看过的世界历史纪录片和科技史、经济史、人类史笔记
  14. ERP : 产出控制
  15. 一阶方向导数与梯度和方向向量的关系及其应用
  16. 为何选择阿里云——恒生银行案例
  17. Kafka集群的安全认证机构 SASL_SCRAM
  18. so easy,用 Python 实现图片转字符画
  19. 中国搜索 20 年:巨头百度的兴衰密码
  20. cam350删除东西

热门文章

  1. ZEMAX光学设计视频教程 ZEMAX资料教程大全
  2. js解析复杂json对象
  3. 关于linux内核中jiffies和jiffies_64解析
  4. 通信设备市场遭遇狼来了,华为面临三星挑战
  5. Python3学习(八)
  6. 统帅空调成华为HiLink智能家居首批智慧家电
  7. 拼多多平台商品解析与获取
  8. spring 框架简介与搭建
  9. spring框架搭建与入门案例
  10. 嵌套函数—面向对象初步