Apache httpd 学习总结

以下所总结仅是学习记录,如有不对的部分,还请及时指出,十分感谢
参考文档目录都在末尾写出了作者的链接,有兴趣的可以直接点击

Apache httpd 简介

  • apache和httpd区别
  • httpd配置相关目录
  • httpd配置文件
  • https运行模式–MPM
  • httpd虚拟主机的配置
  • httpd命令使用
  • mod_wsgi介绍

附录小知识

  1. 如何查看某个进程的线程数
  2. httpd process 和 wsgi process
  3. DFOREGROUND 含义
  4. 查看apache当前并发访问数和进程数 ApacheLinux 常用web服务器对比

Apache httpd 简介

Apache HTTPD又可以简称为httpd或者Apache,它是Internet使用最广泛的web服务器之一,使用Apache提供的web服务器是由守护进程httpd,通过http协议进行文本传输,默认使用80端口的明文传输方式,当然,后来,为了保证数据的安全和可靠性,又添加了443的加密传输的方式,Apache提供的服务器又被称为:补丁服务器,原因很简单,它是一款高度模块化的软件,想要给它添加相应的功能只需添加相应的模块,让其Apache主程序加载相应的模块,不需要的模块也可以不用加载,保证了Apache的简洁,轻便,高效性,当出现大量访问一个服务器是可以使用多种复用模式,保证了服务器能快速回应客户端的请求,如MPM,端口复用技术。

apache和httpd区别

从我们仅仅web服务器使用者的角度说的话,它们是同一个东西。在 Apache 的网站上有两种安装包下载
httpd-2.0.50-i686-pc-linux-gnu.tar.gz 和 apache_1.3.33-i686-whatever-linux22.tar.gz
其实都是提供Web服务的,只是一个是早期版一个是新的版本模式。httpd是apache开源项目的一部分,如果只需要web服务器,现在只需安装httpd2.*就可以了。

和 “Apache” 的历史有关。可以参考官方介绍:http://httpd.apache.org/ABOUT_APACHE.html

早 期的Apache小组,现在已经成为一个拥有巨大力量的Apache软件基金会,而apache现在成为 apache基金会下几十种开源项目的标识。其中有一个项目做HTTP Server,httpd是HTTP Server的守护进程,在Linux下最常用的是Apache,所以一提到httpd就会想到Apache HTTP Server。
他们把起 家的apache更名为httpd,也更符合其http server的特性。以前apache的http server在1.3的时候直接叫apache_1.3.37,现在2.*版本的都叫httpd_2.2.3。在Linux下最常用的是Apache,所 以一提到httpd就会想到Apache HTTP Server。

对于nginx/mod_wsgi,请确保阅读:

http://blog.dscpl.com.au/2009/05/blocking-requests-and-nginx-version-of.html

httpd配置相关目录

[root@localhost ~]# cd /etc/httpd
[root@localhost httpd]# tree .
.
|-- conf
|   |-- httpd.conf
|   `-- magic
|-- conf.d
|   |-- README
|   |-- proxy_ajp.conf
|   `-- welcome.conf
|-- logs -> ../../var/log/httpd
|-- modules -> ../../usr/lib/httpd/modules
`-- run -> ../../var/run

第一,httpd的主配置文件是/etc/httpd/conf/httpd.conf

第二,在httpd.conf文件中通过include指令将conf.d/*.conf进行包含,也就是说,以后我们可以在conf.d目录下新增自己的配置文件。

第三,对于WEB服务器而言,都有一个功能,那就是记录访问,错误日志。HTTPD的日志目录在/var/log/httpd下。

第四,HTTPD的一个特性,就是模块化设计。我们可以增加模块来添加功能。

httpd配置文件

下面的三个文件分别是主配置文件和辅助配置文件,以及模块配置文件,对主配置文件进行分割方便管理,在重启服务或者重新加载配置文件时会一并加载

/etc/httpd/conf/httpd.conf # 主配置文件,这个是httpd最主要的配置文档

/etc/httpd/conf.d/*.conf # 扩展配置文件,这个是httpd的额外配置文档

/etc/httpd/conf.modules.d/*.conf # 模块相关的配置文件

/var/www/html # 文档根目录,这个是apache 首页的文档目录 ,即输入http://127.0.0.1 显示页面所在的目录

/etc/rc.d/init.d/httpd # 服务脚本

/var/www/error # 错误目录,服务器设定错误,请求的资源错误或浏览器访问出现错误等错误文件的存储目录

/var/www/cgi-bin/ # CGI目录,预设为CGI运行脚本的存储目录

/etc/sysconfig/httpd # 脚本配置文件

/usr/sbin/apachectl ,/usr/sbin/httpd,/usr/bin/htpasswd # 命令执行文件

/var/run/httpd/httpd.pid # PID文件

模块的加载格式为:

LoadModule 模块名 模块存放路径

UnitFile:/usr/lib/systemd/system/httpd.service //Unit文件是rhel7之后的版本系统服务脚本启动文件

模块文件目录:

/usr/lib64/httpd/modules/

站点主服务器根目录默认:

/var/www/httpd/

日志文件:

/var/log/httpd/

​ error_log 错误日志

​ access_log 访问日志

下面是 /etc/httpd/conf/httpd.conf 简单配置的解释:

# 1. ServerRoot:服务器的基础目录,一般来说它将包含conf/和logs/子目录,其它配置文件的相对路径即基于此目录。默认为安装目录,不需更改。
# 语法:ServerRoot directory-path
# 如: ServerRoot "/usr/local/apache-2.2.6"
ServerRoot "/etc/httpd"

# 加载其它配置文件,类似于C语言的头文件的加载,此处可以使用相对路径也可以使用绝对路径,相对路径是相对于ServerRoot的路径,可以使用glob通配符,此处的配置文件是用来加载DSO(dynamic shared object)模块
Include conf.modules.d/*.conf

# 程序运行时的用户名和组名,在安装Apache时已经创建了系统账号和组账号,程序启动时是以root身份启动,执行完root特权的所有操作后(例如启动监听80端口,低于1024的端口的监听需要root才有权力执行)会以非特权用户执行程序
User apache
Group apache

# 管理员的邮箱地址,当httpd出问题时,联系该邮箱地址可以联系到管理员
ServerAdmin root@localhost

# 关于目录的一些配置,有关目录的访问权限等都是在这里定义,可以使用基于URL定义访问权限,但要使用<Location “”> …<Location>来定义
<Directory />
		# AllowOverride参数就是指明Apache服务器是否去找.htacess文件作为配置文件,如果设置为none,那么服务器将忽略.htacess文件,如果设置为All,那么所有在.htaccess文件里有的指令都将被重写。对于AllowOverride,还可以对它指定如下一些能被重写的指令类型.
    AllowOverride none
    # 对目录的授权此处为拒绝所有访问
    Require all denied
</Directory>

# 定义目录的根位置类似于配置文件的根,不过此处是网页存放的根,在定义Directory目录时,那里的目录同样可以是绝对路径,也可以是相对于此处的路径
DocumentRoot "/var/www/html"

# 此处为仅在加载了模块dir_module 后才执行,DirectoryIndex配置指令后面的值可以跟多个,先后顺序很关键,值的含义为URL访问时进入目录是应该寻找哪一个文件,多个时按顺序寻找,找不到第一个然后寻找第二个值
<Directory "/var/www">
    AllowOverride None
    Require all granted
</Directory>
<Directory "/var/www/html">
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>
<IfModule dir_module>
    DirectoryIndex index.html
</IfModule>

# 对所有安全相关的敏感文件设置为禁止,如目录下的.htaccess,.htpasswd
<Files ".ht*">
    Require all denied
</Files>

# 设置错误日志的存放路径,这里是一个软链接,指向/var/log/httpd/的符号链接
ErrorLog "logs/error_log"

# 设置日志级别,仅达到该级别才记录日志
LogLevel warn

<IfModule log_config_module>
		# 下面定义了多种日志的记录格式,可以人为的修改自己想要定义的格式,LogFormat后面的双引号具体定义了日志的格式,后面有一个名字,在使用该定义好的格式可以使用后面的别名代替,当然也可以在使用时直接用双引号加相应的格式,访问日志也可以在虚拟主机中单独定义
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b" common
    <IfModule logio_module>
      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>
    # 下面定义问日志,和使用相应的格式为combined
    CustomLog "logs/access_log" combined
</IfModule>

<IfModule alias_module>
		# ScriptAlias和Alias类似都是在此定义,两者的区别是ScriptAlias是作为服务器的运行文件,而不是发送到客户端的文件
    ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
</IfModule>

<Directory "/var/www/cgi-bin">
    AllowOverride None
    Options None
    Require all granted
</Directory>

# mime多媒体英特网邮件扩展,这个模块是用来指定内容元数据,选择HTTP响应的映射模式中的URI或文件的元数据值的内容。如mime-type中的类型有语言,字符集,编码方式
<IfModule mime_module>
    TypesConfig /etc/mime.types
    AddType application/x-compress .Z
    AddType application/x-gzip .gz .tgz
    AddType text/html .shtml
    AddOutputFilter INCLUDES .shtml
</IfModule>

# 下面的设置向text/plain和text/html 资源的content-type报头中添加charset部分。
AddDefaultCharset UTF-8
<IfModule mime_magic_module>
    MIMEMagicFile conf/magic
</IfModule>

# 控制httpd是否可以使用操作系统内核的sendfile支持来将文件发送到客户端。
EnableSendfile on

IncludeOptional conf.d/*.conf

更加具体的配置文件信息可见下面的链接,作者介绍的很详细

https://blog.csdn.net/number_chc/article/details/38978567?utm_medium=distribute.pc_relevant_t0.none-task-blog-OPENSEARCH-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-OPENSEARCH-1.channel_param

https://blog.csdn.net/fzjw/article/details/87662?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

https运行模式–MPM

MPM模块在httpd-2.4中是动态共享模块的,没有编译如主程序当中,httpd-2. 2中是静态编译入主程序当中的。在这些模型中,默认使用第一个prefork模型,第二个模型因为出错不以排查,因此使用较少,在第三个模型当中因为是比较新的功能,只有在httpd-2.4之后的版本才有的功能,所以使用较少,因为在企业使用时稳定才是王道,绝非功能越新越好

配置文件在:/etc/httpd/conf.modules.d/00-mpm.conf

# Select the MPM module which should be used by uncommenting exactly
# one of the following LoadModule lines:

# prefork MPM: Implements a non-threaded, pre-forking web server
# See: http://httpd.apache.org/docs/2.4/mod/prefork.html
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so				# prefork

# worker MPM: Multi-Processing Module implementing a hybrid
# multi-threaded multi-process web server
# See: http://httpd.apache.org/docs/2.4/mod/worker.html
#
#LoadModule mpm_worker_module modules/mod_mpm_worker.so					# worker

# event MPM: A variant of the worker MPM with the goal of consuming
# threads only for connections with active processing
# See: http://httpd.apache.org/docs/2.4/mod/event.html
#
#LoadModule mpm_event_module modules/mod_mpm_event.so						# event

每种模式的详解:

prefork

简介:prefork模式可以算是很古老但是非常稳定的Apache模式。Apache在启动之初,就预先fork一些子进程,然后等待请求进来。之所以这样做,是为了减少频繁创建和销毁进程的开销。每个子进程只有一个线程,在一个时间点内,只能处理一个请求。
优点:成熟稳定,兼容所有新老模块。同时,不需要担心线程安全的问题。(我们常用的mod_php,PHP的拓展不需要支持线程安全)
缺点:一个进程相对占用更多的系统资源,消耗更多的内存。而且,它并不擅长处理高并发请求,在这种场景下,它会将请求放进队列中,一直等到有可用进程,请求才会被处理。

工作原理:

一个单独的控制进程(父进程)负责产生子进程,这些子进程用于监听请求并作出应答。Apache总是试图保持一些备用的 (spare)或是空闲的子进程用于迎接即将到来的请求。这样客户端就无需在得到服务前等候子进程的产生。在Unix系统中,父进程通常以root身份运行以便邦定80端口,而 Apache产生的子进程通常以一个低特权的用户运行。User和Group指令用于配置子进程的低特权用户。运行子进程的用户必须要对他所服务的内容有读取的权限,但是对服务内容之外的其他资源必须拥有尽可能少的权限。
 这样可以减少频繁创建和销毁进程的开销,每个子进程只有一个线程,在一个时间点内,只能处理一个请求。这是一个成熟稳定,可以兼容新老模块,也不需要担心线程安全问题,但是一个进程相对占用资源,消耗大量内存,不擅长处理高并发的场景。

     		----->		派生子进程		----->		子进程
主进程		----->		派生子进程		----->		子进程
		 		----->		派生子进程		----->		子进程		 		

配置说明:

如何配置在Apache的配置文件httpd.conf的配置方式:

<IfModule mpm_prefork_module>
    StartServers             5
    MinSpareServers          5
    MaxSpareServers          10
    MaxRequestWorkers        250
    MaxConnectionsPerChild   1000
</IfModule>
  • StartServers  服务器启动时建立的子进程数量,默认是5个
  • MinSpareServers  空闲子进程的最小数量,默认5个;如果当前空闲子进程数少于MinSpareServers ,那么Apache将以最大每秒一个的速度产生新的子进程。此参数不要设的太大。
  • MaxSpareServers   空闲子进程的最大数量,默认10;如果当前有超过MaxSpareServers数量的空闲子进程,那么父进程会杀死多余的子进程。次参数也不需要设置太大,如果你将其设置比MinSpareServers 小,Apache会自动将其修改为MinSpareServers +1的数量。
  • MaxRequestWorkers  限定服务器同一时间内客户端最大接入的请求数量,默认是256;任何超过了MaxRequestWorkers限制的请求都要进入等待队列,一旦一个个连接被释放,队列中的请求才将得到服务,如果要增大这个数值,必须先增大ServerLimit。在Apache2.3.1版本之前这参数MaxRequestWorkers被称为MaxClients。
  • MaxConnectionsPerChild   每个子进程在其生命周期内允许最大的请求数量,如果请求总数已经达到这个数值,子进程将会结束,如果设置为0,子进程将永远不会结束。在Apache2.3.9之前称之为MaxRequestsPerChild。
worker

简介:worker模式比起上一个,是使用了多进程和多线程的混合模式。它也预先fork了几个子进程(数量比较少),然后每个子进程创建一些线程,同时包括一个监听线程。每个请求过来,会被分配到1个线程来服务。线程比起进程会更轻量,因为线程通常会共享父进程的内存空间,因此,内存的占用会减少一些。在高并发的场景下,因为比起prefork有更多的可用线程,表现会更优秀一些。
有些人会觉得奇怪,那么这里为什么不完全使用多线程呢,还要引入多进程?
原因主要是需要考虑稳定性,如果一个线程异常挂了,会导致父进程连同其他正常的子线程都挂了(它们都是同一个进程下的)。为了防止这场异常场景出现,就不能全部使用线程,使用多个进程再加多线程,如果某个线程出现异常,受影响的只是Apache的一部分服务,而不是整个服务。

优点:占据更少的内存,高并发下表现更优秀。

缺点:必须考虑线程安全的问题,因为多个子线程是共享父进程的内存地址的。如果使用keep-alive的长连接方式,某个线程会一直被占据,也许中间几乎没有请求,需要一直等待到超时才会被释放。如果过多的线程,被这样占据,也会导致在高并发场景下的无服务线程可用。(该问题在prefork模式下,同样会发生)

注:keep-alive的长连接方式,是为了让下一次的socket通信复用之前创建的连接,从而,减少连接的创建和销毁的系统开销。保持连接,会让某个进程或者线程一直处于等待状态,即使没有数据过来。

工作原理:

和prefork模式相比,worker使用了多进程和多线程的混合模式,worker模式也同样会先预派生一些子进程,然后每个子进程创建一些线程,同时包括一个监听线程,每个请求过来会被分配到一个线程来服务。线程比起进程会更轻量,因为线程是通过共享父进程的内存空间,因此,内存的占用会减少一些,在高并发的场景下会比prefork有更多可用的线程,表现会更优秀一些;另外,如果一个线程出现了问题也会导致同一进程下的线程出现问题,如果是多个线程出现问题,也只是影响Apache的一部分,而不是全部。由于用到多进程多线程,需要考虑到线程的安全了,在使用keep-alive长连接的时候,某个线程会一直被占用,即使中间没有请求,需要等待到超时才会被释放(该问题在prefork模式下也存在)。

     		----->		派生子进程		----->		线程
主进程		----->		派生子进程		----->		线程
		 		----->		派生子进程		----->		线程		 		

配置说明:

配置在Apache的配置文件httpd.conf的配置方式:

<IfModule mpm_worker_module>
    StartServers             3
    ServerLimit              16
    MinSpareThreads          75
    MaxSpareThreads          250
    ThreadsPerChild          25
    MaxRequestWorkers        400
    MaxConnectionsPerChild   1000
</IfModule>
  • StartServers 服务器启动时建立的子进程数量,在workers模式下默认是3个.
  • ServerLimit系统配置的最大进程数量
  • MinSpareThreads空闲子进程的最小数量,默认75
  • MaxSpareThreads 空闲子进程的最大数量,默认250
  • ThreadsPerChild 每个子进程产生的线程数量,默认是64
  • MaxRequestWorkers /MaxClients 限定服务器同一时间内客户端最大接入的请求数量.
  • MaxConnectionsPerChild 每个子进程在其生命周期内允许最大的请求数量,如果请求总数已经达到这个数值,子进程将会结束,如果设置为0,子进程将永远不会结束。在Apache2.3.9之前称之为MaxRequestsPerChild。

这里建议设置为非零,注意原因:
1)能够防止(偶然的)内存泄漏无限进行,从而耗尽内存。
2)给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量(重生的机会)。

Worker模式下所能同时处理的请求总数是由子进程总数乘以ThreadsPerChild 值决定的,应该大于等于MaxRequestWorkers。如果负载很大,现有的子进程数不能满足时,控制进程会派生新的子进程。默认最大的子进程总数是16,加大时 也需要显式声明ServerLimit(最大值是20000)。需要注意的是,如果显式声明了ServerLimit,那么它乘以 ThreadsPerChild的值必须大于等于MaxRequestWorkers,而且MaxRequestWorkers必须是ThreadsPerChild的整数倍,否则 Apache将会自动调节到一个相应值。

event

简介:这个是Apache中最新的模式,在现在版本里的已经是稳定可用的模式。它和worker模式很像,最大的区别在于,它解决了keep-alive场景下,长期被占用的线程的资源浪费问题(某些线程因为被keep-alive,空挂在哪里等待,中间几乎没有请求过来,甚至等到超时)。event MPM中,会有一个专门的线程来管理这些keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。这样增强了高并发场景下的请求处理能力。

event MPM在遇到某些不兼容的模块时,会失效,将会回退到worker模式,一个工作线程处理一个请求。官方自带的模块,全部是支持event MPM的。

注意一点,event MPM需要Linux系统(Linux 2.6+)对EPoll的支持,才能启用。

还有,需要补充的是HTTPS的连接(SSL),它的运行模式仍然是类似worker的方式,线程会被一直占用,知道连接关闭。部分比较老的资料里,说event MPM不支持SSL,那个说法是几年前的说法,现在已经支持了。

工作原理:

这是Apache最新的工作模式,它和worker模式很像,不同的是在于它解决了keep-alive长连接的时候占用线程资源被浪费的问题,在event工作模式中,会有一些专门的线程用来管理这些keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务器的线程,执行完毕后,又允许它释放。这增强了在高并发场景下的请求处理。

     		----->		子进程		----->		多线程		----->		管理&分配线程		----->		HTTP请求
主进程		----->		子进程		----->		线程
		 		----->		子进程		----->		线程		 		

配置说明:

配置在Apache的配置文件httpd.conf的配置方式:

<IfModule mpm_event_module>
    StartServers             3
    ServerLimit              16
    MinSpareThreads          75
    MaxSpareThreads          250
    ThreadsPerChild          25
    MaxRequestWorkers        400
    MaxConnectionsPerChild   1000
</IfModule>
  • StartServers 服务器启动时建立的子进程数量,在workers模式下默认是3个.
  • ServerLimit系统配置的最大进程数量
  • MinSpareThreads空闲子进程的最小数量,默认75
  • MaxSpareThreads 空闲子进程的最大数量,默认250
  • ThreadsPerChild 每个子进程产生的线程数量,默认是64
  • MaxRequestWorkers /MaxClients 限定服务器同一时间内客户端最大接入的请求数量.
  • MaxConnectionsPerChild 每个子进程在其生命周期内允许最大的请求数量,如果请求总数已经达到这个数值,子进程将会结束,如果设置为0,子进程将永远不会结束。

ps:

[root@localhost httpd]# /usr/sbin/httpd
You have new mail in /var/spool/mail/root
[root@localhost httpd]# ps aux | grep httpd
root      5589  0.0  0.6  10292  2820 ?        Ss   22:58   0:00 /usr/sbin/httpd
apache    5590  0.0  0.4  10424  2060 ?        S    22:58   0:00 /usr/sbin/httpd
apache    5591  0.0  0.4  10424  2060 ?        S    22:58   0:00 /usr/sbin/httpd
apache    5592  0.0  0.4  10424  2060 ?        S    22:58   0:00 /usr/sbin/httpd
apache    5593  0.0  0.4  10424  2060 ?        S    22:58   0:00 /usr/sbin/httpd
apache    5594  0.0  0.4  10424  2060 ?        S    22:58   0:00 /usr/sbin/httpd
apache    5595  0.0  0.4  10424  2060 ?        S    22:58   0:00 /usr/sbin/httpd
apache    5596  0.0  0.4  10424  2060 ?        S    22:58   0:00 /usr/sbin/httpd
apache    5597  0.0  0.4  10424  2060 ?        S    22:58   0:00 /usr/sbin/httpd
root      5599  0.0  0.1   3896   664 pts/0    R+   22:59   0:00 grep httpd
启动HTTPD,可以通过/usr/sbin/httpd来启动,或者service httpd start。

默认,HTTPD的工作模型是perfork。

通过上面的,可以知道,启动HTTPD后,由于HTTPD的特性【事先创建进程】,会有多个HTTPD的进程,其中会有一个HTTPD的进程的OWER:GROUP都是ROOT。【很显然,这是一个主导进程,用于创建,销毁其他HTTPD进程的 master process】。其他HTTPD进程可以成为工作进程,work process.

说白了,就是每一个用户请求,由master process负责创建work process来响应。

httpd虚拟主机的配置

基于IP地址的虚拟主机

在同一台服务器上,有多个IP地址,每一个IP地址负责一台虚拟主机的绑定,每个主机的主机名不一样如www.vhost1.com www.vhost2.com,使用较少,因为IP地址较为宝贵,而这种虚拟主机需要大量IP地址。

配置示例:

(1) 添加多个供虚拟主机使用的IP地址

[root@cnode6_8conf.d]# ip a |grep 192  //此时eth2有一个IP地址
    inet 192.168.66.142/24 scope global eth2

#使用ip命令添加三个临时IP地址

[root@cnode6_8conf.d]# ip addr add 192.168.66.143/24 dev eth2
[root@cnode6_8conf.d]# ip addr add 192.168.66.144/24 dev eth2
[root@cnode6_8conf.d]# ip addr add 192.168.66.145/24 dev eth2
[root@cnode6_8conf.d]# ip a | grep 192  //通过查看多了3个IP地址
    inet 192.168.66.142/24 scope global eth2
    inet 192.168.66.143/24 scope globalsecondary eth2
    inet 192.168.66.144/24 scope globalsecondary eth2

(2)添加虚拟主机的配置文件

[root@cnode6_8conf.d]# pwd
/etc/httpd/conf.d
[root@cnode6_8conf.d]# vim virtual.conf
<VirtualHost 192.168.66.143:80> 
    ServerName www.vhost1.com
    DocumentRoot "/testdir/vhost1"
    <Directory"/testdir/vhost1">
             AllowOverride none
             Allow from all
             Order Allow,deny   
    </Directory>   
</VirtualHost>
 
<VirtualHost 192.168.66.144:80>
    ServerName www.vhost2.com
    DocumentRoot "/testdir/vhost2"
    <Directory"/testdir/vhost2">
             AllowOverride none
             Allow from all
             Order Allow,deny   
    </Directory>   
</VirtualHost>

(3)修改/etc/hosts文件(此处不是必须的,因为这里没有DNS服务器解析域名,只好修改hosts文件以供测试!)

[root@cnode6_8conf.d]# grep "^192" /etc/hosts
168.66.143  www.vhost1.com
168.66.144  www.vhost2.com
168.66.145 www.vhost3.com

(4)添加相应的目录和文件重启服务测试,添加的目录和文件都因该是配置文件定义的。这里省略这些步骤,测试结果应该为访问相应的域名,会被解析为相应的IP能访问到响应的网页

基于域名的虚拟主机

在同一台服务器上面,仅有一个IP地址,使用不同的主机名访问不同的网页内容,在虚拟主机块定义上面需要使用NameVirtualHost声明监听的IP地址,使用较多。需要注意在httpd-2.4的版本中不需要使用NameVirtualHost关键字指定监听IP地址和端口号,其余部分没有变化

(1)修改配置文件

root@cnode6_8conf.d]# pwd
/etc/httpd/conf.d
[root@cnode6_8conf.d]# vim virtual.conf
NameVirtualHost 192.168.66.142:80 //如果要监听主机所有IP可以使用通配符 *
<VirtualHost192.168.66.142:80>
    ServerNamewww.vhost1.com
    DocumentRoot "/testdir/vhost1"
    <Directory"/testdir/vhost1">
             AllowOverride none
             Allow from all
             Order Allow,deny   
    </Directory>   
</VirtualHost>
 
<VirtualHost192.168.66.142:80>
    ServerNamewww.vhost2.com
    DocumentRoot "/testdir/vhost2"
    <Directory"/testdir/vhost2">
          AllowOverride none
          Allow from all
          Order Allow,deny   
    </Directory>   
</VirtualHost>

(2)修改/etc/hosts文件

[root@cnode6_8 conf.d]# grep 192 /etc/hosts
168.66.143 www.vhost1.com
168.66.143 www.vhost2.com

(3)测试

测试时访问不同的域名,虽然是被解析为相同的IP地址,但是能访问到不同的主页

基于不同端口的虚拟主机

在同一IP,同一主机名下,使用监听不同端口,访问时需要加访问的端口。使用不多,一般用来做内网测试使用

(1)修改配置文件

[root@cnode6_8conf.d]# cat virtual.conf
Listen 8080   //添加监听的端口
<VirtualHost 192.168.66.142:8080>
    ServerName www.vhost1.com
    DocumentRoot "/testdir/vhost1"
    <Directory"/testdir/vhost1">
          AllowOverride none
          Allow from all
          Order Allow,deny   
    </Directory>   
</VirtualHost>
 
<VirtualHost 192.168.66.142:80>
    ServerName www.vhost1.com
    DocumentRoot "/testdir/vhost2"
    <Directory"/testdir/vhost2">
             AllowOverride none
             Allow from all
             Order Allow,deny   
    </Directory>   
</VirtualHost>

(2)修改/etc/hosts文件

[root@cnode6_8 conf.d]# grep 192 /etc/hosts
168.66.142 www.vhost1.com

测试要注意默认的端口可以不加,但是非80的端口访问时要手动添加,在访问相同的域名,不同的端口的地址时,同样可以得到不同的网页

httpd命令使用

httpd -M 用来列出基于当前配置加载的所有模块 
httpd -l 输出一个静态编译在服务器中的模块的列表。它不会列出使用LoadModule指令动态加载的模块
httpd -S 显示虚拟机的设置
httpd -t 对配置文件执行语法检查
httpd -v 显示httpd的版本
httpd -V 显示httpd的版本和编译参数
httpd -f 在启动中使用的配置文件
httpd -e levle 在服务器启动时,设置LogLevel为level 。它用于在启动时,临时增加出错信息的详细程度,以帮助排错

mod_wsgi介绍

apache mod_wsgi

在openstack中,所有提供API接口的服务都是python web server,而其本身性能很弱,目前已经将它们配置到了apache上。且加载了mod_wsgi模块

Apache HTTP服务器的mod_wsgi扩展模块,实现了Python WSGI标准,可以支持任何兼容Python WSGI标准的Python应用。

httpd中配置加载了Include conf.modules.d/?.conf和IncludeOptional conf.d/?.conf,其中

Include conf.modules.d/?.conf

-rw-r--r-- 1 root root 3739 Oct 20  2017 00-base.conf
-rw-r--r-- 1 root root  139 Oct 20  2017 00-dav.conf
-rw-r--r-- 1 root root   41 Oct 20  2017 00-lua.conf
-rw-r--r-- 1 root root  742 Oct 20  2017 00-mpm.conf
-rw-r--r-- 1 root root  957 Oct 20  2017 00-proxy.conf
-rw-r--r-- 1 root root   41 Oct 20  2017 00-ssl.conf
-rw-r--r-- 1 root root   88 Oct 20  2017 00-systemd.conf
-rw-r--r-- 1 root root  451 Oct 20  2017 01-cgi.conf
-rw-r--r-- 1 root root   43 Aug 25  2014 10-wsgi.conf

这里是加载的一些模块,加载的目录在/usr/lib64/httpd/modules/
IncludeOptional conf.d/?.conf

-rw-r--r-- 1 root root 2926 Dec 25  2017 autoindex.conf
-rw-r--r-- 1 root root  366 Dec 25  2017 README
-rw-r--r-- 1 root root 9439 Aug  4 00:12 ssl.conf
-rw-r--r-- 1 root root 1252 Oct 20  2017 userdir.conf
-rw-r--r-- 1 root root  824 Oct 20  2017 welcome.conf
-r--r--r-- 1 root root  738 Aug  7 14:56 wsgi-gnocchi.conf

mod_wsgi.go文件放在/usr/lib64/httpd/modules/

先介绍下mod_wsgi的两种工作模式:

第一种是嵌入模式,类似于mod_python,直接在apache进程中运行,这样的好处是不需要另外增加进程,但是坏处也很明显,所有内存都和apache共享,如果和mod_python一样造成内存漏洞的话,就会危害整个apache。而且如果apache是用worker mpm,mod_wsgi也就强制进入了线程模式,这样子对于非线程安全的程序来说就没法用了。

这种模式下需要在apache的vhost中如下设置:

WSGIScriptAlias /path /path-to-wsgi

即可生效,对于小型脚本的话,直接用这种模式即可。

第二种是后台模式,类似于FastCGI的后台,mod_wsgi会借apache的外壳,另外启动一个或多个进程,然后通过socket通信和apache的进程联系。

这种方式只要使用以下配置即可:

#启动WSGI后台,site1是后台名字
WSGIDaemonProcess site1 processes=1 threads=15 display-name=%{GROUP}

#分配当前上下文应该使用哪个WSGI后台,可以放在Location里面指定
WSGIProcessGroup site1

#根据当前上下文的ProcessGroup分配到对应的后台
WSGIScriptAlias /path /path-to-wsgi

在这种模式下,我们可以通过调节processes和threads的值来设置三种MPM的模式:prefork’, ‘worker’, ‘winnt’。

winnt模式
WSGIDaemonProcess example threads=25

wsgi.multithread	True
wsgi.multiprocess	False

此时processes=1,但是multiprocess为false
如果显式地指出processes为1那么:
WSGIDaemonProcess example processes=1 threads=25

wsgi.multithread	True
wsgi.multiprocess	True


worker模式
WSGIDaemonProcess example processes=2 threads=25
wsgi.multithread	True
wsgi.multiprocess	True

preforker模式
WSGIDaemonProcess example processes=5 threads=1
wsgi.multithread	False
wsgi.multiprocess	True

后台模式由于是与apache进程分离了,内存独立,而且可以独立重启,不会影响apache的进程,如果你有多个项目(django),可以选择建立多个后台或者共同使用一个后台。

比如在同一个VirtualHost里面,不同的path对应不同的django项目,可以同时使用一个Daemon:

WSGIDaemonProcess default processes=1 threads=1 display-name=%{GROUP}

WSGIProcessGroup default

WSGIScriptAlias /project1 “/home/website/project1.wsgi”

WSGIScriptAlias /project2 “/home/website/project2.wsgi”

这样子两个django都使用同一个WSGI后台。

也可以把不同的项目分开,分开使用不同的后台,这样开销比较大,但就不会耦合在一起了。

display-name是后台进程的名字,这样方便重启对应的进程,而不需要全部杀掉。

WSGIDaemonProcess site1 processes=1 threads=1 display-name=%{GROUP}

WSGIDaemonProcess site2 processes=1 threads=1 display-name=%{GROUP}

<Location “/project1″>

WSGIProcessGroup site1

</Location>

WSGIScriptAlias /project1 “/home/website/project1.wsgi”

<Location “/project1″>

WSGIProcessGroup site2

</Location>

WSGIScriptAlias /project2 “/home/website/project2.wsgi”

对于django 1.0以下的版本,由于官方认定不是线程安全的,所以建议使用多进程单线程模式

processes=n threads=1

对于django 1.0以后,就可以放心的使用多进程多线程模式:

processes=2 threads=64

这样子性能会更好。

ps:

这里介绍了关于mod_wsgi运行模式的用法:modwsgi-ProcessesAndThreading.wiki

大概总结下,运行模式分为三类:

1. prefork:
  该MPM是最常用的。它是Apache 1.3中唯一可用的操作模式,并且在更高版本的Apache中仍然是UNIX系统上的默认模式。在此配置中,主Apache进程将在启动时创建多个子进程。当父进程接收到一个请求时,它将由哪个子进程准备就绪进行处理。

  每个子进程一次只能处理一个请求。如果另一个请求同时到达,它将由下一个可用的子进程处理。当检测到可用进程数已用完时,将根据需要创建其他子进程。如果为可以创建的子进程数指定了限制,并且达到了该限制,并且有足够的请求到达以填充侦听器套接字队列,则客户端可能会收到由于无法建立而导致的错误与Web服务器的连接。

  在由于到达的当前请求数量达到峰值而必须创建其他子进程的情况下,并且随后请求数量减少的情况下,多余的子进程可能会被关闭并被杀死。子进程在处理了一定数量的请求后也可能被关闭并被杀死。

  尽管不使用线程来满足各个请求,但这并不妨碍应用程序创建单独的线程来执行某些特定任务。

  对于使用多个进程的典型“ prefork”配置,指示如何使用进程和线程的WSGI环境键/值对如下所示。

  | wsgi.multithread | False | |:------------------- |:---- | | wsgi.multiprocess |真|

  由于正在使用多个进程,因此将无法使用WSGI中间件组件(如所述的基于交互式浏览器的调试器)。如果在开发和测试WSGI应用程序期间需要使用这样的调试器,那么唯一存在的选择是限制所使用的进程数。这可以使用Apache配置来实现:

  StartServers 1 ServerLimit 1

  使用此配置,将仅启动一个进程,而不会创建其他进程。指示如何使用进程和线程的WSGI环境键/值对将用于此配置,如下所示。

  | wsgi.multithread | False | |:------------------- |:---- | | wsgi.multiprocess | False |

  实际上,此配置的结果是通过单个过程序列化所有请求。这将允许使用基于浏览器的交互式调试器,但可能会使使用AJAX技术的更复杂的WSGI应用程序无法正常工作。在网页启动一系列AJAX请求并期望后续请求能够完成而初始请求的响应仍未决的情况下,可能会发生这种情况。换句话说,在请求重叠的地方可能会出现问题,因为在初始请求完成之前,后续请求将无法执行。
  
2. worker:
  'worker'MPM与'prefork'模式相似,除了在每个子进程中将存在许多worker线程。代替只能由下一个可用的空闲子进程处理请求,并且仅由子进程执行该请求的处理,该请求可以由子进程中的工作线程处理,该线程已经具有其他工作线程同时处理其他请求。

  一个子进程中的多个工作线程可以同时执行WSGI应用程序。这意味着多个工作线程可能希望同时访问公共共享数据。因此,必须以一种允许以线程安全的方式进行访问和修改的方式来保护此类公共共享数据。通常,这将需要使用某种形式的同步机制,以确保一次仅一个线程访问和/或修改公共共享数据。

  如果新请求到达时子进程中的所有工作线程都忙,则该请求将由另一个子进程中的空闲工作线程处理。如果需要,Apache仍可以根据需要创建新的子进程。Apache可能仍会关闭并杀死多余的子进程或已处理了多个请求数量的子进程。

  总体而言,使用“工作者” MPM将导致需要创建的子流程更少,但是单个子流程的资源使用量将会更大。在现代计算机系统上,通常使用“工作者” MPM作为首选的MPM,并且如果可能的话,应该优先使用“工作者” MPM。

  尽管对Python中的全局解释器锁(GIL)的争用会导致纯Python程序出现问题,但是在Apache中使用Python时,这通常不是一个大问题。这是因为所有用于接受请求并将URL映射到WSGI应用程序的基础结构以及对静态文件的请求处理都是由Apache用C代码执行的。在执行此代码时,线程将不会保留Python GIL,因此在系统具有多个CPU或具有多个核心的CPU的情况下,可以实现更高水平的重叠执行。

  Apache使用多个进程来处理请求,而不仅仅是一个进程,这一事实进一步增强了即使在使用多线程时也可以充分利用处理器以外的功能的能力。因此,即使在特定进程中存在GIL争用时,它也不会阻止其他进程运行,因为GIL仅在进程本地,并且不会跨进程扩展。

  对于使用多个进程和多个线程的典型“工作者”配置,指示如何使用进程和线程的WSGI环境键/值对如下所示。

  | wsgi.multithread | True | |:--------------- ||:--- | | wsgi.multiprocess |真|

  与“ prefork” MPM相似,如果需要,可以使用以下配置将进程数限制为一个:

  StartServers 1 ServerLimit 1

  使用此配置,将仅启动一个进程,而不会再创建任何其他进程,但是该进程仍将使用多个线程。

  指示如何使用进程和线程的WSGI环境键/值对将用于此配置,如下所示。

  | wsgi.multithread | True | |:--------------- ||:--- | | wsgi.multiprocess | False |

  因为使用了多个线程,所以基于AJAX的网页生成的重叠请求不会有问题。

3. winnt:
  在Windows平台上,“ winnt” MPM是唯一可用的选项。使用此MPM,子进程中的多个工作线程可用于处理所有请求。“ winnt” MPM与“ worker”模式不同,但是只有一个子进程。除了要停止或重新启动整个Apache之外,绝不会创建其他子进程,也不会立即关闭该子进程。因为只有一个子进程,所以使用的最大线程数要大得多。

  指示如何使用进程和线程的WSGI环境键/值对将用于此配置,如下所示。

  | wsgi.multithread | True | |:--------------- ||:--- | | wsgi.multiprocess | False |
  
4. The mod_wsgi Daemon Processes
  当使用mod_wsgi的“守护程序”模式时,可以单独配置每个进程组,使其以类似于Apache的“ prefork”,“ worker”或“ winnt” MPM的方式运行。这是通过使用WSGIDaemonProcess指令的“进程”和“线程”选项控制每个进程中的进程和线程数来实现的。

  为了模拟与“ winnt” MPM相同的进程/线程模型,即具有多个线程的单个进程,将使用以下配置:

  WSGIDaemonProcess example threads=25

  指示如何使用进程和线程的WSGI环境键/值对将用于此配置,如下所示。

  | wsgi.multithread | True | |:--------------- ||:--- | | wsgi.multiprocess | False |

  请注意,通过不指定'processes'选项,只能在流程组中创建一个流程。尽管提供“ processes = 1”作为选项也将导致创建单个进程,但这具有稍微不同的含义,因此您仅应在必要时这样做。

  未指定'processes'选项和定义'processes = 1'之间的区别是,在定义'processes'选项时,名为'wsgi.multiprocess'的WSGI环境属性将设置为True,而在以下位置不提供该选项:全部将导致该属性设置为False。这种区别是为了允许使用某种形式的映射机制在多个进程组之间分配请求,因此实际上它仍然是一个多进程应用程序。

  换句话说,如果您使用配置:

  WSGIDaemonProcess example processes=1 threads=25

  指示如何使用进程和线程的WSGI环境键/值对将改为:

  | wsgi.multithread | True | |:--------------- ||:--- | | wsgi.multiprocess |真|

  如果您需要确保'wsgi.multiprocess'为False,以使交互式调试器不会抱怨配置不兼容,只需不指定'processes'选项,并允许应用单个守护进程的默认行为即可。

  为了模拟与“工人” MPM相同的进程/线程模型,即具有多个线程的多个进程,将使用以下配置:

  WSGIDaemonProcess example processes=2 threads=25

  指示如何使用进程和线程的WSGI环境键/值对将用于此配置,如下所示。

  | wsgi.multithread | True | |:--------------- ||:--- | | wsgi.multiprocess |真|

  为了模拟与“ prefork” MPM相同的进程/线程模型,即,多个进程中每个进程仅运行一个线程,将使用以下配置:

  WSGIDaemonProcess example processes=5 threads=1

  指示如何使用进程和线程的WSGI环境键/值对将用于此配置,如下所示。

  | wsgi.multithread | False | |:------------------- |:---- | | wsgi.multiprocess |真|

  请注意,在使用mod_wsgi守护进程时,这些进程仅用于执行基于Python的WSGI应用程序。这些过程绝不用于提供静态文件或托管以其他语言实现的应用程序。

  与使用mod_wsgi的“嵌入式”模式的普通Apache子进程不同,进程组中守护进程数量的配置是固定的。也就是说,当服务器承受额外的负载时,创建的守护进程不会超过定义的进程。因此,您应该始终提前计划,并确保定义的进程和线程数足以应付预期的负载

apache-wsgi-python如何工作

客户端也就是浏览器端,当用户在浏览器的地址栏输入一个网站并且回车的时候,就会产生一个http的request请求到对应的服务器,服务器端的web服务器程序-这里就是我们的apache接受到,请求后,就查看所请求的这个url对应的虚拟机的对应的目录或者文件。这样说,可能有点晕,给个实际的例子吧:

<VirtualHost 192.168.77.122:80>  
   ServerAdmin admin@system  
   DocumentRoot "C:/Program Files/Apache Software Foundation/Apache2.2/htdocs/test"  
   ServerName myserver 
   WSGIScriptAlias / "C:/Program Files/Apache Software Foundation/Apache2.2/htdocs/test/mytest.py" 
   AddType text/html .py  
   ErrorLog logs/dummy-host.example.com-error_log  
   CustomLog logs/dummy-host.example.com-access_log common
   <Directory />
     Options FollowSymLinks ExecCGI
     AllowOverride None
     Order deny,allow
     Allow from all
   </Directory>
</VirtualHost> 

apache接受到这个请求后,发现请求对应的是目录C:/Program Files/Apache Software Foundation/Apache2.2/htdocs/test,虚拟机是myserver,这个虚拟机中有个很重要的配置是就是WSGIScriptAlias

这个东西非常关键,因为如果没有这个那么apache就不知道如何解析这个请求了。这个关键字告诉apache,该虚拟对应的目录下面的程序有wsgi对应的模块去执行,那么apache又怎么知道什么是wsgi模块,这个模块又在什么地方呢?这个需要在httpd.conf中来告诉apache,上面已经介绍过,加载mod_wsgi.go

LoadModule wsgi_module modules/mod_wsgi.so,在httpd.conf中加入这个配置后,apache就知道wsgi是哪个模块,在什么位置了。注意LoadModulewsgi_module是apache自己的关键字,它自己知道wsgi_module就是wsgi对应模块定义关键字。

你可以自己写一个动态库so,然后通过上面的方式-LoadModule加载进apache,但是对不起,apache并不认识你的模块,不能让你的这个so工作起来。好了我们言归正传吧,回到我们的主题。

所以当apache收到这个请求后,就知道使用mod_wsgi.so这个动态库的函数去处理请求,上面因为有这句:

WSGIScriptAlias / "C:/Program Files/Apache Software Foundation/Apache2.2/htdocs/test/mytest.py"

这样apache就知道当收到访问当前服务器的根目录时,就使用mytest.py来处理请求。谁来处理mytest.py,就是python解释器,所以mod_wsgi.so中就要创建进程-python解释器进程来解释执行mytest.py。

执行mytest.py就是为了生成这个请求的应答的内容,接着返回mod_wsgi,从而通知apache,处理完成并把结果-比如是一个html的流,apache再把这个结果发送给我们的客户端-浏览器,浏览器最后显示它。整个过程结束。

这里加一句题外话,上面是指定只要访问服务器就使用mytest.py来处理请求,这样的话,你请求别的页面,比如http://192.168.77.122/test.py那么服务器还是会使用mytest.py来处理请求,这不是我们希望的,我们希望用户访问不同的页面会有不同结果。怎么办呢?我们只要一个小小的改变就可以,就是将上面的有wsgiscriptAlias那就修改为下面的这句:

WSGIScriptAlias / "C:/Program Files/Apache Software Foundation/Apache2.2/htdocs/test"

这样就达到我们的效果了。

nginx mod_wsgi

其实nginx也可以使用mod_wsgi的模块,但是由于nginx在底层是一个事件驱动系统,因此它具有不利于阻塞应用程序的行为特征,例如基于WSGI的应用程序。更糟糕的情况是,使用多进程nginx配置,您可以看到用户请求被阻止,即使某些nginx工作进程可能处于空闲状态。Apache/mod_wsgi没有这个问题,因为Apache进程只有在有资源实际处理请求时才会接受请求。因此,Apache/mod_wsgi将提供更可预测和可靠的行为。

附录小知识

如何查看某个进程的线程数

有些时候需要确定进程内部当前运行了多少线程,查询方法如下:
  
1)通过pstree命令(根据pid)进行查询:
[root@xqsj_web2 ~]# ps -ef|grep java     //查找进程pid(比如这里查找java(tomcat)进程的pid)
[root@xqsj_web2 ~]# pstree -p 19135
java(19135)─┬─{java}(19136)
            ├─{java}(19137)
             .......
            └─{java}(13578)
[root@xqsj_web2 ~]# pstree -p 19135|wc -l
46     //由于第一行包括了2个线程,所以该进程下一共有47个线程!
  
或者使用top命令查看(可以查看到线程情况)
[root@xqsj_web2 ~]# top -Hp 19135       //下面结果中的Tasks 对应的47即是线程的个数
  
top - 14:05:55 up 391 days, 20:59,  1 user,  load average: 0.00, 0.00, 0.00
Tasks:  47 total,   0 running,  47 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.2%us,  0.1%sy,  0.0%ni, 99.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   8058056k total,  7718656k used,   339400k free,   354216k buffers
Swap:        0k total,        0k used,        0k free,  4678160k cached
  
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                      
19135 root      20   0 5339m 632m 5476 S  0.0  8.0   0:00.00 java                                                                          
19136 root      20   0 5339m 632m 5476 S  0.0  8.0   0:00.84 java                                                                          
......
  
2)根据ps命令直接查询:
[root@xqsj_web2 ~]# ps hH p 19135| wc -l
47
  
3)通过查看/proc/pid/status
proc伪文件系统,它驻留在/proc目录,这是最简单的方法来查看任何活动进程的线程数。/proc目录以可读文本文件形式输出,提供现有进程和系统硬件
相关的信息如CPU、中断、内存、磁盘等等。
  
[root@xqsj_web2 ~]# cat /proc/19135/status
Name:   java
State:  S (sleeping)
Tgid:   19135
Pid:    19135
PPid:   1
TracerPid:  0
........
Threads:    47                    //这里显示的是进程创建的总线程数。输出表明该进程有47个线程。
SigQ:   1/62793
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
.......
voluntary_ctxt_switches:    1
nonvoluntary_ctxt_switches: 1
  
或者,也可以在/proc//task中简单的统计子目录的数量,如下所示:
[root@xqsj_web2 ~]# ll /proc/19135/task
总用量 0
dr-xr-xr-x 6 root root 0 6月  14 17:57 11553
......
[root@xqsj_web2 ~]# ll /proc/19135/task|wc -l
48
  
这是因为,对于一个进程中创建的每个线程,在/proc/<pid>/task中会创建一个相应的目录,命名为其线程ID。由此在/proc/<pid>/task中目录的总数表示在进程中线程的数目。

参考:https://www.cnblogs.com/kevingrace/p/5252919.html

httpd process 和 wsgi process

()[root@gnocchi-api-797d4748bd-9ljfw /]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 Aug03 ?        00:00:00 /usr/local/bin/dumb-init /bin/bash /tmp/gnocchi-api.sh start
root         7     1  0 Aug03 ?        00:00:28 httpd -DFOREGROUND
gnocchi      8     7  0 Aug03 ?        00:04:09 (wsgi -DFOREGROUND

为什么在apache中使用了mod_wsgi之后,却会有两个不同名字进程

根据:

When you use daemon mode and your Django application is therefore running in a separate process to main Apache processes, you still need the Apache parent process and at least one Apache child process. The later is what accepts requests and proxies them through to the mod_wsgi daemon processes.

即httpd是转发请求给wsgi进程,由wsgi进程处理具体请求

DFOREGROUND 含义

在k8s中运行的httpd和wsgi进程中总会有 DFOREGROUND

()[root@gnocchi-api-797d4748bd-9ljfw /]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 Aug03 ?        00:00:00 /usr/local/bin/dumb-init /bin/bash /tmp/gnocchi-api.sh start
root         7     1  0 Aug03 ?        00:00:28 httpd -DFOREGROUND
gnocchi      8     7  0 Aug03 ?        00:04:09 (wsgi -DFOREGROUND

通俗的说就是它使得 apache 的进程一直在 console 界面的“前端”运行,而不是作为一个守护进程挂起,想象一下你用 tail -f 跟踪某个 log 文件时的窗口,就是那个效果。其目的就是让 docker “认为” apache 一直在跑着,否则 docker 就会认为自己的任务结束了,从而 exit;那是我们不希望看到的。据此,也让我对 docker 的运行机制多了一点了解。

查看apache当前并发访问数和进程数 ApacheLinux

1、查看apache当前并发访问数:
 netstat -an | grep ESTABLISHED | wc -l

对比httpd.conf中MaxClients的数字差距多少。

2、查看有多少个进程数:
ps aux|grep httpd|wc -l

3、可以使用如下参数查看数据
server-status?auto

#ps -ef|grep httpd|wc -l
1388
统计httpd进程数,连个请求会启动一个进程,使用于Apache服务器。
表示Apache能够处理1388个并发请求,这个值Apache可根据负载情况自动调整。

#netstat -nat|grep -i "80"|wc -l
4341
netstat -an会打印系统当前网络链接状态,而grep -i "80"是用来提取与80端口有关的连接的,wc -l进行连接数统计。
最终返回的数字就是当前所有80端口的请求总数。

#netstat -na|grep ESTABLISHED|wc -l
376
netstat -an会打印系统当前网络链接状态,而grep ESTABLISHED 提取出已建立连接的信息。 然后wc -l统计。
最终返回的数字就是当前所有80端口的已建立连接的总数。

netstat -nat||grep ESTABLISHED|wc - 可查看所有建立连接的详细记录

查看Apache的并发请求数及其TCP连接状态:
  Linux命令:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

(这条语句是从 新浪互动社区事业部 新浪互动社区事业部技术总监王老大那儿获得的,非常不错)返回结果示例:
  LAST_ACK 5
  SYN_RECV 30
  ESTABLISHED 1597
  FIN_WAIT1 51
  FIN_WAIT2 504
  TIME_WAIT 1057
  其中的
SYN_RECV表示正在等待处理的请求数;
ESTABLISHED表示正常数据传输状态;
TIME_WAIT表示处理完毕,等待超时结束的请求数

常用web服务器对比

对比项ApacheNginxLighttpd
Proxy代理非常好非常好一般
Rewriter非常好一般
Fcgi不好非常好
热部署不支持支持不支持
系统压力很大很小比较小
稳定性非常好不好
安全性一般一般
静态文件处理一般非常好
反向代理一般非常好一般

参考:

http://blog.360converter.com/archives/1005

https://www.cnblogs.com/fengchong/p/10230266.html

https://blog.csdn.net/a3192048/article/details/89737337

https://blog.csdn.net/weixin_34117211/article/details/85928265?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.channel_param

https://blog.csdn.net/weixin_33779515/article/details/92821188?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param

https://blog.csdn.net/weixin_33994444/article/details/92981756?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

https://blog.csdn.net/weixin_33842304/article/details/86420744?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param

https://blog.csdn.net/willierStrong/article/details/7226938?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值