`
pengpeng
  • 浏览: 84847 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

[原]客户/服务器程序设计范式

阅读更多

 

                           本篇从基于TCP/IP协议出发,探讨现代流行的应对高并发请求网络服务端设计架构;

1. TCP/IP 模型

首先回顾一下TCP/IP模型,并知道各个层次在操作系统的哪一个层次; 

   看上图,OSI模型的底下两层是随系统提供的设备驱动程序和网络硬件。通常情况下,除需知道数据链路的某些特性外,我们不用关心这两层的情况。网络层由IPv4和IPv6两个协议处理,可以选择的传输层有TCP或UDP。OSI模型的顶上三层被合并为一层,称为应用层,这就是web客户(浏览器)、telnet客户、web服务器等都所在的层。

   可见OSI模型以传输层为分界线;套接字编程接口为应用层进入传输层的接口;也符合抽象的目的:对应用层隐藏网络协议的具体通信细节,应用层只处理具体网络应用;而底下四层(从传输层到物理层)对具体网络应用了解不多,却处理所有的通信细节:发送数据,等待确认,给无序到达的数据排序,计算并验证校验和,等等。

   其次,顶上三层通常构成所谓的用户进程,底下四层却通常作为操作系统内核的一部分提供。完全符合Unix和其他现代操作系统都提供分割用户进程和内核的机制。

2. 基本TCP 套接字编程

   TCP:传输控制协议(Transmission Control Protocol).TCP是一个面向连接的协议,为用户进程提供可靠的全双工字节流。TCP套接字是一种流套接字(stream socket). TCP关心确认,超时和重传之类的细节。大多数网络应用程序使用TCP;

    以apache为例子;apache工作在OSI模型的应用层;我们都知道启动apache后他会监听在80端口,并通过线程池来响应每个客户请求;即来一个客户请求,从连接池那出一个线程去处理这个请求;那么apache的内部是如何针对每个请求创建套接字,然后分配一个线程的呢?

    看图2,apache服务器启动后通过创建监听套接字listensocket,通过调用bind(),listen(),accept(),让主线程监听在80端口;客户请求过来后tcp三次握手,握手成功后accept()返回一个已连接套接字connsocket,代表与所返回客户的tcp连接;然后apache从连接池里拉出一个线程,并将这个已连接套接字给这个线程,让次线程处理这个请求;请求处理完毕后关闭连接,已连接套接字相应的回收;

注:监听套接字(listening socket)是在该tcp服务进程生命周期内一直存在。而已连接套接字代表一个和客户请求建立的一个套接字,生命周期为一次请求;



 

                     图2 : 基本TCP客户/服务器程序套接字函数

注:我们的jms客户端程序也是采用主线程监听队列消息,并将收到的消息给线程池里的一个线程去处理的方式来并发处理消息;

3. 现代并发web服务器的设计范式:

     但是apache真的是一个主线程在监听80端口么? 不是的,一个主线程监听80端口,然后将已连接套接字抛给线程池里的线程去处理,有些缺点;

     缺点如下:1. 只有一个线程监听80端口,并负责三次握手和转发已连接套接字;万一此线程挂了,整个web server就没有服务能力了,容错能力不强;

                    2. 因为connect(),accept()都是阻塞函数。所以每个客户请求来都阻塞在主线程,导致不能很好的应对并发;

     基于这些缺点;apache采用每个线程都去监听80端口,当然同一时刻,只有一个线程在监听80端口;其他线程属于空闲状态;一个客户请求过来,正在监听的线程会处理这个请求并转换为工作者线程;并让出监听者的角色,这样其他线程竞争监听者的角色,并最终有一个线程监听80端口;当一个工作线程处理完请求后,回到连接池中,又处于空闲状态;

但是这样又有问题,如果一个客户请求过来,会导致所有的空闲线程都去竞争监听者的角色。会导致很多空闲线程一下被唤醒,并只有一个线程获得监听者角色,其他线程继续空闲(睡觉),这种大批线程从空闲状态突然被唤醒有突然又睡过去,就是惊群现象;惊群现象会导致性能下降;

     apache通过在每个accept()函数上  增加互斥锁和条件变量   来解决这个惊群问题。保证每个请求只会被一个线程刚好拿到,不会影响其他线程;

       这里详细介绍下: 条件变量与互斥锁不同,条件变量是用来等待而不是用来上锁的。条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。通常条件变量和互斥锁同时使用;互斥锁提供互斥机制,条件变量提供信号机制;
     那么apache是如何利用条件变量和互斥锁来解决每次只有一个空闲线程被唤醒,并且处于监听者角色呢?
     每次一个新的客户请求过来,正在监听的线程与该请求建立连接,并变为worker工作者线程。让出监听者角色时它同时发送信号到条件变量,并释放锁。这样在空闲(idle)状态的一个线程将被唤醒并获得锁。

     也就是说:条件变量保证了其他线程在等待条件变化期间处于睡眠;互斥锁保证一次只有一个线程被唤醒;


                                                      图3 :apache 的preforking 机制

 

 

总结:通过了解了TCP/IP编程模型。和apache的MPM、Preforking机制后,我们再去看jms消息客户端代码,memcache服务器代码,jetty,等流行的web服务器的机制就不是很难了。

                                                                                                                                                       参考:《UNIX网络编程 卷1 :套接字联网API》

分享到:
评论

相关推荐

    UNIX网络编程卷1:套接字联网API(第3版)part1 共2部分

    第一部分 简介和TCP/IP 第1章 简介 ... 第30章 客户/服务器程序设计范式 第31章 流 附录A IPv4、IPv6、ICMPv4和ICMPv6 附录B 虚拟网络 附录C 调试技术 附录D 杂凑的源代码 附录E 精选习题答案 参考文献 索引

    UNIX网络编程 卷1:套接字联网API

    第一部分 简介和TCP/IP ...第30章 客户/服务器程序设计范式 第31章 流 附录A IPv4、IPv6、ICMPv4和ICMPv6 附录B 虚拟网络 附录C 调试技术 附录D 杂凑的源代码 附录E 精选习题答案 参考文献 索引

    UNIX网络编程卷2进程间通信(第2版)

    进程间通信(IPC)几乎是所有Unix程序性能的关键,理解IPC也是理解如何开发不同主机间网络应用程序的必要条件。本书从对Posix IPC和System V IPC的内部结构...第30章 客户/服务器程序设计范式 第31章 流 第4部分 附录?

    JAVA 语言与其程序设计范式

    Java语言是一种广泛使用的高级编程语言...综上所述,Java语言及其程序设计范式是学习软件开发不可或缺的知识点,无论你是初学者还是经验丰富的开发者,都能从中找到适合自己的工具和方法,构建出稳定、高效的软件系统。

    面向对象程序设计试题A

    面向对象程序设计(Object-Oriented Programming,简称OOP)是一种编程范式,它使用“对象”来设计软件。对象是由数据(属性或字段)和代码(方法或函数)组成的实体,它们可以执行特定的操作。面向对象程序设计的...

    WEB程序设计课件第一章

    学习者需要了解服务器端和客户端的概念,以及存在的各种网络程序设计语言。同时,课程设置了平时成绩和期末考试的考核方式,鼓励学生在实践中深化理解。 网络程序设计语言的发展深受Internet起源的影响。最初,网页...

    2009 系统架构师大会PPT 应用服务器架构设计(PDF格式)

    4. **高性能服务器程序设计** - 肖彬的论文《高性能服务器程序设计》深入讲解了如何设计和实现能够处理大规模并发请求的服务器程序。这可能涉及到多线程编程、异步I/O模型、非阻塞算法、内存管理策略以及并行计算...

    Delphi7 高效数据库程序设计

    最后,数据库设计的原则和范式也是高效程序设计的基础。了解第一范式(1NF)、第二范式(2NF)、第三范式(3NF)以及更高范式,可以帮助你创建更合理、更易于维护的数据模型。 综上所述,《Delphi7 高效数据库程序...

    面向对象程序设计试题B

    面向对象程序设计是一种重要的编程范式,它将数据和处理数据的方法封装在一起,形成对象,通过对象之间的交互来实现程序的功能。2011年的面向对象程序设计考试真题(上机部分)提供了对这一主题深入理解的机会,尤其...

    UNIX网络编程 第2卷 进程间通信.pdf(带书签)

    第四部分是本卷的补充,提供了多个附录,这些附录包含了作者认为对理解本书内容有帮助的额外信息,比如客户/服务器程序设计范式、流的概念等。这些内容有助于读者深化对进程间通信各个方面的理解,并能够更好地应用...

    《Python语言程序设计基础(第二版PDF+课件+源代码)》,嵩天,礼欣,高教.zip

    《Python语言程序设计基础》是由嵩天和礼欣两位作者合作编著的教材,第二版在高教出版社出版。这本书是Python编程初学者的理想选择,它深入浅出地介绍了Python编程的基本概念和技术,旨在帮助读者掌握Python编程的...

    PLSQL程序设计

    PL/SQL(Procedure Language & Structured Query Language)是一种高级数据库程序设计语言,特别为Oracle数据库设计,它扩展了SQL语言,允许开发者编写存储过程、函数、包、触发器等数据库对象。PL/SQL代码集成于...

    吉首大学网站程序设计上题目答案

    5. **数据库操作**:对SQL语言的理解,包括CRUD(创建、读取、更新、删除)操作,以及数据库设计(如关系模型、范式理论)是网站程序设计中的重要组成部分。 6. **网络基础知识**:理解TCP/IP协议、HTTP/HTTPS协议...

    java程序设计教程

    - **面向对象编程(OOP)**: 是一种程序设计范式,它使用“对象”来设计软件。对象是指包含数据和操作这些数据的方法的实体。 - **核心概念**: 封装、继承、多态。封装保护了对象的状态不被外部直接访问;继承允许子类...

    Java面向对象程序设计面向对象程序设计_名词解释

    OOP(Object-Oriented Programming,面向对象程序设计)是一种编程范式,其基本概念是将数据(属性)和操作数据的方法(行为)封装在一个对象中。一个对象可以包含多个实例变量和方法,这样可以模拟现实世界中的一些...

    Erlang程序设计,包含完整目录和全套源码

    这个压缩包包含了Erlang程序设计的完整目录和源码,是学习和理解Erlang编程的重要资源。 Erlang的并发特性源于其轻量级进程模型,每个进程都有自己的内存空间,进程间通信通过消息传递实现,这种设计降低了并发执行...

    软件工程软件设计推选PPT文档.ppt

    两层客户/服务器结构是一种常见的软件设计模型。在这种模型中,系统的逻辑分层分别实现在不同的物理层(物理机器)上,通常将这种物理层次上的划分称为客户端程序和服务器端程序。 三层/多层应用模型是两层C/S模型...

Global site tag (gtag.js) - Google Analytics