apache并发模型

并发模型

在讨论HTTP面对并发连接之前我们先讨论一下银行工作人员面对大量客户时的工作机制,其实银行的工作机制与HTTP的工作面对并发时的工作机制是类似的。

1.    如果一个银行在刚开业只有一个柜台,假设接待一个客户需要5分钟的话,那么如果同时来10个客户,只能先接待接待一个,让另外的9个人先等着排列,如果队列很多,很多人连大厅都坐不下,保安就不让排队了。

2.    银行的人员越来越多,然后开了10个柜台,同时来了100个用户,还有90个等待,为什么不能开100个柜台呢?你不考虑成本的吗!!又出现了队列很长,很多人连大厅都坐不下,保安就不让排队了。

3.    开10个柜台就已经是极限了,那么怎样才能加快工作的效率呢?我们可以做一些优化,原本一个柜台只有一个工作人员,服务一个客户需要2分种,现在每个柜台多个工作人员,第一个工作人员只负责接待,第两个工作人员负责打印票据,第三人工作人员负责处理文档……,当第两个工作人员打印票据的时候,第一个工作人员又可以为第二个客户服务,从客户的角度因为隔着窗户,只能看清最外面的负责接待的工作人员,其实里面有很多工作人员工作,这话的话一个服务一个客户可能仅需要几秒的时间。

WEB服务器的IO结构:(阅读下面的文字请参照上文当中银行的工作案例)

单线程结构:一次只能接收一个请求,余下的排队,也可以称做是单线程结构,因为在linux当中线程与进程的区别没什么差别,一般来讲linux一个进程里面也通常只有一个线程。

多线程多请求结构:每个用户都创建一个进程对应,但是创建的进程数是有限的

请注意是多请求结构而不是多用户结构,为什么?因为一个用户可以发起多个请求,有100个请求并不意味着有100个用户,多请求的是这样的,HTTP的主程序侦听到TCP80端口,一旦有有连接的话就把自己复制一份(生成一个子进程)到内存当中去处理连接的请求,而自己继续侦听TCP的80,当这个子进程处理完请求,构建好响应报文之后就会由其父进程将其销毁,也就是说必须有一个进程(父进程)做分配管理才行。

复用的IO结构:也叫做单进程多请求模型,一个进程可以响应多个请求,它是怎样做到的呢?向外看来是一个进程服务了多个请求,但是对内看来是这样的:服务于多个请求的进程是并不是单纯的一个进程,而是一个团队,这个进程里面有很多的“人”只是外人看起来是一个进程在响应多个请求。

既然有三种模型那么哪个占用的资源更少而且用户体验较好呢?

答:

在讲明白这个问题之前,首先理解一点:在进程的角度看内存,整个内存都由自己占用。

CPU进程的切换,切换本身就会浪费时间

单进程的坏处有:崩溃,机制复杂,稳定性来说多线程多请求更好,资源节约来讲单进程多请求最好。

服务器接入并响应过程

上图中的虚线指的是内核空间与用户空间的分隔.

其实上图中的七步就基本的描述了客户端访问站点的过程。下面用文字解释一下

1)    建立连接,当然是客户端先发起请求,与服务器完成三次握手之后建立连接

2)    接收请求,当服务器接收了请求之后,内核根据套节字把客户端要请求的请求资源交给应用程序

3)    处理请求,应用程序不能调用硬盘当中的资源肯定是找内核调用

4)    访问资源,内核去硬盘调用资源

5)    构建响应,应用程序要构建响应报文

6)    发送响应,通过套节字发送给客户端

7)    记录事务的处理过程,这一步也要IO

从IO的角度看待响应

第一步:客户端与服务器建立连接时,服务器的通信子网(内核)首先判断是不是给自己的数据,然后取出此数据访问的套节字,然后把数据的内容给侦听到此套节字的进程。

第二步:客户端的请求无非也就是请求资源,而资源一般都放在磁盘上,而资源子网的应用无权限访问磁盘,这时程序会发起系统调用,代码的执行由用户空间切换到了内核空间,然后内核去磁盘调用加载磁盘当中数据,那么问题来了?内核把数据调用到哪里去了?是直接把数据放在进程的内存空间了吗?

第三步:虽然内核有这个能力,但是没有那么做,内核通常把从磁盘调用的数据放在自己的内核空间的当中了,而这部分空间被我们称之为cache,然后再给进程多分配一些页框,最后把cache当中的数据复制一份到进程的页框当中,注意,进程没有权限访问内核空间的数据。

第四步:数据进入用户空间进程构建响应报文,提交给内核。

让我们总结一下:上文当中的数据流向是这样的:内核用户-----用户空间------内核空间--------用户空间------内核空间

通过上文我们可以知道被客户端请求的文件被调用了2次,,事实上所有的IO都是这样.

那么我们可不可以让内核调用完数据后不用交给内核直接给客户端响应呢?可能你会问,如果不交给应用层的应用的话怎样构建响应报文呢?事实上,内核是可以构建响应报文的,也就是说内核调用完资源之后直接给客户端回应不用经过用户空间构建响应报文,它是怎样做到的呢?在一个系统调用 sed-file可以帮助我们把构建响应报文,我们可以在httpd的配置文件当中,直接就调用它,这样的话,用户的访问的速度会加快很多,服务器本身的资源也会节省很多,就变成了下面这样:

从函数的角度看待响应

某个服务想要侦听到某个套接字上“坐诊”,必须要调用四个函数(如果是C语言):socket(),bind(),.listen(),accept(),首先,服务先人调用socket()API用来申请一个套接字,当然只申请完一个套接字是远远不够的,申请了之后要把自己(服务绑定(bind())到申请的套接字上,仅仅绑定还是不够,还要调用listen()API侦听在此套接字上,当申请、绑定、侦听完成之后接下来就可以“接客”了,会调用一个accept()API等待接收别人的访问,会处于一直阻塞的状态等待客户端的连接。

做为客户端同样也是需要申请套接字的socket(),申请完成之后就是下一步主动连接(connetct)服务端,建立连接有四个元素,源IP端口,目标IP端口,这也就是为什么客户端也要申请套接字的原因了,建立连接当然是通过三次握手建立 ,三次握手完成之间意味着从客户端到服务器的虚链路建立完成,虚链路建立完成之后就会把此虚链路保存成一个套接字文件(当然服务器也会这么做了),一切皆文件嘛!当然这个文件当中主要也就是有四个元素:本地的IP端口,服务器端的IP端口。下一步是客户端要向服务器发出一个申请,怎样发的呢?因为客户端有了虚链路的套接字文件以此来标识与服务器之间的连接,客户端发起请求时可以直接调用write()函数直接把请求的信息写入到套接字文件当中,然后客户端会通过此套接字连接起来的虚链路把请求发给服务器那边的套接字文件(当建立完成三次握手,服务器和客户端各自维护一个套接字),服务器端的套接字接收到请求之后,服务器端就要从套接字文件当中读出(read())一些信息出来,这里面就是服务器端的请求信息,请求的资源无非也就是服务器端磁盘的资源,很有可能是html文件,然后就处理请求,怎样处理呢?处理就非常的简单了,http通过内核去存储器当中读取数据,读取完之后构建响应报文,把响应报文写入到服务器自己维护的套接字文件当中,这下论到客户端方接收信息了,客户端就会去套节字文件当中读取资源,发现此资源并不完整,里面包含很多的图片,客户端会再向服务器端请求,服务器端会再次响应,循环下去直到资源完成。

当资源传输完成之后,客户端会终止此连接并且会向套节字当中发起close()终止信号,当服务器收到之后同样还是先读取,读取一看是是终止信息,于是自己也处于终止状态。客户端是主动关闭的,而服务器是被动关闭的。

日志处理

日志也会产生IO,每处理一份事务HTTP都会产生IO,那么这个IO如果每次都要写入到磁盘当中的话,IO次数太过频繁,影响服务器的性能,还好我们可以自己规定多长时间IO一次,比如我们规定1分钟IO一次,1分钟中所有的日志先暂时放入到内存里面,到了规定的时候,一块打包放入磁盘里面.这样的话能够减少一部分的IO.

如果规定的时间过长,一旦断电就都丢失的数据比较多,但是IO次数减少了

如果规定的时间过短,一旦断电丢失的数据比较少,但是IO次数要多一些.至于多少时间,自己选.

原文地址:https://www.cnblogs.com/yizhangheka/p/11038911.html

时间: 2024-10-12 09:08:29

apache并发模型的相关文章

nginx并发模型与traffic_server并发模型简单比较

ginx并发模型: nginx 的进程模型采用的是prefork方式,预先分配的worker子进程数量由配置文件指定,默认为1,不超过1024.master主进程创建监听套接口,fork子进程以后,由worker进程监听客户连接,每个worker子进程独自尝试accept已连接套接口,accept是否上锁可以配置,默认会上锁,如果操作系统支持原子整型,才会使用共享内存实现原子上锁,否则使用文件上锁.不使用锁的时候,当多个进程同时accept,当一个连接来的时候多个进程同时被唤起,会导致惊群问题.

课堂笔记--Strom并发模型

Strom并发模型: topology是如何运行的?(可与mapreduce对比) 第一层:cluster 第二层:supervisor(host.node.机器) 第三层:worker(进程) 第四层:executor(线程) 第五层:task(线程的一个个对象.如Spout和Blot) //topology:N workers==每个==>1 excutor=>1 task //此时,它和mapreduce那个是一样的 topology代码    conf.setNumWorkers(2)

Java并发模型(一)

学习资料来自http://ifeve.com/java-concurrency-thread-directory/ 一.多线程 进程和线程的区别: 一个程序运行至少一个进程,一个进程至少包含一个线程. 多线程: 多线程使得在一个程序内部能够拥有多个线程并行执行,一个线程的执行可以被认为是一个cpu在执行该程序,当一个程序运行在多线程下,就好像有多个CPU在同时执行该程序. 多线程在同一个程序内部并发执行,因此会对相同的内存空间进行并发读写操作. 思考: 如果一个线程在读一个内存时,另一个线程正向

并发模型之——基本概念

从很久之前在学校到现在我们编程的时候经常都有听说到并发编程,偶尔也会听到说并行,但我们很多人其实都不太清除并发与并行具体的区别在哪:我们刚开始学习编程语言的时候我相信我们写的都是串行程序,一步接着一步来,可以说这比并发程序更不容易出错,但在性能上要远不如并发:还有一种并发具有很强容错性:分布式程序,分布式程序也算是并发程序,还可以具有很强的容错性,可以分开部署:     并发与并行有着本质上的区别.     并发指程序在同一时间只能做一个操作,但是可以在不同的时间点()做多个操作:     如:

并发模型—共享内存模型(线程与锁)示例篇

共享内存模型,顾名思义就是通过共享内存来实现并发的模型,当多个线程在并发执行中使用共享资源时如不对所共享的资源进行约定或特殊处理时就会出现读到脏数据.无效数据等问题:而为了决解共享资源所引起的这些问题,Java中引入了同步.锁.原子类型等这些用于处理共享资源的操作; 在本篇文章中,将通过几个Demo来介绍Java的synchronized.lock.atomic相关类等,Java的共享内存并发模型也就体现在同步(synchronized).锁(lock)等这些实现上: 同步: Demo中开启两个

由Go语言并发模型想到游戏服务器并发

这段时间看了一些Go语言相关的东西,发现Go语言的最大特性并发模型类似于C++里面的线程池,正好我们项目服务器也是用的线程池,记录下. Go语言的并发单位是语言内置的协程,使用关键字go+函数创建一个新的协程,新创建的协程会自动加入到协程调度上下文的等待调度队列,一个协程调度上下文对应一个线程,一个协程调度上下文对应多个协程.新加入的协程会动态负载到各个调度上下文,如果所有调度上下文的平均负载较高时,总调度器会自动创建新的线程和对应的调度上下文用于工作.整体上看,是N个线程:N个调度上下文:M个

windows下修改apache并发数

还没有尝试 修改apache的最大连接数,方法如下: 步骤一 先修改 /path/apache/conf/httpd.conf文件. # vi httpd.conf 将“#Include conf/extra/httpd-mpm.conf”前面的 “#” 去掉,保存. 步骤二 再修改 /path/apache/conf/extra/httpd-mpm.conf文件. # vi httpd-mpm.conf 找到 这一行 原: StartServers 5 MinSpareServers 5 Ma

并发模型与Event Loop

JavaScript的并发模型基于"event loop".这个模型与其他在C或者Java中的模型着实不同. 运行时概念 下面的内容解释了一个理论上的模型.现代JavaScript引擎着重实现和优化了描述的几个语义. 可视化描述 栈 函数调用形成了一个frames的栈. function f(b){   var a = 12;   return a+b+35;}function g(x){   var m = 4;   return f(m*x);}g(21); 调用g的时候,创建了第

apache并发测试工具ab为什么测不准

apache并发测试工具ab为什么测不准 发表于2年前(2013-03-21 12:13)   阅读(1146) | 评论(1) 1人收藏此文章, 我要收藏 赞0 3月21日 深圳 OSC 源创会正在报名中,送华为海思开发板 apache ab linux 测试 测不准 我们常常使用apache下的并发测试工具ab进行动态或静态页面URL的并发测试,以此作为服务器性能.配置以及系统架构是否合乎要求的一个衡量标准. 但是有一个问题,就是ab的表现并不稳定,在不同的机器上用ab对同一个服务器上的UR