热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

LinuxSocket编程线程

本章主要列举服务器程序的各种网络模型,示例程序以及性能对比后面再写。一、分类依据。服务器的网络模型分类主要依据以下几点(1)是否阻塞方式处

本章主要列举服务器程序的各种网络模型,示例程序以及性能对比后面再写。
一、分类依据。服务器的网络模型分类主要依据以下几点
(1)是否阻塞方式处理请求,是否多路复用,使用哪种多路复用函数
(2)是否多线程,多线程间如何组织
(3)是否多进程,多进程的切入点一般都是accept函数前
二、分类。首先根据是否多路复用分为三大类:
(1)阻塞式模型
(2)多路复用模型
(3)实时信号模型
三、详细分类。
1、阻塞式模型根据是否多线程分四类:
(1)单线程处理。实现可以参见http://www.cppblog.com/CppExplore/archive/2008/03/14/44509.html后面的示例代码。
(2)一个请求一个线程。
主线程阻塞在accept处,新连接到来,实时生成线程处理新连接。受限于进程的线程数,以及实时创建线程的开销,过多线程后上下文切换的开销,该模型也就是有学习上价值。
(3)预派生一定数量线程,并且所有线程阻塞在accept处。
该模型与下面的(4)类似与线程的领导者/追随者模型。
传统的看法认为多进程(linux上线程仍然是进程方式)同时阻塞在accept处,当新连接到来时会有“惊群”现象发生,即所有都被激活,之后有一个获取连接描述符返回,其它再次转为睡眠。linux从2.2.9版本开始就不再存在这个问题,只会有一个被激活,其它平台依旧可能有这个问题,甚至是不支持所有进程直接在accept阻塞。
(4)预派生一定数量线程,并且所有线程阻塞在accept前的线程锁处。
一次只有一个线程能阻塞在accept处。避免不支持所有线程直接阻塞在accept,并且避免惊群问题。特别是当前linux2.6的线程库下,模型(3)没有存在的价值了。另有文件锁方式,不具有通用性,并且效率也不高,不再单独列举。
(5)主线程处理accept,预派生多个线程(线程池)处理连接。
类似与线程的半同步/半异步模型。
主线程的accept返回后,将clientfd放入预派生线程的线程消息队列,线程池读取线程消息队列处理clientfd。主线程只处理accept,可以快速返回继续调用accept,可以避免连接爆发情况的拒绝连接问题,另加大线程消息队列的长度,可以有效减少线程消息队列处的系统调用次数。
(6)预派生多线程阻塞在accept处,每个线程又有预派生线程专门处理连接。
(3)和(4)/(5)的复合体。
经测试,(5)中的accept线程处理能力非常强,远远大于业务线程,并发10000的连接数也毫无影响,因此该模型没有实际意义。
总结:就前五模型而言,性能最好的是模型(5)。模型(3)/(4)可以一定程度上改善模型(1)的处理性能,处理爆发繁忙的连接,仍然不理想。。阻塞式模型因为读的阻塞性,容易受到攻击,一个死连接(建立连接但是不发送数据的连接)就可以导致业务线程死掉。因此内部服务器的交互可以采用这类模型,对外的服务不适合。优先(5),然后是(4),然后是(1),其它不考虑。
2、多路复用模型根据多路复用点、是否多线程分类:
以下各个模型依据选用select/poll/epoll又都细分为3类。下面个别术语采用select中的,仅为说明。
(1)accept函数在多路复用函数之前,主线程在accept处阻塞,多个从线程在多路复用函数处阻塞。主线程和从线程通过管道通讯,主线程通过管道依次将连接的clientfd写入对应从线程管道,从线程把管道的读端pipefd作为fd_set的第一个描述符,如pipefd可读,则读数据,根据预定义格式分解出clientfd放入fd_set,如果clientfd可读,则read之后处理业务。
此方法可以避免select的fd_set上限限制,具体机器上select可以支持多少个描述符,可以通过打印sizeof(fd_set)查看,我机器上是512字节,则支持512×8=4096个。为了支持多余4096的连接数,此模型下就可以创建多个从线程分别多路复用,主线程accept后平均放入(顺序循环)各个线程的管道中。创建5个从线程以其对应管道,就可以支持2w的连接,足够了。另一方面相对与单线程的select,单一连接可读的时候,还可以减少循环扫描fd_set的次数。单线程下要扫描所有fd_set(如果再最后),该模型下,只需要扫描所在线程的fd_set就可。
(2)accept函数在多路复用函数之前,与(1)的差别在于,主线程不直接与从线程通过管道通讯,而是将获取的fd放入另一缓存线程的线程消息队列,缓存线程读消息队列,然后通过管道与从线程通讯。
目的在主线程中减少系统调用,加快accept的处理,避免连接爆发情况下的拒绝连接。
(3)多路复用函数在accept之前。多路复用函数返回,如果可读的是serverfd,则accept,其它则read,后处理业务,这是多路复用通用的模型,也是经典的reactor模型。
(4)连接在单独线程中处理。
以上(1)(2)(3)都可以在检测到cliendfd可读的时候,把描述符写入另一线程(也可以是线程池)的线程消息队列,另一线程(或线程池)负责read,后处理业务。
(5)业务线程独立,下面的网络层读取结束后通知业务线程。
以上(1)(2)(3)(4)中都可以将业务线程(可以是线程池)独立,事先告之(1)、(2)、(3)、(4)中read所在线程(上面1、2、4都可以是线程池),需要读取的字符串结束标志或者需要读取的字符串个数,读取结束,则将clientfd/buffer指针放入业务线程的线程消息队列,业务线程读取消息队列处理业务。这也就是经典的proactor模拟。
总结:模型(1)是拓展select处理能力不错选择;模型(2)是模型(1)在爆发连接下的调整版本;模型(3)是经典的reactor,epoll在该模型下性能就已经很好,而select/poll仍然存在爆发连接的拒绝连接情况;模型(4)(5)则是方便业务处理,对模型(3)进行多线程调整的版本。带有复杂业务处理的情况下推荐模型(5)。根据测试显示,使用epoll的时候,模型(1)(2)相对(3)没有明显的性能优势,(1)由于主线程两次的系统调用,反而性能下降。
3、实时信号模型:
使用fcntl的F_SETSIG操作,把描述符可读的信号由不可靠的SIGIO(SYSTEM V)或者SIGPOLL(BSD)换成可靠信号。即可成为替代多路复用的方式。优于select/poll,特别是在大量死连接存在的情况下,但不及epoll。
四、多进程的参与的方式
(1)fork模型。fork后所有进程直接在accept阻塞。以上主线程在accept阻塞的都可以在accept前fork为多进程。同样面临惊群问题。
(2)fork模型。fork后所有进程阻塞在accept前的线程锁处。同线程中一样避免不支持所有进程直接阻塞在accept或者惊群问题,所有进程阻塞在共享内存上实现的线程互斥锁。
(3)业务和网络层分离为不同进程模型。这个模型可能是受unix简单哲学的影响,一个进程完成一件事情,复杂的事情通过多个进程结合管道完成。我见过进程方式的商业协议栈实现。自己暂时还没有写该模型的示例程序测试对比性能。
(4)均衡负载模型。起多个进程绑定到不同的服务端口,前端部署lvs等均衡负载系统,暴露一个网络地址,后端映射到不同的进程,实现可扩展的多进程方案。
总结:个人认为(1)(2)没什么意义。(3)暂不评价。(4)则是均衡负载方案,和以上所有方案不冲突。
以上模型的代码示例以及性能对比后面给出。



推荐阅读
  • WebBenchmark:强大的Web API性能测试工具
    本文介绍了一款名为WebBenchmark的Web API性能测试工具,该工具不仅支持HTTP和HTTPS服务的测试,还提供了丰富的功能来帮助开发者进行高效的性能评估。 ... [详细]
  • Asynchronous JavaScript and XML (AJAX) 的流行很大程度上得益于 Google 在其产品如 Google Suggest 和 Google Maps 中的应用。本文将深入探讨 AJAX 在 .NET 环境下的工作原理及其实现方法。 ... [详细]
  • 流处理中的计数挑战与解决方案
    本文探讨了在流处理中进行计数的各种技术和挑战,并基于作者在2016年圣何塞举行的Hadoop World大会上的演讲进行了深入分析。文章不仅介绍了传统批处理和Lambda架构的局限性,还详细探讨了流处理架构的优势及其在现代大数据应用中的重要作用。 ... [详细]
  • 深入理解线程池及其基本实现
    本文探讨了线程池的概念、优势及其在Java中的应用。通过实例分析不同类型的线程池,并指导如何构建一个简易的线程池。 ... [详细]
  • 本文详细探讨了在Java TCP编程中,如何理解和测量并发连接数、请求数及并发用户数,并提供了实际应用中的测试方法和优化建议。 ... [详细]
  • H5技术实现经典游戏《贪吃蛇》
    本文将分享一个使用HTML5技术实现的经典小游戏——《贪吃蛇》。通过H5技术,我们将探讨如何构建这款游戏的两种主要玩法:积分闯关和无尽模式。 ... [详细]
  • 本文介绍了SIP(Session Initiation Protocol,会话发起协议)的基本概念、功能、消息格式及其实现机制。SIP是一种在IP网络上用于建立、管理和终止多媒体通信会话的应用层协议。 ... [详细]
  • 我的读书清单(持续更新)201705311.《一千零一夜》2006(四五年级)2.《中华上下五千年》2008(初一)3.《鲁滨孙漂流记》2008(初二)4.《钢铁是怎样炼成的》20 ... [详细]
  • 深入探讨:Actor模型如何解决并发与分布式计算难题
    在现代软件开发中,高并发和分布式系统的设计面临着诸多挑战。本文基于Akka最新文档,详细探讨了Actor模型如何有效地解决这些挑战,并提供了对并发和分布式计算的新视角。 ... [详细]
  • JUC并发编程——线程的基本方法使用
    目录一、线程名称设置和获取二、线程的sleep()三、线程的interrupt四、join()五、yield()六、wait(),notify(),notifyAll( ... [详细]
  • 本文探讨了如何在PHP与MySQL环境中实现高效的分页查询,包括基本的分页实现、性能优化技巧以及高级的分页策略。 ... [详细]
  • Docker安全策略与管理
    本文探讨了Docker的安全挑战、核心安全特性及其管理策略,旨在帮助读者深入理解Docker安全机制,并提供实用的安全管理建议。 ... [详细]
  • 在使用 Nginx 作为服务器时,发现 Chrome 能正确从缓存中读取 CSS 和 JS 文件,而 Firefox 却无法有效利用缓存,导致加载速度显著变慢。 ... [详细]
  • 本文详细介绍了如何在Oracle VM VirtualBox中实现主机与虚拟机之间的数据交换,包括安装Guest Additions增强功能,以及如何利用这些功能进行文件传输、屏幕调整等操作。 ... [详细]
  • Jenkins API当前未直接提供获取任务构建队列长度的功能,因此需要通过解析HTML页面来间接实现这一需求。 ... [详细]
author-avatar
大约在冬季1122_867
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有