您的位置:首页 > 理论基础 > 计算机网络

Apache HTTP Server2.2 笔记

2017-03-17 11:38 363 查看

多处理模块(MPM)

Apache HTTP 服务器被设计为一个功能强大,并且灵活的 web 服务器, 可以在很多平台与环境中工作。不同平台和不同的环境往往需要不同 的特性,或可能以不同的方式实现相同的特性最有效率。Apache 通过模块化的设计来适应各种环境。这种设计允许网站管理员通过在 编译时或运行时,选择哪些模块将会加载在服务器中,来选择服务器特性。Apache 2.0 扩展此模块化设计到最基本的 web 服务器功能。 它提供了可以选择的多处理模块(MPM),此类型的模块负责基本的对请求的处理和指派,它用来绑定到网络端口上,接受请求,
以及调度子进程处理请求。

在用户看来,MPM 很像其它 Apache 模块。主要是区别是,在任何时间, 必须有一个,而且只有一个 MPM 加载到服务器中。MPM 必须在编译前夕,配置时指定,然后编译到服务器程序中。 仅当编译器知道使用了线程时,它才有能力优化许多函数。为了使用指定的 MPM,请在执行 configure 时,使用参数 --with-mpm=NAME。NAME 是指定的 MPM 名称。编译完成后,可以使用 ./httpd -l 来确定选择的 MPM。 此命令会列出编译到服务器程序中的所有模块,包括 MPM。Windows
NT默认的MPM是mpm_winnt,它使用一个单独的父进程产生一个单独的子进程,在这个子进程中轮流产生多个线程来处理请求。

常用指令

ServerRoot

设置了服务器所在的目录。一般来说它将包含conf/和logs/子目录。其它配置文件的相对路径即基于此目录 (比如Include或LoadModule),修改为你自己的目录,如ServerRoot "D:/develop/java/run/httpd-2.2.31-win64"。

DocumentRoot

这个指定设置了httpd提供文件的目录,除非和Alias指令相匹配,服务器会将URL上的路径添加到DocumentRoot配置的路径上以构成指向文档的路径。比如说:DocumentRoot /usr/web。于是对http://www.my.host.com/index.html的访问就会指向/usr/web/index.html 。可以配置为相对ServerRoot的相对路径,如

DocumentRoot "htdocs"。

Listen

指示Apache只在指定的IP地址和端口上监听,如果只指定端口,那么Apache会在所有本机IP地址上监听。可以指定多个不同的监听端口和/或地址端口组合。

使服务器在所有地址上同时接受来自端口80和8000的请求,可以这样写:

Listen 8

Listen 8000 

接受来自两个指定的地址+端口的组合:

Listen 192.170.2.1:80 

Listen 192.170.2.5:8000 

IPv6地址必须用方括号括起来:

Listen [2001:db8::a00:20ff:fea7:ccea]:80 

还可以指定http和https协议,一般来说,不需要指定协议,443端口默认https,其他端口默认http,如果指定特殊的端口如8443端口用于https,那么就需要指定协议。

如:Listen 192.170.2.1:8443 https

LoadModule

加载目标文件或库,并将其添加到活动模块列表。语法是LoadModule module filename,module是源代码文件中用于拼写module的外部变量名,filename相对于ServerRoot。例如:LoadModule status_module modules/mod_status.so。

ServerAdmin

服务器返回给客户端的错误信息中包含的管理员邮件地址,例如:ServerAdmin admin@example.com。

IfModule

IfModule test>...</IfModule>配置段用于封装根据指定的模块是否启用而决定是否生效的指令。在<IfModule>配置段中的指令仅当test为真的时候才进行处理。如果test为假,所有其间的指令都将被忽略。<IfModule>段中的test可以为以下两种方式之一:module或者!module。在第一种情况下,起始和结束标记之间的指令仅当module被载入后才被执行。此模块可以为编译时静态链接进核心的模块或是使用LoadModule指令动态载入的模块。第二种情况则相反,仅当module没有载入时才进行指令的处理。

Include

这个指令允许在服务器配置文件中加入其它配置文件。可以是绝对路径也可以是相对于ServerRoot的路径。例如:Include conf/ssl.conf。

Allow和Deny

Allow指令控制哪些主机可以访问服务器的该区域,可以根据主机名、IP地址、 IP地址范围或其他环境变量中捕获的客户端请求特性进行控制。Deny和Allow作用相反,配置方法一样。这个指令的第一个参数总是"from",随后的参数可以有三种不同形式。

第一种是all,Allow from all,允许所有主机访问。

第二种是允许特定的一台或多台主机访问,有很多的配置方式,常见的如下:

Allow from .net example.edu:主机名与给定字符串匹配或者以给定字符串结尾的主机允许访问。

Allow from 192.168.1.104 192.168.1.205:允许拥有这些IP地址的主机进行访问。

Allow from 10.1 192.168.2 :IP地址的开始1到3个字节,用于子网限制。

第三种是允许对服务器的访问由环境变量的一个扩展指定。指定"Allow from env=env-variable"时,如果环境变量env-variable存在则访问被允许。使用由mod_setenvif提供的指令SetEnvIf ,服务器用一种基于客户端请求的弹性方式提供了设置环境变量的能力。因此,这条指令可以用于允许基于像User-Agent(浏览器类型)、Referer或其他HTTP请求头字段的访问。

SetEnvIf User-Agent ^KnockKnock/2\.0 let_me_in

<Directory /docroot>

Order Deny,Allow

Deny from all

Allow from env=let_me_in

</Directory> 

这种情况下,发送以KnockKnock/2.0开头的用户代理标示的浏览器将被允许访问,而所有其他浏览器将被禁止访问。

Order

Order指令控制默认的访问状态与Allow和Deny指令生效的顺序。

Deny,Allow :Deny指令在Allow指令之前被评估。默认允许所有访问。任何不匹配Deny指令或者匹配Allow指令的客户都被允许访问。 

Allow,Deny :Allow指令在Deny指令之前被评估。默认拒绝所有访问。任何不匹配Allow指令或者匹配Deny指令的客户都将被禁止访问。

规则是先判断默认的,再根据顺序判断Allow和Deny,最后叠加。

例如下面的例子表示,默认允许所有访问,然后拒绝192.168.1.109访问,最后叠加的结果是除了192.168.1.109其他都可以访问。

Order deny,allow

Deny from 192.168.1.109

下面的例子最后一句是没有意义的,因为默认已经决绝了所有的访问,叠加后还是决绝所有的访问。

Order allow,deny

Deny from 192.168.1.109

Directory和DirectoryMatch

用于封装一组指令,使之仅对某个目录及其子目录生效。任何可以在"directory"作用域中使用的指令都可以使用。Directory-path可以是一个目录的完整路径,或是包含了Unix shell匹配语法的通配符字符串。在通配符字符串中,"*"匹配任何字符串,"?"匹配任何单个的字符,"[seq]"匹配seq序列中的任何字符,符号"/"不被任何通配符所匹配,必须显式地使用。所以<Directory /*/public_html>将无法匹配/home/user/public_html ,但<Directory
/home/*/public_html>能够正确匹配。例如:<Directory /usr/local/httpd/htdocs>。Directory加上~符号后,可以用正则表达式,例如:<Directory ~ "^/www/(.+/)*[0-9]{3}">。

DirectoryMatch和Directory功能一样,区别是DirectoryMatch仅支持正则表达式,例如:<DirectoryMatch "^/www/(.+/)*[0-9]{3}">。

Files和FilesMatch

指令提供了基于文件名的访问控制,与<Directory>指令类似。<Files>能嵌入到<Directory>段中以限制它们作用的文件系统范围。参数应当是一个文件名或是一个包含了Unix shell匹配语法的通配符字符串。在"~"字符之后同样可以使用正则表达式。比如:<Files ~ "\.(gif|jpe?g|png)$">,将匹配绝大部分常见的因特网图象格式。

Files 和FilesMatch功能一样,区别是FilesMatch仅支持正则表达式,例如:<FilesMatch "\.(gif|jpe?g|png)$">。

Location和LocationMatch

提供了基于URL的访问控制。与<Directory>指令类似。何时使用<Location>?使用<Location>来将指令应用于独立于文件系统之外的内容。文件系统之内的内容请使用<Directory>和<Files>指令。不过一个例外是<Location /> ,它可以方便的作用于所有URL。对所有的原始(非代理)请求来说,匹配的URL应该是具有"/path/"形式的URL路径。不包括访问方法、主机名、端口或查询字符串等。对于代理的请求,匹配的URL必须为"scheme://servername/path"的形式,而且必须包括前缀。URL可以是一个包含了Unix
shell匹配语法的通配符字符串。也可以附加"~"字符来表示使用正则表达式。例如:<Location ~ "/(extra|special)/data">

Location和LocationMatch功能一样,区别是LocationMatch仅支持正则表达式,例如:<LocationMatch "/(extra|special)/data">。

Proxy和ProxyMatch

位于<Proxy>配置段中的指令仅作用于通过mod_proxy代理服务器访问的、与指定URL匹配的站点。语句中可以是包含了Unix shell匹配语法的通配符字符串。Proxy和ProxyMatch作用一样,只是ProxyMatch使用正则表达式匹配代理内容。

下例仅允许yournetwork.example.com中的主机通过您的代理服务器访问代理内容:

<Proxy *>

Order Deny,Allow

Deny from all

Allow from yournetwork.example.com

</Proxy> 

下例中的配置会拒绝通过代理服务器访问cnn.com站点。

<Proxy http://cnn.com/*>
Order allow,deny

Deny from all

</Proxy> 

DirectoryIndex

指令设置了当客户端请求一个目录时寻找的资源列表。参数是多个路径,用空格分开,可以是相对于被请求目录的路径,也可以是不在那个目录下的绝对路径。服务器将返回最先找到的那一个。若一个也没有找到,并且那个目录设置了Indexes选项(参考Options指令),服务器将会自动产生一个那个目录中的资源列表。例如:DirectoryIndex index.html。上例配置指示对 http://myserver/docs/ 的请求返回 http://myserver/docs/index.html(若存在)。
DirectoryIndex index.html index.txt /cgi-bin/index.pl。这样的设置将导致在index.html或index.txt都不存在的情况下执行CGI脚本/cgi-bin/index.pl 。

LogFormat

定义访问日志的记录格式,具体格式参考官网文档,有两个参数。第一个参数是格式字符串。第二个参数是别名,别名可以省略,省略别名主要用于TransferLog指令。例如:LogFormat "%v %h %l %u %t \"%r\" %>s %b" common。common是别名。

CustomLog

指令用来记录对服务器的访问,有三个参数。第一个参数可以是文件位置(相对于ServerRoot或者绝对路径),也可以是管道符“|”,后面紧跟着一个把日志输出当作标准输入的处理程序相对于ServerRoot路径。第二个参数是格式,可以是LogFormat定义的别名,也可以是格式字符串。第三个参数是可选的,它根据服务器上特定的环境变量是否被设置来决定是否对某一特定的请求进行日志记录。如果这个特定的环境变量被设置(或者在"env=!name"的情况下未被设置),那么这个请求将被记录。

例如:CustomLog "|bin/rotatelogs.exe -l  E:/logs/apache/access_log_%Y_%m_%d.log 1G" combined env=!dontlog

ErrorLog

指令指定了当服务器遇到错误时记录错误日志的文件。可以是绝对路径也可以是相对于ServerRoot。只有一个参数,可以是文件位置也可以是管道符“|”,后面紧跟着一个把日志输出当作标准输入的处理程序相对于ServerRoot路径。

例如:ErrorLog "|bin/rotatelogs.exe -l E:/logs/apache/error_log_%Y_%m_%d.log 1G"

配置段合并

合并的结果是后面生效的会覆盖前面生效的,顺序是:

1、<Directory>(除了正则表达式)和.htaccess同时处理;(如果允许的话,.htaccess的设置会覆盖<Directory>的设置) 

2、<DirectoryMatch>(和<Directory ~>) 

3、<Files>和<FilesMatch>同时处理 

4、<Location>和<LocationMatch>同时处理 

除了<Directory>,每个组都按它们在配置文件中出现的顺序被依次处理,而<Directory>会按字典顺序由短到长被依次处理,因为Directory作用于当前目录及其子目录。

例如:<Directory /var/web/dir>会先于<Directory /var/web/dir/subdir>被处理。如果有多个指向同一个目录的<Directory>段,则按它们在配置文件中的顺序被依次处理。

用Include指令包含进来的配置被视为按原样插入到Include指令的位置。

位于<VirtualHost>容器中的配置段在外部对应的段处理完毕以后再处理,这样就允许虚拟主机覆盖主服务器的设置。

当请求是由mod_proxy处理的时候,<Proxy>容器将会在处理顺序中取代<Directory>容器的位置。

后面的段覆盖前面的相应的段的配置。

 A > B > C > D >E 的顺序依次生效。

<Location />

E

</Location>

<Files f.html>

D

</Files>

<VirtualHost *>

<Directory /a/b>

B

</Directory>

</VirtualHost>

<DirectoryMatch "^.*b$">

C

</DirectoryMatch>

<Directory /a/b>

A

</Directory>

在下面这个更具体的例子中,无论在<Directory>段中加了多少访问限制,由于<Location>段将会被最后处理,从而会允许不加限制的对服务器的访问,可见合并的顺序是很重要的,千万小心!

<Location />

Order deny,allow

Allow from all

</Location>

# 这个<Directory>段将不会实际生效

<Directory />

Order allow,deny

Allow from all

Deny from badguy.example.com
</Directory> 

HTTPS双向认证配置

生成所需证书

创建CA私钥

openssl genrsa -aes256 -out private/ca.key.pem 2048

创建CA签名请求

openssl req -new -key private/ca.key.pem -out private/ca.csr

自己签发CA根证书

openssl x509 -req -days 3650 -sha1 -extensions v3_ca -signkey private/ca.key.pem -in private/ca.csr -out certificates/ca.cer

创建服务端私钥 

openssl genrsa -aes256 -out private/server.key.pem 2048
解密服务端私钥(win32下需要)
rsa -in private/server.key.pem -out private/server.key

创建服务端证书签发请求 

openssl req -new -key private/server.key.pem -out private/server.csr

利用CA根证书,签发服务端证书

openssl x509 -req -days 3650 -sha1 -extensions v3_req -CA certificates/ca.cer -CAkey private/ca.key.pem -CAserial ca.srl -CAcreateserial -in private/server.csr -out certificates/server.cer

创建客户端私钥

openssl genrsa -aes256 -out private/client.key.pem 2048

创建客户端证书签发请求

openssl req -new -key private/client.key.pem -out private/client.csr

利用CA根证书,签发客户端证书 

openssl x509 -req -days 3650 -sha1 -extensions v3_req -CA certificates/ca.cer -CAkey private/ca.key.pem -CAserial ca.srl -CAcreateserial -in private/client.csr -out certificates/client.cer

把客户端证书转换成p12格式

openssl pkcs12 -export -clcerts -inkey private/client.key.pem -in certificates/client.cer -out certificates/client.p12

配置示例

加载模块:LoadModule ssl_module modules/mod_ssl.so
#在给定的文件扩展名与特定的内容类型之间建立映射
AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl    .crl

#允许客户端使用哪些加密算法套件
SSLCipherSuite HIGH:MEDIUM:!MD5:!RC4
SSLProxyCipherSuite HIGH:MEDIUM:!MD5:!RC4

#允许除了SSLv2和SSLv3以外的其他SSL/TLS协议
SSLProtocol all -SSLv2 -SSLv3
SSLProxyProtocol all -SSLv2 -SSLv3

#优先使用服务器端的加密算法套件优先级顺序
SSLHonorCipherOrder on

#Apache在启动时获取用于解密私钥文件密语的方式,在win32下无效,所以win32私钥不能加密
#SSLPassPhraseDialog  builtin

#指定SSL会话缓存的类型,减少握手过程
SSLSessionCache        "shmcb:D:/develop/java/run/httpd-2.2.31-win64/logs/ssl_scache(512000)"
#指定SSL会话缓存有效期,单位秒
SSLSessionCacheTimeout  300

#这个指令指定了SSL引擎使用什么样的信号量(互斥锁)来在多个Apache服务器进程之间实现串行化互斥操作
SSLMutex default

Listen 9001
NameVirtualHost *:9001
<VirtualHost *:9001>
SSLEngine on
#服务器证书文件(PEM编码的X.509证书)
SSLCertificateFile "conf/test/server.cer"
#服务器私钥文件(PEM编码)
SSLCertificateKeyFile "conf/test/server.key.new.pem"

#客户端证书的验证级别
SSLVerifyClient require
#验证客户端证书有效性时允许的最大证书链深度
SSLVerifyDepth 1
#用于客户端认证的多合一CA证书(PEM格式),此CA签发的客户端才可以访问
SSLCACertificateFile "conf/test/ca.cer"

DocumentRoot D:/develop/java/run/apache-tomcat-8.5.6/webapps/docs
ServerName www.gjb.com
ErrorLog "|bin/rotatelogs.exe -l D:/develop/java/run/httpd-2.2.31-win64/logs/test/9001_error_log_%Y_%m_%d.log 86400"
CustomLog "|bin/rotatelogs.exe -l  D:/develop/java/run/httpd-2.2.31-win64/logs/test/9001_access_log_%Y_%m_%d.log 86400" combined

<Directory />
AllowOverride None
Order Deny,Allow
</Directory>
</VirtualHost>


负载均衡

所用Tomcat版本为8.5.6。
加载以下模块

LoadModule proxy_module modules/mod_proxy.so

LoadModule proxy_ajp_module modules/mod_proxy_ajp.so

LoadModule proxy_balancer_module modules/mod_proxy_balancer.so

LoadModule proxy_connect_module modules/mod_proxy_connect.so

LoadModule proxy_http_module modules/mod_proxy_http.so

负载均衡策略

轮询:将根据请求数,按顺序轮流地分配到后端服务器上,它均衡地对待后端的每一台服务器,而不关心服务器实际的连接数和当前的系统负载。

ProxyPass / balancer://mycluster lbmethod=byrequests
<Proxy balancer://mycluster>
BalancerMember ajp://1.2.3.4:8009
BalancerMember ajp://1.2.3.5:8009
</Proxy>


加权轮询:在轮询的基础上加了权重,权重高的多处理,权重低的少处理,权重因子loadfactor可以设置为1-100,这里可以设置lbmethod为bytraffic,意思是根据流量的权重分配,默认lbmethod是byrequests,即根据请求数的权重分配。

ProxyPass / balancer://mycluster lbmethod=byrequests
<Proxy balancer://mycluster>
BalancerMember ajp://1.2.3.4:8009 loadfactor=1
BalancerMember ajp://1.2.3.5:8009 loadfactor=2
</Proxy>


会话管理

stickysession:会话和某个Tomcat绑定,如果这个Tomcat宕机,那么会话就失效。

首先找到每个Tomcat的server.xml文件,在其中的Engine标签中加上jvmRoute属性。

<Engine name="Catalina" defaultHost="localhost" jvmRoute="a">
<Engine name="Catalina" defaultHost="localhost" jvmRoute="b">


接着配置Apache,stickysession=JSESSIONID|jsessionid表示的是后端服务器的session的cookie的key。JSESSIONID和jsessionid分别支持ajp和http。注意BalancerMember指令最后的route=a,这个要和jvmRoute属性值对应。原理是,Apache响应给客户端的cookie值后面会加上route的值,以此来记录cookie属于哪个Tomcat。nofailover是值有on和off,on表示当绑定的后端服务器错误时session中断,off则不会中断而是重新分配到其他后端服务器,在后端服务器不支持session复制的时候,最好设置为on。
#反向代理,balancer://mycluster要和Proxy指令的参数一致
ProxyPass /ice-web1 balancer://mycluster stickysession=JSESSIONID|jsessionid nofailover=off
#此指令使Apache调整HTTP重定向应答中Location, Content-Location, URI头里的URL。这样可以避免在Apache作为反向代理使用时,后端服务器的HTTP重定向造成的绕过反向代理的问题。
ProxyPassReverse /ice-web1 balancer://mycluster
<Proxy balancer://mycluster>
BalancerMember ajp://127.0.0.1:8009/ice-web1  route=a
BalancerMember ajp://127.0.0.1:8010/ice-web1  route=b
</Proxy>


session复制:在Tomcat间共享session,这个方案会消耗更多内存和带宽,tomcat官方推荐在集群比较小时采用此方案。

tomcat集群用的是组播技术,主要需要注意的配置是Membership和Receiver。Membership是组播组,Receiver是接收方。228.0.0.4是组播地址,这是一个保留地址,port是端口。同一个集群下的机器要加入相同的组播组,所以同一个集群下的tomcat的Membership是一样的。Receiver是接收组播信息的配置,如果两个tomcat在同一个机器,Receiver的port要不相同。如果在不同的机器Receiver的address最好改成ip,如果使用auto,他的值很可能是127.0.0.1,这样会导致接收不到消息。另外,要将Membership和Receiver的端口加入到防火墙中,不然也会无法访问。在每个Tomcat的Engine标签中配置如下:

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
         channelSendOptions="8">

    <Manager className="org.apache.catalina.ha.session.DeltaManager"
             expireSessionsOnShutdown="false"
             notifyListenersOnReplication="true"/>

    <Channel className="org.apache.catalina.tribes.group.GroupChannel">
        <Membership className="org.apache.catalina.tribes.membership.McastService"
                    address="228.0.0.4"
                    port="45564"
                    frequency="500"
                    dropTime="3000"/>
        <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                  address="auto"
                  port="4000"
                  autoBind="100"
                  selectorTimeout="5000"
                  maxThreads="6"/>

        <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
            <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
        </Sender>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
    </Channel>

    <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
           filter=""/>
    <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

    <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
              tempDir="/tmp/war-temp/"
              deployDir="/tmp/war-deploy/"
              watchDir="/tmp/war-listen/"
              watchEnabled="false"/>
    <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>


服务器监控

加载模块
LoadModule info_module modules/mod_info.so

LoadModule status_module modules/mod_status.so

配置

ExtendedStatus On
<Location /server-status>
SetHandler server-status
Order Allow,Deny
Allow from 127.0.0.1
</Location>

<Location /server-info>
SetHandler server-info
Order Allow,Deny
Allow from 127.0.0.1
</Location>

<Location /balancer-manager>
SetHandler balancer-manager
Order Allow,Deny
Allow from 127.0.0.1
</Location>


假如监听端口是9000,那么访问地址是:http://127.0.0.1:9000/server-status。有个地方要注意的,balancer-manager表示负载均衡监控,如果负载均衡配置在虚拟主机里,那么访问这个监控网页需要输入的是虚拟主机的主机名和端口。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: