httpd之七层代理服务

httpd做七层代理服务,httpd可以代理同构协议http,也可以代理异构协议如factcgi等...

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&nbsp;/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>、
updatedupdated2020-10-162020-10-16
加载评论