
web中间件
1中间件是什么
中间件(英语:Middleware)是提供系统软件和应⽤软件之间连接的软件,以便于软件各部件之间的沟通。中间件处在操作系统和更⾼⼀
级应⽤程序之间。他充当的功能是:将应⽤程序运⾏环境与操作系统隔离,从⽽实现应⽤程序开发者不必为更多系统问题忧虑,⽽直接关注
该应⽤程序在解决问题上的能⼒。容器就是中间件的⼀种。
也就是说,关于中间件,我们可以理解为:是⼀类能够为⼀种或多种应⽤程序合作互通、资源共享,同时还能够为该应⽤程序提供相关的服
务的软件。(注意:中间件是⼀类软件的总称,不是单独的⼀个软件)
我们经常管web中间件叫做web服务器或者web容器
正常情况下⼀次web的访问顺序是:web浏览器---服务器(硬件)---web容器---web应⽤服务器---数据库服务器。
2常见中间件简述
Tomcat
Tomcat是Apache软件基⾦会(ApacheSoftwareFoundation)的Jakarta项⽬中的⼀个核⼼项⽬,由Apache、Sun和其他⼀些公司
及个⼈共同开发⽽成。因为Tomcat技术先进、性能稳定,⽽且免费,因⽽深受Java爱好者的喜爱并得到了部分软件开发商的认可,成为
⽬前⽐较流⾏的JavaWeb应⽤服务器(Servlet容器)。实际上Tomcat部分是Apache服务器的扩展,但它是独⽴运⾏的,所以当你运⾏
tomcat时,它实际上作为⼀个与Apache独⽴的进程单独运⾏的。Tomcat服务器是⼀个免费的开放源代码的Web应⽤服务器,属于轻量
级应⽤服务器,在中⼩型系统和并发访问⽤户不是很多的场合下被普遍使⽤,是开发和调试JSP程序的⾸选。Tomcat默认使⽤8080号端
⼝
WebLogic是美国Oracle公司出品的⼀个applicationrver,确切的说是⼀个基于JAVAEE架构的中间件,WebLogic是⽤于开发、集
成、部署和管理⼤型分布式Web应⽤、⽹络应⽤和数据库应⽤的Java应⽤服务器。将Java的动态功能和JavaEnterpri标准的安全性引⼊
⼤型⽹络应⽤的开发、集成、部署和管理之中。Weblogic默认端⼝是7001。
Jboss是⼀个基于JavaEE的开放源代码的应⽤服务器。它不但是Servlet容器,⽽且也是EJB容器,从⽽受到企业级开发⼈员的欢迎,从
⽽弥补了Tomcat只是⼀个Servlet容器的缺憾。JBoss是⼀个管理EJB的容器和服务器。但JBoss核⼼服务不包括⽀持rvlet/JSP的
WEB容器,⼀般与Tomcat或Jetty绑定使⽤。Jboss默认端⼝号是8080。
Jetty是⼀个开源的rvlet容器,它为基于Java的web容器,例如JSP和rvlet提供运⾏环境。Jetty是使⽤JAVA编写的,它的API以⼀组
JAR包的形式发布。开发⼈员可以将Jetty容器实例化成⼀个对象,可以迅速为⼀些独⽴运⾏(stand-alone)的Java应⽤提供⽹络和web连
接。
WebShere是IBM的软件平台。它包含了编写、运⾏和监视全天候的⼯业强度的随需应变Web应⽤程序和跨平台、跨产品解决⽅案所需
要的整个中间件基础设施,如服务器、服务和⼯具。WebSphere提供了可靠、灵活和健壮的软件。WebSphere是⼀个模块化的平台,基
于业界⽀持的开放标准。可以通过受信任和持久的接⼝,将现有资产插⼊WebSphere,可以继续扩展环境。WebSphere可以在许多平台
上运⾏,包括Intel、Linux和z/OS。Webshere默认端⼝号是9080。
GlassFish是⼀款强健的商业兼容应⽤服务器,达到产品级质量,可免费⽤于开发、部署和重新分发。开发者可以免费获得源代码,还可以
对代码进⾏更改。
3常见WEB中间件细节
3.1Tomcat
3.1.1概念
Tomcat服务器是⼀个开源的轻量级Web应⽤服务器,在中⼩型系统和并发量⼩的场合下被普遍使⽤,是开发和调试Servlet、JSP程序
的⾸选。
3.1.2原理
Tomcat结构图:
Tomcat主要组件:服务器Server,服务Service,连接器Connector、容器Container。连接器Connector和容器Container是
Tomcat的核⼼。
⼀个Container容器和⼀个或多个Connector组合在⼀起,加上其他⼀些⽀持的组件共同组成⼀个Service服务,有了Service服务便可
以对外提供能⼒了,但是Service服务的⽣存需要⼀个环境,这个环境便是Server,Server组件为Service服务的正常使⽤提供了⽣存环
境,Server组件可以同时管理⼀个或多个Service服务。
3.1.3两⼤组件
1、Connector
⼀个Connecter将在某个指定的端⼝上侦听客户请求,接收浏览器的发过来的tcp连接请求,创建⼀个Request和Respon对象分
别⽤于和请求端交换数据,然后会产⽣⼀个线程来处理这个请求并把产⽣的Request和Respon对象传给处理Engine(Container中的
⼀部分),从Engine出获得响应并返回客户。
Tomcat中有两个经典的Connector,⼀个直接侦听来⾃Browr的HTTP请求,另外⼀个来⾃其他的WebServer请求。HTTP/1.1
Connector在端⼝8080处侦听来⾃客户Browr的HTTP请求,AJP/1.3Connector在端⼝8009处侦听其他WebServer(其他的
HTTP服务器)的Servlet/JSP请求。
Connector最重要的功能就是接收连接请求然后分配线程让Container来处理这个请求,所以这必然是多线程的,多线程的处理是
Connector设计的核⼼。
2、Container
Container是容器的⽗接⼝,该容器的设计⽤的是典型的责任链的设计模式,它由四个⾃容器组件构成,分别是Engine、Host、
Context、Wrapper。这四个组件是负责关系,存在包含关系。通常⼀个Servletclass对应⼀个Wrapper,如果有多个Servlet定义多个
Wrapper,如果有多个Wrapper就要定义⼀个更⾼的Container,如Context。
Context还可以定义在⽗容器Host中,Host不是必须的,但是要运⾏war程序,就必须要Host,因为war中必有⽂件,这
个⽂件的解析就需要Host了,如果要有多个Host就要定义⼀个top容器Engine了。⽽Engine没有⽗容器了,⼀个Engine代表⼀个
完整的Servlet引擎。
Engine容器
Engine容器⽐较简单,它只定义了⼀些基本的关联关系
Host容器
Host是Engine的⼦容器,⼀个Host在Engine中代表⼀个虚拟主机,这个虚拟主机的作⽤就是运⾏多个应⽤,它负责安装和展开
这些应⽤,并且标识这个应⽤以便能够区分它们。它的⼦容器通常是Context,它除了关联⼦容器外,还有就是保存⼀个主机应该有的
信息。
Context容器
Context代表Servlet的Context,它具备了Servlet运⾏的基本环境,理论上只要有Context就能运⾏Servlet了。简单的
Tomcat可以没有Engine和Host。Context最重要的功能就是管理它⾥⾯的Servlet实例,Servlet实例在Context中是以
Wrapper出现的,还有⼀点就是Context如何才能找到正确的Servlet来执⾏它呢?Tomcat5以前是通过⼀个Mapper类来管理
的,Tomcat5以后这个功能被移到了request中,在前⾯的时序图中就可以发现获取⼦容器都是通过request来分配的。
Wrapper容器
Wrapper代表⼀个Servlet,它负责管理⼀个Servlet,包括的Servlet的装载、初始化、执⾏以及资源回收。Wrapper是最底层的
容器,它没有⼦容器了,所以调⽤它的addChild将会报错。
Wrapper的实现类是StandardWrapper,StandardWrapper还实现了拥有⼀个Servlet初始化信息的ServletConfig,由此看出
StandardWrapper将直接和Servlet的各种信息打交道。
3、其他组件
Tomcat还有其它重要的组件,如安全组件curity、logger⽇志组件、ssion、mbeans、naming等其它组件。这些组件共同为
Connector和Container提供必要的服务。
3.1.4HTTP请求过程
TomcatServer处理⼀个HTTP请求的过程
1、⽤户点击⽹页内容,请求被发送到本机端⼝8080,被在那⾥监听的CoyoteHTTP/1.1Connector获得。
2、Connector把该请求交给它所在的Service的Engine来处理,并等待Engine的回应。
3、Engine获得请求localhost/test/,匹配所有的虚拟主机Host。
4、Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机),名为
localhost的Host获得请求/test/,匹配它所拥有的所有的Context。Host匹配到路径为/test的Context(如果匹配不到就把该
请求交给路径名为“”的Context去处理)。
5、path=“/test”的Context获得请求/,在它的mappingtable中寻找出对应的Servlet。Context匹配到URLPATTERN为
*.jsp的Servlet,对应于JspServlet类。
6、构造HttpServletRequest对象和HttpServletRespon对象,作为参数调⽤JspServlet的doGet()或doPost().执⾏业务逻辑、
数据存储等程序。
7、Context把执⾏完之后的HttpServletRespon对象返回给Host。
8、Host把HttpServletRespon对象返回给Engine。
9、Engine把HttpServletRespon对象返回Connector。
10、Connector把HttpServletRespon对象返回给客户Browr。
3.2Jetty
3.2.1什么是jetty?
简单来讲jetty就是⼀个开源HTTP服务器和Servlet引擎,它可以为JSP和Servlet提供运⾏时环境。⽐如Javaweb应⽤最常⽤的Servlet容
器和Tomcat。由于其轻量、灵活的特性,jetty也被应⽤于⼀些知名产品中,例如ActiveMQ、maven、spark、gooleAppEngine、
Eclip、Hadoop等。
3.2.2为什么使⽤jetty?
1.异步的Servlet,⽀持更⾼的并发量。
2.模块化的设计,更灵活,更容易定制,也意味着更⾼的资源利⽤率。
3.在⾯对⼤量长连接的业务场景下,jetty默认采⽤的NIO模型是更好的选择。
将jetty嵌⼊到应⽤中,使⼀个普通应⽤可以快速⽀持HTTP服务。
3.2.3与tomcat的对⽐
jetty⽐较容易贴合第三⽅框架,⽐如你可以直接⽤Spring配置⼀个jetty服务器
直接将jetty作为提供HTTP服务的组件,嵌⼊到应⽤中
jetty是⾯向Handler的架构,⽽tomcat是⾯向容器的架构
jetty默认采⽤NIO技术,⽽tomcat默认是BIO
jetty⾼度模块化,可以很灵活的管理拓展组件,⽽tomcat对其他组件的管理则相对困难
3.2.4jetty的基本架构
3.2.5jetty的项⽬结构
3.3Nginx
3.3.1代理服务器
Nginx就是反向代理服务器。
⾸先我们先来看看什么是代理服务器,代理服务器⼀般是指局域⽹内部的机器通过代理服务发送请求到互联⽹上的服务器,代理服务器⼀般
作⽤于客户端。⽐如GoAgent,FQ神器。
⼀个完整的代理请求过程为:客户端⾸先与代理服务器创建连接,然后根据代理服务器所使⽤的代理协议,请求对⽬标服务器创建连接、或
则获得⽬标服务器的指定资源。Web代理服务器是⽹络的中间实体。代理位于Web客户端和Web服务器之间,扮演“中间⼈”的⾓⾊。
HTTP的代理服务器既是Web服务器⼜是Web客户端。
代理服务器是介于客户端和Web服务器之间的另⼀台服务器,有了它之后,浏览器不是直接到Web服务器去取回⽹页,⽽是通过向代理服
务器发送请求,信号会先送到代理服务器,由代理服务器来取回浏览器所需要的信息并传送给你的浏览器。
正向代理是⼀个位于客户端和原始服务器之间的服务器,为了从原始服务器取的内容,客户端向代理发送⼀个请求并指定⽬标(原始服务
器),然后代理向原始服务器转交请求并将获得的内容返回给客户端,客户端必须要进⾏⼀些特别的设置才能使⽤正向代理。
反向代理服务器:在服务器端接收客户端的请求,然后把请求分发给具体的服务器进⾏处理,然后再将服务器的响应结果反馈给客户端。
Nginx就是其中的⼀种反向代理服务器软件。
Nginx:Nginx(“enginex”),Nginx是俄罗斯⼈IgorSysoev(塞索耶夫)编写的⼀款⾼性能的HTTP和反向代理服务器。也是⼀个
IMAP/POP3/SMTP代理服务器,也就是说,Nginx本⾝就可以托管⽹站,进⾏HTTP服务处理,也可以作为反向代理服务器使⽤。
正向代理客户端必须设置正向代理服务器,当然前提是要知道正向代理服务器的IP地址,还有代理程序的端⼝。
反向代理正好与正向代理相反,对于客户端⽽⾔代理服务器就像是原始服务器,并且客户端不需要进⾏任何特别的设置。客户端向反向代理
的命名空间中的内容发送普通请求,接着反向代理将判断向哪个原始服务器转交请求,并将获得的内容返回给客户端。
⽤户A始终认为它访问的是原始服务器B⽽不是代理服务器Z,但实际上反向代理服务器接受⽤户A的应答,
从原始资源服务器B中取得⽤户A的需求资源,然后发送给⽤户A。由于防⽕墙的作⽤,只允许代理服务器Z访问原始资源服务器B。尽管在
这个虚拟的环境下,防⽕墙和反向代理的共同作⽤保护了原始资源服务器B,但⽤户A并不知情。
简单的说:
正向代理:客户端知道服务器端,通过代理端连接服务器端。代理端代理的是服务器端。
反向代理:所谓反向,是对正向⽽⾔的。服务器端知道客户端,客户端不知道服务器端,通过代理端连接服务器端。代理端代理的是客户
端。代理对象刚好相反,所以叫反向代理。
的应⽤现状
Nginx已经在俄罗斯最⼤的门户⽹站──RamblerMedia()上运⾏了很多年,同时俄罗斯超过20%的虚拟主机平台采
⽤Nginx作为反向代理服务器。
在国内,已经有淘宝、新浪博客、新浪播客、⽹易新闻、六间房、、Discuz!、⽔⽊社区、⾖瓣、YUPOO、海内、迅雷在线等多
家⽹站使⽤Nginx作为Web服务器或反向代理服务器。
的特点
(1)跨平台:Nginx可以在⼤多数UnixlikeOS编译运⾏,⽽且也有Windows的移植版本。
(2)配置异常简单,⾮常容易上⼿。配置风格跟程序开发⼀样,神⼀般的配置
(3)⾮阻塞、⾼并发连接:数据复制时,磁盘I/O的第⼀阶段是⾮阻塞的。官⽅测试能够⽀撑5万并发连接,在实际⽣产环境中跑到2~3
万并发连接数.(这得益于Nginx使⽤了最新的epoll模型)
(4)事件驱动:通信机制采⽤epoll模型,⽀持更⼤的并发连接。
(5)master/worker结构:⼀个master进程,⽣成⼀个或多个worker进程
(6)内存消耗⼩:处理⼤并发的请求内存消耗⾮常⼩。在3万并发连接下,开启的10个Nginx进程才消耗150M内存
(15M*10=150M)
(7)成本低廉:Nginx为开源软件,可以免费使⽤。⽽购买F5BIG-IP、NetScaler等硬件负载均衡交换机则需要⼗多万⾄⼏⼗万⼈民币
(8)内置的健康检查功能:如果NginxProxy后端的某台Web服务器宕机了,不会影响前端访问。
(9)节省带宽:⽀持GZIP压缩,可以添加浏览器本地缓存的Header头。
(10)稳定性⾼:⽤于反向代理,宕机的概率微乎其微
如何使⽤事件驱动呢?
Nginx的事件处理机制:
对于⼀个基本的web服务器来说,事件通常有三种类型,⽹络事件、信号、定时器。
⾸先看⼀个请求的基本过程:建⽴连接---接收数据---发送数据。
再次看系统底层的操作:上述过程(建⽴连接---接收数据---发送数据)在系统底层就是读写事件。
1)如果采⽤阻塞调⽤的⽅式,当读写事件没有准备好时,必然不能够进⾏读写事件,那么久只好等待,等事件准备好了,才能进⾏读写事
件。那么请求就会被耽搁。阻塞调⽤会进⼊内核等待,cpu就会让出去给别⼈⽤了,对单线程的worker来说,显然不合适,当⽹络事件越
多时,⼤家都在等待呢,cpu空闲下来没⼈⽤,cpu利⽤率⾃然上不去了,更别谈⾼并发了。
2)既然没有准备好阻塞调⽤不⾏,那么采⽤⾮阻塞⽅式。⾮阻塞就是,事件,马上返回EAGAIN,告诉你,事件还没准备好呢,你慌什
么,过会再来吧。好吧,你过⼀会,再来检查⼀下事件,直到事件准备好了为⽌,在这期间,你就可以先去做其它事情,然后再来看看事
件好了没。虽然不阻塞了,但你得不时地过来检查⼀下事件的状态,你可以做更多的事情了,但带来的开销也是不⼩的
⼩结:⾮阻塞通过不断检查事件的状态来判断是否进⾏读写操作,这样带来的开销很⼤。
3)因此才有了异步⾮阻塞的事件处理机制。具体到系统调⽤就是像lect/poll/epoll/kqueue这样的系统调⽤。他们提供了⼀种机制,让
你可以同时监控多个事件,调⽤他们是阻塞的,但可以设置超时时间,在超时时间之内,如果有事件准备好了,就返回。这种机制解决了我
们上⾯两个问题。
以epoll为例:当事件没有准备好时,就放⼊epoll(队列)⾥⾯。如果有事件准备好了,那么就去处理;如果事件返回的是EAGAIN,那么继续
将其放⼊epoll⾥⾯。从⽽,只要有事件准备好了,我们就去处理她,只有当所有时间都没有准备好时,才在epoll⾥⾯等着。这样,我们就
可以并发处理⼤量的并发了,当然,这⾥的并发请求,是指未处理完的请求,线程只有⼀个,所以同时能处理的请求当然只有⼀个了,只是
在请求间进⾏不断地切换⽽已,切换也是因为异步事件未准备好,⽽主动让出的。这⾥的切换是没有任何代价,你可以理解为循环处理多
个准备好的事件,事实上就是这样的。
4)与多线程的⽐较:
与多线程相⽐,这种事件处理⽅式是有很⼤的优势的,不需要创建线程,每个请求占⽤的内存也很少,没有上下⽂切换,事件处理⾮常的轻
量级。并发数再多也不会导致⽆谓的资源浪费(上下⽂切换)。
⼩结:通过异步⾮阻塞的事件处理机制,Nginx实现由进程循环处理多个准备好的事件,从⽽实现⾼并发和轻量级。
的不为⼈知的特点
(1)nginx代理和后端web服务器间⽆需长连接;
(2)接收⽤户请求是异步的,即先将⽤户请求全部接收下来,再⼀次性发送后后端web服务器,极⼤的减轻后端web服务器的压⼒
(3)发送响应报⽂时,是边接收来⾃后端web服务器的数据,边发送给客户端的
(4)⽹络依赖型低。NGINX对⽹络的依赖程度⾮常低,理论上讲,只要能够ping通就可以实施负载均衡,⽽且可以有效区分内⽹和外⽹流
量
(5)⽀持服务器检测。NGINX能够根据应⽤服务器处理页⾯返回的状态码、超时信息等检测服务器是否出现故障,并及时返回错误的请求
重新提交到其它节点上
的内部(进程)模型
nginx是以多进程的⽅式来⼯作的,当然nginx也是⽀持多线程的⽅式的,只是我们主流的⽅式还是多进程的⽅式,也是nginx的默认⽅式。
nginx采⽤多进程的⽅式有诸多好处.
(1)nginx在启动后,会有⼀个master进程和多个worker进程。master进程主要⽤来管理worker进程,包含:接收来⾃外界的信号,向各
worker进程发送信号,监控worker进程的运⾏状态,当worker进程退出后(异常情况下),会⾃动重新启动新的worker进程。⽽基本的⽹络
事件,则是放在worker进程中来处理了。多个worker进程之间是对等的,他们同等竞争来⾃客户端的请求,各进程互相之间是独⽴的。
⼀个请求,只可能在⼀个worker进程中处理,⼀个worker进程,不可能处理其它进程的请求。worker进程的个数是可以设置的,⼀般我
们会设置与机器cpu核数⼀致,这⾥⾯的原因与nginx的进程模型以及事件处理模型是分不开的。
(2)Master接收到信号以后怎样进⾏处理(./nginx-sreload)?⾸先master进程在接到信号后,会先重新加载配置⽂件,然后再启动新的
进程,并向所有⽼的进程发送信号,告诉他们可以光荣退休了。新的进程在启动后,就开始接收新的请求,⽽⽼的进程在收到来⾃master
的信号后,就不再接收新的请求,并且在当前进程中的所有未处理完的请求处理完成后,再退出.
(3)worker进程⼜是如何处理请求的呢?我们前⾯有提到,worker进程之间是平等的,每个进程,处理请求的机会也是⼀样的。当我们提
供80端⼝的http服务时,⼀个连接请求过来,每个进程都有可能处理这个连接,怎么做到的呢?⾸先,每个worker进程都是从master进
程fork(分配)过来,在master进程⾥⾯,先建⽴好需要listen的socket之后,然后再fork出多个worker进程,这样每个worker进程都可以
去accept这个socket(当然不是同⼀个socket,只是每个进程的这个socket会监控在同⼀个ip地址与端⼝,这个在⽹络协议⾥⾯是允许
的)。⼀般来说,当⼀个连接进来后,所有在accept在这个socket上⾯的进程,都会收到通知,⽽只有⼀个进程可以accept这个连接,其它
的则accept失败,这是所谓的惊群现象。当然,nginx也不会视⽽不见,所以nginx提供了⼀个accept_mutex这个东西,从名字上,我们
可以看这是⼀个加在accept上的⼀把共享锁。有了这把锁之后,同⼀时刻,就只会有⼀个进程在accpet连接,这样就不会有惊群问题了。
accept_mutex是⼀个可控选项,我们可以显⽰地关掉,默认是打开的。当⼀个worker进程在accept这个连接之后,就开始读取请求,解
析请求,处理请求,产⽣数据后,再返回给客户端,最后才断开连接,这样⼀个完整的请求就是这样的了。我们可以看到,⼀个请求,完全
由worker进程来处理,⽽且只在⼀个worker进程中处理。
(4)nginx采⽤这种进程模型有什么好处呢?采⽤独⽴的进程,可以让互相之间不会影响,⼀个进程退出后,其它进程还在⼯作,服务不会中
断,master进程则很快重新启动新的worker进程。当然,worker进程的异常退出,肯定是程序有bug了,异常退出,会导致当前worker
上的所有请求失败,不过不会影响到所有请求,所以降低了风险。当然,好处还有很多,⼤家可以慢慢体会。
(5)有⼈可能要问了,nginx采⽤多worker的⽅式来处理请求,每个worker⾥⾯只有⼀个主线程,那能够处理的并发数很有限啊,多少个
worker就能处理多少个并发,何来⾼并发呢?⾮也,这就是nginx的⾼明之处,nginx采⽤了异步⾮阻塞的⽅式来处理请求,也就是
说,nginx是可以同时处理成千上万个请求的.对于IIS服务器每个请求会独占⼀个⼯作线程,当并发数上到⼏千时,就同时有⼏千的线程在
处理请求了。这对操作系统来说,是个不⼩的挑战,线程带来的内存占⽤⾮常⼤,线程的上下⽂切换带来的cpu开销很⼤,⾃然性能就上不
去了,⽽这些开销完全是没有意义的。我们之前说过,推荐设置worker的个数为cpu的核数,在这⾥就很容易理解了,更多的worker数,
只会导致进程来竞争cpu资源了,从⽽带来不必要的上下⽂切换。⽽且,nginx为了更好的利⽤多核特性,提供了cpu亲缘性的绑定选项,
我们可以将某⼀个进程绑定在某⼀个核上,这样就不会因为进程的切换带来cache的失效
是如何处理⼀个请求
⾸先,nginx在启动时,会解析配置⽂件,得到需要监听的端⼝与ip地址,然后在nginx的master进程⾥⾯,先初始化好这个监控的
socket(创建socket,设置addrreu等选项,绑定到指定的ip地址端⼝,再listen),然后再fork(⼀个现有进程可以调⽤fork函数创建⼀
个新进程。由fork创建的新进程被称为⼦进程)出多个⼦进程出来,然后⼦进程会竞争accept新的连接。此时,客户端就可以向nginx发起
连接了。当客户端与nginx进⾏三次握⼿,与nginx建⽴好⼀个连接后,此时,某⼀个⼦进程会accept成功,得到这个建⽴好的连接
的socket,然后创建nginx对连接的封装,即ngx_connection_t结构体。接着,设置读写事件处理函数并添加读写事件来与客户端进⾏数
据的交换。最后,nginx或客户端来主动关掉连接,到此,⼀个连接就寿终正寝了。
当然,nginx也是可以作为客户端来请求其它rver的数据的(如upstream模块),此时,与其它rver创建的连接,也封装在
ngx_connection_t中。作为客户端,nginx先获取⼀个ngx_connection_t结构体,然后创建socket,并设置socket的属性(⽐如⾮阻
塞)。然后再通过添加读写事件,调⽤connect/read/write来调⽤连接,最后关掉连接,并释放ngx_connection_t。
nginx在实现时,是通过⼀个连接池来管理的,每个worker进程都有⼀个独⽴的连接池,连接池的⼤⼩是worker_connections。这⾥的连
接池⾥⾯保存的其实不是真实的连接,它只是⼀个worker_connections⼤⼩的⼀个ngx_connection_t结构的数组。并且,nginx会通过⼀
个链表free_connections来保存所有的空闲ngx_connection_t,每次获取⼀个连接时,就从空闲连接链表中获取⼀个,⽤完后,再放回空
闲连接链表⾥⾯。
在这⾥,很多⼈会误解worker_connections这个参数的意思,认为这个值就是nginx所能建⽴连接的最⼤值。其实不然,这个值是表⽰每
个worker进程所能建⽴连接的最⼤值,所以,⼀个nginx能建⽴的最⼤连接数,应该是worker_connections*worker_process。当
然,这⾥说的是最⼤连接数,对于HTTP请求本地资源来说,能够⽀持的最⼤并发数量是worker_connections*worker_process,⽽
如果是HTTP作为反向代理来说,最⼤并发数量应该是worker_connections*worker_process/2。因为作为反向代理服务器,每个并
发会建⽴与客户端的连接和与后端服务的连接,会占⽤两个连接。
本文发布于:2023-03-14 02:36:18,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/zhishi/a/167873257828943.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:goagent.doc
本文 PDF 下载地址:goagent.pdf
| 留言与评论(共有 0 条评论) |