httpd代理
正代
httpd可以配置为正向代理,如局域网内部的正代上网出口,一般不常用,可以设置只允许部分局域网内部的ip进行正代上网;
ProxyRequests on
#通过启用proxyrequests指令,即可启动正代服务;
ProxyVia on
<Proxy "*">
Require host www.a.com
</Proxy>
#proxy指令设置,允许正代的客户端ip,以及允许正代出去访问的url
www.a.com 的主机,可以通过该httpd的代理,访问所有url,proxyvia,可以在响应首部加一个via字段
客户端可通过这个知道中间经由了哪个客户端;
eg:
1,httpd配置正代:
[root@www conf.d]# cat proxy.conf
ProxyRequests on
Proxyvia on
<Proxy "*">
Require ip 192.168.80.100
</Proxy>
[root@www conf.d]# pwd
/etc/httpd/conf.d
然后重启;
2,客户端加代理,不加代理访问;
[root@localhost ~]# curl -h |grep proxy
--noproxy List of hosts which do not use proxy
-x, --proxy [PROTOCOL://]HOST[:PORT] Use proxy on given port
[root@localhost ~]# curl -I www.baidu.com
HTTP/1.1 200 OK
...
Server: bfe/1.0.8.1
加了代理后,头部多了个via字段;
# curl的-x参数,可以指定正向代理的信息;
[root@localhost ~]# curl -I -x 192.168.80.101:80 www.baidu.com
HTTP/1.1 200 OK
...
Pragma: no-cache
Via: 1.1 www.b.com
反代
https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html
httpd做反代的场景更常用,做反向代理时,分为同构协议反代,和异构协议反代,同构可以代理http协议,异构可以代理factcgi协议,和后端php服务器通信,常见于lamp环境;
反代服务器,屏蔽了后端的真实服务器,接收客户端请求,转发到后端服务器处理,接收后端发来的处理结果,再转给客户端;
同构反代http
1、如下,为同构,反代http协议时配置示例:
---
host3上:配2个虚拟主机;
[root@host3 conf.d]# cat vhosts.conf
<Directory "/data/host3/www1">
Require all granted
</Directory>
<Directory "/data/host3/www2">
Require all granted
</Directory>
<VirtualHost *:80>
ServerName www1.host3.com
DocumentRoot "/data/host3/www1"
</VirtualHost>
<VirtualHost *:80>
ServerName www2.host3.com
DocumentRoot "/data/host3/www2"
</VirtualHost>
---
host2上:写入一个index,然后重启;
[root@host2 httpd]# cat /var/www/html/index.html
host2-index
[root@host2 httpd]
---
host1做client,访问host2
[root@host1 ~]# curl http://www.host2.com
host2-index
此时为host2的主页
---
host2加上反代配置,注意重启生效;
[root@host2 httpd]# cat conf.d/proxy.conf
ProxyPass "/" "http://www1.host3.com"
ProxyPassReverse "/" "http://www1.host3.com"
[root@host2 httpd]#
---
此时host1再访问host2,就已经是被代理的网页了!
[root@host1 ~]# curl http://www.host2.com
www1.host3
--
【遇到的错误】
上面的错误:加index.html访问出错;
[root@host1 ~]# curl http://www.host2.com
www1.host3
[root@host1 ~]# curl http://www.host2.com/index.html
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>502 Proxy Error</title>
...
html">GET /index.html</a></em>.<p>
Reason: <strong>DNS lookup failure for: www1.host3.comindex.html</strong></p></p>
</body></html>
如下:加了斜线后
[root@host2 httpd]# cat conf.d/proxy.conf
ProxyPass "/" "http://www1.host3.com/"
ProxyPassReverse "/" "http://www1.host3.com/"
再访问正常;【还是等效替换的方法】
原来的没加斜线,访问/index.html就-》host3.comindex.html,自然找不到,映射时加个斜线即-》host3.com/index.html,就对应/data/host3/www1/index.html了;
[root@host1 ~]# curl http://www.host2.com/index.html
www1.host3
eg2:
[root@host2 httpd]# cat conf.d/proxy.conf
ProxyPass "/images" "http://www1.host3.com"
ProxyPassReverse "/images" "http://www1.host3.com"
注意顺序,范围小的放前面!
ProxyPass "/" "http://www1.host3.com/"
ProxyPassReverse "/" "http://www1.host3.com/"
[root@host1 ~]# curl http://www.host2.com/images/1.jpg
1.jpg
[root@host1 ~]# curl http://www.host2.com/images/2.jpg
2.jpg
2、配置时需注意问题:
【地址重定向时的反向代理,要多加一行ProxyPassReverse指令,后面的和ProxyPass保持一致即可;】
举例说:
ProxyPass "/images" "http://www.a1.com"
ProxyPassReverse "/images" "http://www.a1.com"
客户端请求http://www.a.com/images/a.gif 时;
会反代到http://www.a1.com/a.gif
如果a.gif被重定向到了b.gif
那么没有ProxyPassReverse时,反代服务器返回给客户的重定向信息时:http://www.a1.com/b.gif,客户群请求该url,是无法访问到的,因为a1是内网地址,无法直接访问;
如果加了ProxyPassReverse ,反代服务器返回给客户端的重定向信息是:http://www.a.com/images/b.gif;客户端访问该url,后,被被反代到a1.com 的b.gif,此时才正常;
【反代,和重定向:反代是反代服务器代为访问,返回结果;重定向是返回重定向到的新url,由客户端自己去访问,】
异构反代fastcgi
如下,为反代配置示例:
eg:
ProxyPass "/" "http://www.a1.com/"
ProxyPassMatch "^(.*\.php)$" "fcgi://127.0.0.1:9000/var/www/html/$1"
加了fcgi的协议头
后端主机组配置
主机组配置
将一组后端服务器,定义为一个后端服务器组;此时采用各种调度算法,轮询,加权轮询,【可以实现负载分流,故障转移,线性扩缩容等功能】
示例1:
<Proxy balancer://myset>
BalancerMember http://1.1.1.1:8080
BalancerMember http://2.2.2.2:8080
ProxySet lbmethod=bytraffic
调度算法
</Proxy>
# 用proxy指令定义一个后端服务器组:myset为组名,balancermember定义一各个后端节点,
proxyset可以定义该后端服务器组的属性信息,如调度算法;
ProxyPass "/images/" "balancer://myset/"
ProxyPassReverse "/images" "balancer://myset/"
proxypass处引用,后端服务器组的组名即可,【注意/加还是不加】
#每个balancermember后可以定义每个后端节点属性信息,如权重、超时时长、是否禁用,是否是备用
<Proxy balancer://myset>
BalancerMember http://1.1.1.1:8080
BalancerMember http://2.2.2.2:8080 Loadfactor=3 timeout=1
权重为1:3
ProxySet lbmethod=byrequests
调度算法
</Proxy>
eg:
反代配置:示例参考官方doc,/的位置,不符合等效替代法了。。
[root@host2 httpd]# cat conf.d/proxy.conf
#ProxyPass "/images" "http://www1.host3.com"
#ProxyPassReverse "/images" "http://www1.host3.com"
#ProxyPass "/" "http://www1.host3.com/"
#ProxyPassReverse "/" "http://www1.host3.com/"
<Proxy balancer://back1>
BalancerMember http://www1.host3.com
BalancerMember http://www2.host3.com
ProxySet lbmethod=byrequests
</Proxy>
ProxyPass "/img" "balancer://back1/"
ProxyPassReverse "/img" "balancer://back1/"
后端服务器:
[root@host3 conf.d]# tree /data/host3/
/data/host3/
├── www1
│ └── 2.html
└── www2
└── 2.html
访问测试
[root@host1 ~]# curl http://www.host2.com/img/2.html
www222.html
[root@host1 ~]# curl http://www.host2.com/img/2.html
www111.html
各个节点属性信息配置
主机组内,每个节点都可以设置属性信息,如权重、是否备用,是否禁用,
后端节点可以设置优先级、热备节点
eg:
<Proxy balancer://myset>
BalancerMember http://master1.com:8080
BalancerMember http;//master2.com:8080
BalancerMember http://back1.com:8080 lbset=1
BalancerMember http://back2.com:8080 lbset=1
BalancerMember http://hotstandby.com:8080 status=+H
</Proxy>
master1 master2正常时,优先轮询调度;两个都失败时;
back1 back2登场,因为lbset=1,设置它优先级低于 master1和2,默认lbset=0,数越大,优先级越低
back1和2都坏了,hoststandby生效,因为设置了status=+H
eg:
[root@host2 conf.d]# cat proxy.conf
<Proxy balancer://back1>
BalancerMember http://www1.host3.com
BalancerMember http://www2.host3.com Loadfactor=2 Timeout=2
BalancerMember http://www.host1.com status=+H
ProxySet lbmethod=byrequests
</Proxy>
ProxyPass "/img" "balancer://back1/"
ProxyPassReverse "/img" "balancer://back1/"
再启一台host1,做热备,重启,
客户端测试,结果是
www1 www2的权重轮询,2者都坏,host1就顶上了;
lbset=1不生效?
调度算法
httpd支持三种调度算法:
- bytraffice
- byrequests
- bybusyness
调度算法3种:
byrequests 默认,基于请求次数计算权重
bytraffic 基于io大小算权重
bybusyness 基于挂起请求数,即后端的繁忙程度算权重
负载均衡状态页、管理页
<Location "/balancer-manager">
SetHandler balancer-manager
Require host localhost
</Location>
<Location "/server-status">
SetHandler server-status
Require ip 192.168.80.100
</Location>、
摘自官方doc,直接贴,重启;
浏览器访问该uri即可
健康检查
1、提供检查功能的模块
ProxyPass指令自带ping指令,可判断后端节点是否可以ping通,但http服务只ping不够准确;
mod_proxy_hcheck模块提供了对http服务检查的指令;
[root@host2 httpd-2.4.27]# ll /usr/local/apache/modules/ |grep check
-rwxr-xr-x 1 apache apache 105896 Aug 18 19:35 mod_proxy_hcheck.so
[root@host2 httpd-2.4.27]# ./configure -h |grep hcheck
--enable-proxy-hcheck reverse-proxy health-check module. Requires
默认不启用该模块,编译时需要明确指定编译该模块,
2、检查配置示例:
检查的方法:常见检查方法有2种,tcp检查,和http探测;
hcmethod
TCP
OPTIONS
HEAD
GET
检查的属性参数
hcinterval 默认30s,检查间隔
hcuri 检查哪个uri
hcpasses=N 默认1,检查几次通过,认为检查,再次启动
hcfails=N 默认1,检查几次失败,认为不可用
eg:
<Proxy balancer://back1>
BalancerMember http://www.a.com/ hcmethod=TCP hcinterval=5 hcpasses=3 hcfails=5
BalancerMember http://www.b.com/ hcmethod=GET hcuri=/status.php
BalancerMember http://www.c.com/
</Proxy>
ProxyPass "/" "balancer://back1"
ProxyPassReverse "/" "balancer://back1"
【注意:/斜线的问题】
访问反代的/1.jpg 对应balancer://back1+1.jpg
又对应,www.a.com/+1.jpg
所以最后访问的是www.a.com/1.jpg
3、带有变量的检查方法
参考文档:https://httpd.apache.org/docs/2.4/mod/mod_proxy_hcheck.html#proxyhcexpr
# 通过ProxyHCExpr指令,设置变量,该变量利用正则对应匹配探测响应报文的头部或body部分,
# 再在每个节点出引用该变量,作为判断节点是否健康的依据
ProxyHCExpr ok234 {%{REQUEST_STATUS} =~ /^[234]/}
ProxyHCExpr gdown {%{REQUEST_STATUS} =~ /^[5]/}
ProxyHCExpr in_maint {hc('body') !~ /Under maintenance/}
<Proxy balancer://foo>
BalancerMember http://www.example.com/ hcmethod=GET hcexpr=in_maint hcuri=/status.php
BalancerMember http://www2.example.com/ hcmethod=HEAD hcexpr=ok234 hcinterval=10
BalancerMember http://www3.example.com/ hcmethod=TCP hcinterval=5 hcpasses=2 hcfails=3
BalancerMember http://www4.example.com/
</Proxy>
ProxyPass "/" "balancer://foo"
ProxyPassReverse "/" "balancer://foo"
Proxy相关指令
实验中例子;
[root@host2 conf.d]# cat proxy.conf
#ProxyPass "/images" "http://www1.host3.com"
#ProxyPassReverse "/images" "http://www1.host3.com"
#ProxyPass "/" "http://www1.host3.com/"
#ProxyPassReverse "/" "http://www1.host3.com/"
ProxyStatus On
ProxyVia on
<Location "/doc">
ProxyPass "http://www1.host3.com"
</Location>
ProxyPassMatch "^/(.*\.gif)$" "http://www.host1.com/$1"
<Proxy balancer://back1>
BalancerMember http://www1.host3.com
BalancerMember http://www2.host3.com Loadfactor=2 Timeout=2
BalancerMember http://www.host1.com status=+H
ProxySet lbmethod=byrequests
</Proxy>
ProxyPass "/img" "balancer://back1/"
ProxyPassReverse "/img" "balancer://back1/"
# 开启2个页面,后端主机组管理页面,和状态页面
# 注意设置较为严格的访问权限
<Location "/balancer-manager">
SetHandler balancer-manager
Require host localhost
Require ip 192.168.80.100
</Location>
<Location "/server-status">
SetHandler server-status
Require ip 192.168.80.100
</Location>
ProxyPass
1,配置反代,应关闭正代
ProxyRequests=off
2,ProxyPass 语法
Syntax: ProxyPass [path] !|url [key=value [key=value ...]] [nocanon] [interpolate] [noquery]
ProxyPass [path] !|url [key=valuse...]
path为反代对客户端提供的url路径;
url为后端服务器提供实际内容的url路径;
若为!,表示path表示的路径,不做反代处理
key=value是一些属性设置,设置后端节点的属性;
3,示例:
ProxyPass "/images/" "http://www.b.com/"
或
ProxyPass "/images" "http://www.b.com"
可以看出;path和url部分,对于末尾斜线,要么都由,要么都没有;
4,location容器中,不需要指定path,因为location本身就带了path配置
<Location "/images">
ProxyPass "http://www.a.com"
</Location>
访问http://反代机器/images/1.jpg 会反代到http://www.a.com/1.jpg
<Location "/doc">
ProxyPass "http://www1.host3.com"
</Location>
5,eg
ProxyPass "/images/1.jpg" "!"
ProxyPass "/images/" "http://www.a.com/"
1.jpg不反代,其他都反代;
----
httpd用连接池组织后端的节点;节点属性相同的共享一个连接池;后端节点属性,kv值指定
keepalive=on|off默认off,一般也是off
lbset=N,后端节点优先级,数越大,优先级越小;
httpd只有找不到上一个高优先级的节点之后,才会找下一个优先级的节点;
ping=N,和后端tomat通过ajp协议ping探测的时间间隔;
retry=N,检查到后端节点错误时,多久后重试
timeout=ProxyTimeout,等待后端返回数据的超时时间;
status=value,设置节点状态;
+为设置
-为取消设置
D:禁用节点
H:备份节点
I:无视该节点的错误
S:节点维护期
E:节点为错误状态
N:节点drain模式,只接收已预订的sticky session
---
用了balancer://后,其中节点可共享一部分属性,用ProxySet设置;
lbmethod= bytraffic byrequests bybusyness
三种调度算法
nofailover=on|off,是否开启故障状态,当后端节点之间,没有会话复制的时候,建议为on,不要失败转移,因为即便转移了,会话在新机器上也没有,直接返回错误才恰当
stickysession:sesssion名称如:JSESSIOND PHPSESSION
---
eg:
都不带斜线
<Proxy balancer://myset>
BalancerMember http://www.a.com
BalancerMember http://www.b.com Loadfactor=3 Timeout=3
ProxySet lbmethod=byrequests
</Proxy>
都带斜线
ProxyRequests off
ProxyPass "/images/" "balancer://myset/"
ProxyPassReverse "/images/" "balancer://myset/"
注意:斜线的一致原则,判断方法,位置等效替代;
/images/1.jpg > myset/1.jpg
myset/1.jpg > http://www.a.com/1.jpg
此时a.com的1.jpg有文件,就可以了
ProxyPassMatch
支持正则的ProxyPass;
eg:
ProxyPassMatch "^/(.*\.jpg)$" "http://www.a.com/$1"
ProxyPassMatch "^/(.*\.php)$" "fcgi://127.0.0.1:9000/var/www/a.com/$1"
两处都是分组匹配,注意/没有归到分组里;
^/的/和/$1的/ ,2者对应;
ProxySet
设置后端节点的属性,一般设置在一个proxy节点组里;
如该主机组的调度算法,是否开启长连接
<Proxy "balancer://back1">
BalancerMember "http://www.a.com"
BalancerMember "http://www.b.com" Loadfactor=2 Timeout=3
ProxySet lbmethod=bytraffic
ProxySet keealive=on
</Proxy>
ProxySet "balancer://foo" lbmethod=traffic timeout=15
也可以单独设置;
Proxy容器
<proxy>容器,用于封装proxy相关的指令;主要用来定义后端节点组,他们的属性,调度算法;
然后再proxyPass中引用;
<Proxy "*">
Require host yournetwork.example.com
</Proxy>
ProxyStatus
ProxyStatus {on|off|full}
on=full,开启后,server-stauts页面会有代理相关信息
需要开启状态页,定义一个location,并用set-handler指令开启状态页
eg:
ProxyStatus on
<Location "/server-status">
SetHandler server-stauts
Require all granted
</Location>
浏览器打开状态页,会有代理相关信息;
ProxyVia
ProxyVia on开启时,反代服务器会在给客户端的响应头部中加入一个字段:Via:值一般是反代服务器的ip
告知客户端,你的请求是经由反代转发的,我其实是个反代;
curl -I http://反代/index.html
开启后,
会发现多了个Via字段;
[root@host1 ~]# curl -I http://www.host2.com/hello.gif
HTTP/1.1 200 OK
...
Content-Type: image/gif
Via: 1.1 www.host2.com
ProxyPass指令顺序、共享
顺序
Proxypass 范围小的放前面、看的是在配置文件中出现的位置先后;location无所谓、看的是uri匹配长短
proxypass根据出现的先后顺序生效;前面的被匹配生效了;
后面的就不看了;
但在location容器中,不看location的顺序,而看location中定义的uri的匹配的长度的长短;
即,最长匹配原则
eg:
ProxyPass "/images/1.jpg" "!"
ProxyPass "/images" "http://www.a.com"
此时,请求1.jpg是不会被反代的,顺序一换;就会被反代;
ProxyPass "/images" "http://www.a.com"
ProxyPass "/images/1.jpg" "!"
如果是在location里,顺序就不影响了
<Location "/images">
ProxyPass "http://www.a.com"
</Location>
<Location "/images/1.jpg">
ProxyPass "!"
</Location>
此时仍会被第2个location处理,不被反代,因为它匹配的更长,
共享
后端节点设置的属性会被共享的,
eg:
ProxyPass "/apps" "http://www.a.com" Timeout=10
ProxyPass "/pcs" "http://www.a.com" Timeout=5
访问/pcs/pc1.html
会被第2个处理,但超时时间可是10,不是5;这就是共享;
不太懂?
location指令总结:
https://httpd.apache.org/docs/2.4/mod/core.html#location
location 指令可以结合其他指令一起使用,如:alias,redirect,proxypass,以及单独使用,location指令的作用是定义一个uri路径对外提供,结合其他指令使用时,这个uri可以被映射到本地文件系统路径(alias);可以被重定向到一个新的uri或完整的url(redirect);可以被反代到其他服务器(proxypass),可以开启内置状态页(结合set-handler);可以单独使用(结合directory,放开本地文件系统目录提供uri)
结合alias
<location "uri路径">
alias 本地文件系统路径
</location>
结合redirect
<location "旧的uri路径">
redirect 状态码 新的uri路径
</location>
结合proxypass
<Location "/images">
ProxyPass "http://www.a.com"
</Location>
结合set-handler
<Location "/server-status">
SetHandler server-status
Require ip 192.168.80.100
</Location>、