高性能网络服务器的关键在于并发,如何高效的使用多核心的服务器,让多个线程并发处理程序。web
在计算机内部,最本质的是时间(CPU)和空间(内存)这两种资源,各类并行的界限并无那么明显。所谓基于时间的并行,有两只猫,共同看守一个大仓库,但一个工做,另外一个睡觉,二者不一样时工做。所谓基于空间的并行,将仓库分为两个部分,这样两只猫能够分别看守不一样的部分,两只猫在工做不紧张的时候就能够睡觉。安全
对于网络并发程序,能够从各个角度进行优化,先谈单个UDP的服务器,再谈单个TCP服务器,最后再谈服务器集群。服务器
典型的UDP服务器,例如DNS服务器,有一个缺点,只能经过其著名的服务端口发布给客户端,全部客户端的流量集中在单个端口上,采用单个线程读取端口的数据效率最高,在读套接字时采用任何形式的并发都会致使性能的降低,对于某些版本的内核,多线程收同一套接字将产生惊群现象,这主要是由操做系统的进程调度方式引发的。于是比较好的模式是单个线程收,而后再将数据分发到后台不一样的处理线程,然而在接收线程和处理线程之间的的数据传递可能须要采用锁的方式,这样就致使程序性能降低(然而在采起分主的情境下,即单生产者和单消费者,能够采用无锁队列的方式来实现,这样就能够大幅提升程序性能),若是某种形式的锁,为了不频繁的加锁解锁操做,比较好的改进是数据的批传递,这样能够数百倍的减小加解锁的调用,也能够大幅减小线程的上下文切换开销。网络
在数据的返回阶段,典型的作法是在处理线程处理完成后,再把数据传递到发送线程,再经过原来的接收套接字将数据返回。这样在数据的发送段,又遇到了单点瓶颈。与读套接字相同,在单个套接字上发送数据时,任何并发的写也会致使发送效率的降低,这样看来只好使用单个线程来进行发送。但若是咱们有多个处理线程,它们将数据聚集到单个发送线程队列中,必然又遇到一个加锁解锁开销。虽然在同一个套接字上读和写是对系统而言是采用不一样的缓冲区,收发性能能够互不影响,但咱们为了极大的提高程序的性能,必须解决掉发送瓶颈。这就是采用地址重用,经过多个套接字并发的发送数据。若是客户端对服务器的发送端口有要求,咱们必须把多个套按字绑定到同一地址和端口上屡次,这样就产生了一个时序的问题。因为内核在实现时,能够接收数据的套按字,只有最后一次绑定的能够接收 。所以必须将发送套接字在接收套接字绑定前完成绑定,不然应用程序就收不到任何数据了。经过这样的处理,再进行某些热点的优化,UDP程序就能够作到收和发将千兆网卡跑满。固然若是你有更快的网卡,就能够以读写内存的速度来处理数据。多线程
TCP服务器分为两种并发
对于单个服务器而言,再强大也没有一群服务器强大,这样就涉及到集群的部署和负载均衡策略,最后若是服务器过多,还须要解决服务器的动态加入和退出,以及服务器安全防御问题。负载均衡