您好、欢迎来到现金彩票网!
当前位置:秒速牛牛开奖 > 同步通信量 >

聊聊如何设计千万级吞吐量的

发布时间:2019-06-25 09:23 来源:未知 编辑:admin

  首先看下面这张很具有代表性的图,2018年5月份做的测试。当时单服务器得到(Transactions Per Second,每秒事务数) 的吞吐率。这次测试只是说明一个问题,.Net可以做超高吞吐率的应用。

  上面是最小的网络库例程,简单演示了服务端和客户端,连接和收发信息。网络应用分为NetServer/NetSession,服务端、会话,N个客户端连接服务器,就会有N个会话。来一个客户端连接,服务端就new一个新的NetSession,并执行Start,收到一个数据包,就执行OnReceive,连接断开,就执行OnDispose,这便是服务端的全部。

  客户端连接刚上来的时候,没有数据包等其它信息,所以这个时候没有参数。客户端发数据包过来,

  服务端的创建,可以是很简单,看以下截图。这里为了测试方便,开了很多Log,实际使用的时候,根据需要注释。

  因为是长连接,所以服务端随时可以向客户端发送数据包,客户端也可以收到。tcp在不做设置的时候,默认长连接2小时。

  NetServer默认20分钟,在没有心跳的时候,20分钟没有数据包往来,服务端会干掉这个会话。

  虽然上面讲的NetServer和Client,都是tcp,但是换成其它协议也是可以的。这里的NetServer和NetUri.CreateRemote,同时支持Tcp/Udp/IPv4/IPv6等,CreateRemote内部,就是根据地址的不同,去new不同的客户端。所以我们写的代码,根本不在意用的是tcp还是udp,或者IPv6。有兴趣的可以看看源码

  要真正形成一个网络服务,那得稳定可靠。上面例程EchoTest只是简单演示,接下来看下一个例程EchoAgent。

  必须有这个东西,你的网络服务程序,才有可能达到产品级。linux上直接控制台,上nohup,当然还有很多其它办法。以后希望这个XAgent能够支持linux吧,这样就一劳永逸了

  只需要记住一个两个数字,用打出来2266万tps,流量峰值4.5Gbps

  两千万吞吐量的数字,当然,只能看不能用。因为服务端只是刚才的Echo而已,并没有带什么业务。实际工作中,带着业务和数据库,能跑到10万已经非常非常牛逼了。

  我们工作中的服务可以跑到100万,但是我不敢,怕它不小心就崩了。所以我们都是按照10万的上限来设计,不够就堆服务器好了,达到5万以上后,稳定性更重要

  很多人可能都听说Tcp是流式协议,但是很少人去问,什么叫流式吧?流式,就是它把数据像管道一样传输过去。

  刚才我们发了5个 “你好”,它负责把这10个字发到对方,至于发多少次,每次发几个字,不用我们操心,tcp底层自己处理。tcp负责把数据一个不丢的按顺序的发过去。所以,为了性能,它一般会把相近的数据包凑到一起发过去。对方收到一个大包,5个小包都粘在了一起,这就是最简单的粘包。

  这个特性由NoDelay设置决定。NoDelay默认是false,需要自己设置。如果设置了,就不会等待。但是不要想得那么美好,因为对方可能合包。

  局域网MTU(Maximum Transmission Unit,最大传输单元)是1500,处于ip tcp 头部等,大概1472多点的样子。

  A 1000 字节 B 也是 1000字节,对方可能收到两个包,1400 + 600。对方可能收到两个包,1400 + 600。

  凡是以特殊符号开头或结尾来处理粘包的办法,都会有这样那样的缺陷,最终是给自己挖坑。所以,tcp粘包,绝大部分解决方案,偏向于指定数据包长度。这其中大部分使用4字节长度,长度+数据。对方收到的时候,根据长度判断后面数据足够了没有。

  每次判断长度,接收一个或多个包,如果接收不完,留下,存起来。等下一个包到来的时候,拼凑完整。

  虽然tcp确保数据不丢,但是难免我们自己失手,弄丢了一点点数据。为了避免祸害后面所有包,就需要进行特殊处理了。

  每个数据帧,自己把头部长度和数据体凑一起发送啊,tcp确保顺序。这里我们把超时时间设置为3~5秒,每次凑包,如果发现上次有残留,并且超时了,那么就扔了它,省得祸害后面。

  这么些行代码,就几个地方有价值,一个是注册了两个控制器。你可以直接理解为Mvc的控制器,只不过我们没有路由管理系统,直接手工注册。

  第二个是指定编码器为Json,用Json传输参数和返回值。其实内部默认就是Json,可以不用指定

  看看我们的控制器,特别像Mvc,只不过这里的Controller没有基类,各个Action返回值不是ActionResult,是的,ApiServer就是一个按照Mvc风格设置的RPC框架

  这些就是我们刚才客户端远程调用的stub代码啦,当然,我们没有自动生成stub,也没有要求客户端跟服务端共用接口之类。实际上,我们认为完全没有必要做接口约束,大部分项目的服务接口很少,并且要求灵活多变

  stub就是类似于,刚才那个MyController实现IAbc接口,然后客户端根据服务端元数据自动在内存里面生成一个stub类并编译,这个类实现了IAbc接口。

  其实stub代码内部,就是封装了 这里的InvokeAsync这些代码,等同于自动生成这些代码,包括gRPC、Thrift等都是这么干的

  这个RPC框架,封包协议就是刚才的SRMP,负载数据也就是协议是json

  当需要高速传输的时候,参数用Byte[],它就会直接传输,不经json序列化,这是多年经验得到的灵活性与性能的最佳结合点

  我们一开始就是让Tcp/Udp可以混合使用,网络库设计于2005年,应该要比现如今绝大部分网络框架要老。服务端清一色采用 Server+Session 的方式。

  所有对象,不管客户端服务端,都实现ISocket。然后客户端Client,服务端Server+Session。tcp+udp同时支持并不难,因为它们都基于Socket。

  ,因为要做发送队列、拆分、合并,等等,异步发送大大增加了复杂度。大家如果将来遇到诡异的40ms延迟,非常可能就是tcp的nodelay作怪,可以设为true解决

  ,高吞吐率的服务端,一定是异步接收,而不是多线程同步。当然,可以指定若干个线程去select,也就是Linux里面常见的poll,那个不在这里讨论,Windows极少人这么干,大量资料表明,iocp更厉害。

  SAEA是.netcore当下最流行的网络架构,我们可以通俗理解为,把这个缓冲区送给操作系统内核,待会有数据到来的时候,直接放在里面,这样子就减少了一次内核态到用户态的拷贝过程。

  我们测试4.5Gbps,除以8,大概是 540M字节,这个拷贝成本极高

  ,这也是netty的核心优势。iocp是为了减少内核态到用户态的拷贝,zerocopy进一步把这个数据交给用户层,不用拷贝了。

http://4kci.com/tongbutongxinliang/288.html
锟斤拷锟斤拷锟斤拷QQ微锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷微锟斤拷
关于我们|联系我们|版权声明|网站地图|
Copyright © 2002-2019 现金彩票 版权所有