对Linux服务端的理解

来源:互联网 发布:苹 电脑软件 编辑:程序博客网 时间:2024/05/17 21:52

Linux系统的server性能

当且仅当单台server的情况

 

考虑情况如下:

1、接受用户的能力

2、接受数据,解包的能力

3、发送数据,发包的能力

 

一、考虑接受用户连接请求的能力。

注:此处仅是假想,还没有确认能否直接core绑定单个线程跑,但是在linux c/c++ pthread_create中设置线程属性是可以让他霸占CPU的。

单台服务器,无论你CPU轮询多快,始终快不过进程/线程绑定在一个core上一直accep用户的连接请求。但是,将一个core一直用于accept用户又有可能导致该core的性能浪费。所以,对应不同服务器类型,应当有不同的设计方案:

情况1 服务器一直处于用户连接-断开状态(或大量时间)

情况2 用户的连接是长期存在的,连接不是频繁的

 

考虑情况1

服务器一直处于用户连接-断开状态

毫无疑问,此处绑定core是有优势的。对于某些服务端情况,无限的用户连接,断开请求,绑定core可以避免上下文切换的开销——不必一会某个线程accept,某个线程发生其他的请求又切换core给它处理。很明显,这会导致大量的切换工作,效率是极低的。将accept的线程绑定在core上,它可以永久的处理用户连接,而不必去应付那些切换的开销了。

 

考虑情况2

用户的连接是长期存在的,连接不是频繁的

与上对应,用户连接长期存在,那么并不会是那种需要长期accept的工作,此时绑定core反而会导致该core的浪费。因为绑定core了,并不需要去考虑该accept工作是阻塞还是非阻塞的,它只有一个工作,无论阻塞非阻塞都在做这个工作,这就没什么意义了。只需将它看成阻塞的即可。阻塞的线程可能很久才会接受一个用户的连接请求,单core去做这件事那不是太浪费了吗?epoll的轮询此时更佳。

 

综合上述情况,怎么样才能更好的提高服务端处理用户连接请求的能力?

对于情况1,绑定是最佳的。但是如果我的server是存在1和2情况,比如说,白天连接请求多,夜晚少,1和2的情况交替发生的,怎么办?注意到此处单选1和2的方案都不是优秀的,都存在利弊。如果服务器能动态调整1和2的状态那该多好?

 

 

二、接受数据,解包能力

在Intel的实习就是DPDK的实习,虽然没有学到什么东西,但是考虑到这个问题第一反应就是可以从硬件解决。DPDK的核心就是应用硬件的处理能力绕过Linux协议栈去解包,直接提供给上层应用。硬件能够承担包的处理能力这可以让做软件人并不需要考虑更多问题。但是,单纯从软件层面去考虑解决这个问题会给我们更多的核心适应力和思考能力。数据要快,硬件肯定是不可或缺的。你的软件再牛逼,给你一条速度慢到收不到数据的带宽信道那也是白费劲。所以,此处优先排除带宽问题导致的影响。那么从纯软件的角度去看待这个问题。

 

情况1 包来了,Linux协议栈接收到了,但是程序处理的太慢了怎么办?

情况2 包来的太多了,程序已经达到处理的瓶颈了,Linux协议栈收不完了怎么办?

 

考虑情况1

包来了,Linux协议栈接收到了,但是程序处理的太慢了怎么办?

很明显,你的程序有问题。它根本做不到完全利用硬件资源,更不要说压榨硬件资源了。那么昂贵的硬件挂载你的程序还跑不过多年前的硬件挂载高效的程序,这问题就大了。一切的核心就是压榨完现有的硬件资源,软件能力达到顶峰了再通过提升硬件水平去解决。那么包来了,Linux协议栈都接受到了,将这些包的队列存在缓冲区中,你程序处理的太慢,之后来的包只能被抛弃,如果是TCP或者SCTP这样的协议,将会导致客户端将丢失的包重发,那么你的服务器外部信道就完蛋了。这些信道全跑那些包丢弃的包,此消彼长,信道占满你的服务器也崩了。如何更快的处理这些包?程序需要更高更好更强的I/O能力。最最最理想的情况,就是来多少包你都能解决,Linux协议栈的缓冲区里包的数量永远的固定的或者越来越少的。这对I/O是一个很大的考验。解决方案是,开多个线程去处理这些包,通过压榨CPU分配给其他线程的时间去做包处理的I/O。当然还有一种解决方案,相对来说比较滑稽了,但是也可能是有效的——通过开发的上层应用去阻止客户端给服务端传递消息了。这种手段可能是有效的,但是在我的认知中绝大多数情况都是累赘。不说他效率多低,就是从能帮你流失客户的能力来说简直一流。

 

考虑情况2

包来的太多了,程序已经达到处理的瓶颈了,Linux协议栈收不完了怎么办?

这在上一种情况中已经有过提示,提升硬件的水平去迎接更大的挑战。还有办法,那就是去修改Linux协议栈了。是,你可以通过修改协议栈去解决它。(这还是能解决一定程度上的问题,并不能完全解决,用户总是越来越多的,数据能是越来越多的)但是,如果你需要给应用配置更多的服务器,你也要修改他们的协议栈。你可以说修改好了我们在git上做版本控制,其他服务器安装时直接用,但是,如果你在用的发行版更新了,而你也需要更高级的发行版版本你还是需要重新去kernel中修改并且编译,这实在是太麻烦了,规模大到一定人力资源丰富的话那我就不多嘴了。

 

综上所述,处理这些问题该采用哪些手段?

软件能解决的用软件解决,硬件能解决的用硬件解决,这些都解决不了又要用到Linux协议栈的,那就去自己修改吧。。。

 

 

三、发送数据,发包的能力

以上讨论的都是客户端给服务端发送数据产生的问题。这里则是服务端发给用户数据的难题。

情况1 应用程序处理能力不佳,导致发送过慢

情况2 Linux协议栈发送过慢

情况3 带宽不足

 

情况1 应用程序处理能力不佳,导致发送过慢

这个没什么好说的。招几个算法能力强的工程师吧。要么重构框架做的更好更牛逼。

 

情况2 Linux协议栈发送过慢

紧跟上面,不考虑修改Linux协议栈。用一个线程去跑Linux协议栈是这样的——从顶端应用层开始,发送数据进入协议栈,协议栈从上至下跑完,变成比特流出去。。。那么此时你的线程在做什么呢?不要怀疑,没错它就是在等待。等待这些数据处理完再继续发数据进入协议栈。这就直接导致了协议栈发包太慢了!解决方案还是提高I/O效率。让多个线程去跑Linux协议栈,数据不停的发进去,不停的处理。提高了CPU在协议栈上的时间会让你的程序发包速度提升。

 

情况3 带宽不足

带宽不足没什么好说的。花钱加带宽吧。


此文仅是个人理解,如有巧同,不甚荣幸。欢迎大家指正和补充不足之处,另外,轻喷。。。

0 0
原创粉丝点击