Skip to content

Commit 9d41cb6

Browse files
committed
new doc
1 parent cb750a8 commit 9d41cb6

File tree

7 files changed

+387
-0
lines changed

7 files changed

+387
-0
lines changed

201911/20191101_01.md

Lines changed: 380 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,380 @@
1+
## PostgreSQL HAProxy ha & load balance 代理
2+
3+
### 作者
4+
digoal
5+
6+
### 日期
7+
2019-11-01
8+
9+
### 标签
10+
PostgreSQL , haproxy , master listen , slave(s) listen , ha , stream replication , session loadbalance , xinetd
11+
12+
----
13+
14+
## 背景
15+
HAProxy是一个非常流行的4层、7层(http)负载均衡与会话路由软件,效率也非常高。
16+
17+
虽然他没有办法直接实现pg的读写分离,但是可以实现比较简单的几类PG接入点(监听点)以及会话failover管理:
18+
19+
1、一个或多个主实例。(多个主实例通常是指如下架构:pg-xl的coordinator, citus的coordinator。或者完全对等的multi-master节点。)
20+
21+
![pic](20191101_01_pic_001.jpg)
22+
23+
当会话对应的后端数据库检测到不符合预期状态时,主动断开会话,重联。(failover 会话)
24+
25+
rw点切换后,主动断开这个节点的会话,迁移到新的rw节点
26+
27+
![pic](20191101_01_pic_002.jpg)
28+
29+
2、一个或多个只读实例。(例如一主多从多结构)
30+
31+
当后端有多个ro节点时,可以load balance(会话级)
32+
33+
![pic](20191101_01_pic_003.jpg)
34+
35+
切换后,主动断开这个节点的会话,迁移到新的ro节点
36+
37+
![pic](20191101_01_pic_004.jpg)
38+
39+
## 实现例子
40+
参考 https://www.percona.com/blog/2019/10/31/postgresql-application-connection-failover-using-haproxy-with-xinetd/
41+
42+
环境: CentOS 7, PostgreSQL , 主从 多台 (主从切换不需要haproxy管,haproxy只负责根据后端数据库的状态切换会话)
43+
44+
准备几个东西
45+
46+
- A simple shell script to check the status of the PostgreSQL instance running on the local machine.
47+
- A xinetd service daemonizer.
48+
- HAProxy: Which maintains the routing mechanism.
49+
50+
### 数据库服务器部署:check 后端数据库的脚本
51+
这个脚本配置在数据库服务器上,用来获取数据库的三种状态:
52+
53+
1、恢复中(从库),返回206
54+
55+
2、主库,返回200
56+
57+
3、无法确认(数据库连接不上或其他问题),返回503
58+
59+
脚本如下,不同状态返回不同的内容:
60+
61+
```
62+
#!/bin/bash
63+
# This script checks if a postgres server is healthy running on localhost. It will return:
64+
# "HTTP/1.x 200 OK\r" (if postgres is running smoothly)
65+
# - OR -
66+
# "HTTP/1.x 500 Internal Server Error\r" (else)
67+
# The purpose of this script is make haproxy capable of monitoring postgres properly
68+
# It is recommended that a low-privileged postgres user is created to be used by this script.
69+
# For eg. create user healthchkusr login password 'hc321';
70+
71+
PGBIN=/usr/pgsql-10/bin
72+
PGSQL_HOST="localhost"
73+
PGSQL_PORT="5432"
74+
PGSQL_DATABASE="postgres"
75+
PGSQL_USERNAME="postgres"
76+
export PGPASSWORD="passwd"
77+
TMP_FILE="/tmp/pgsqlchk.out"
78+
ERR_FILE="/tmp/pgsqlchk.err"
79+
80+
81+
# We perform a simple query that should return a few results
82+
# 调用如下脚本,看返回结果pg_is_in_recovery看是不是在恢复中,t表示从库。f表示主库。
83+
84+
VALUE=`/opt/bigsql/pg96/bin/psql -t -h localhost -U postgres -p 5432 -c "select pg_is_in_recovery()" 2> /dev/null`
85+
# Check the output. If it is not empty then everything is fine and we return something. Else, we just do not return anything.
86+
87+
88+
if [ $VALUE == "t" ]
89+
then
90+
/bin/echo -e "HTTP/1.1 206 OK\r\n"
91+
/bin/echo -e "Content-Type: Content-Type: text/plain\r\n"
92+
/bin/echo -e "\r\n"
93+
/bin/echo "Standby"
94+
/bin/echo -e "\r\n"
95+
elif [ $VALUE == "f" ]
96+
then
97+
/bin/echo -e "HTTP/1.1 200 OK\r\n"
98+
/bin/echo -e "Content-Type: Content-Type: text/plain\r\n"
99+
/bin/echo -e "\r\n"
100+
/bin/echo "Primary"
101+
/bin/echo -e "\r\n"
102+
else
103+
/bin/echo -e "HTTP/1.1 503 Service Unavailable\r\n"
104+
/bin/echo -e "Content-Type: Content-Type: text/plain\r\n"
105+
/bin/echo -e "\r\n"
106+
/bin/echo "DB Down"
107+
/bin/echo -e "\r\n"
108+
fi
109+
```
110+
111+
脚本位置/opt/pgsqlchk
112+
113+
```
114+
sudo chmod 755 /opt/pgsqlchk
115+
```
116+
117+
118+
### 数据库服务器部署:配置 xinetd 服务(check后端)
119+
将/opt/pgsqlchk 检查脚本配置为xinetd服务,通过某个监听端口调用(本例为23267)
120+
121+
```
122+
yum install -y xinetd telnet
123+
124+
vi /etc/xinetd.d/pgsqlchk
125+
126+
service pgsqlchk
127+
{
128+
flags = REUSE
129+
socket_type = stream
130+
port = 23267
131+
wait = no
132+
user = nobody
133+
server = /opt/pgsqlchk
134+
log_on_failure += USERID
135+
disable = no
136+
only_from = 0.0.0.0/0
137+
per_source = UNLIMITED
138+
}
139+
```
140+
141+
添加xinetd服务
142+
143+
```
144+
bash -c 'echo "pgsqlchk 23267/tcp # pgsqlchk" >> /etc/services'
145+
```
146+
147+
启动xinetd服务
148+
149+
```
150+
systemctl start xinetd
151+
```
152+
153+
### HAproxy节点部署
154+
假设以上有两台数据库服务器pg0, pg1 (hostname, or dns配置).
155+
156+
另一台服务器,用于部署haproxy,如下。
157+
158+
```
159+
yum install -y haproxy
160+
```
161+
162+
163+
配置haproxy.cfg
164+
165+
监听两个端口,5000对应check返回200状态的数据库节点(pg_is_in_recovery=f),为rw节点
166+
167+
5001对应check返回206状态的数据库节点(pg_is_in_recovery=t),为ro节点
168+
169+
170+
```
171+
vi /etc/haproxy/haproxy.cfg
172+
173+
global
174+
maxconn 100
175+
176+
defaults
177+
log global
178+
mode tcp
179+
retries 2
180+
timeout client 30m
181+
timeout connect 4s
182+
timeout server 30m
183+
timeout check 5s
184+
185+
listen stats
186+
mode http
187+
bind *:7000
188+
stats enable
189+
stats uri /
190+
191+
listen ReadWrite
192+
bind *:5000
193+
option httpchk
194+
http-check expect status 200
195+
default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
196+
server pg0 pg0:5432 maxconn 100 check port 23267
197+
server pg1 pg1:5432 maxconn 100 check port 23267
198+
199+
listen ReadOnly
200+
bind *:5001
201+
option httpchk
202+
http-check expect status 206
203+
default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
204+
server pg0 pg0:5432 maxconn 100 check port 23267
205+
server pg1 pg1:5432 maxconn 100 check port 23267
206+
```
207+
208+
配置解读
209+
210+
- HAProxy is configured to use TCP mode
211+
- HAProxy service will start listening to port 5000 and 5001
212+
- Port 5000 is for Read-Write connections and 5001 is for Read-Only connections
213+
- Status check is done using http-check feature on port 23267
214+
- Both server pg0 and pg1 are candidates for both Read-write and Read-only connections
215+
- Based on the http-check and the status returned, it decides the current role
216+
217+
如果只读节点有多台,配置到server里面即可。
218+
219+
启动 haproxy服务
220+
221+
```
222+
systemctl start haproxy
223+
```
224+
225+
### 测试
226+
连接haproxy 5000端口,读写节点。
227+
228+
```
229+
$ psql -h localhost -p 5000 -U postgres
230+
Password for user postgres:
231+
psql (9.6.5)
232+
Type "help" for help.
233+
234+
postgres=# select pg_is_in_recovery();
235+
pg_is_in_recovery
236+
-------------------
237+
f
238+
(1 row)
239+
```
240+
241+
连接haproxy 5001端口,只读节点。
242+
243+
```
244+
$ psql -h localhost -p 5001 -U postgres
245+
Password for user postgres:
246+
psql (9.6.5)
247+
Type "help" for help.
248+
249+
postgres=# select pg_is_in_recovery();
250+
pg_is_in_recovery
251+
-------------------
252+
t
253+
(1 row)
254+
```
255+
256+
## haproxy配置介绍
257+
258+
https://www.cnblogs.com/MacoLee/p/5853413.html
259+
260+
https://www.jianshu.com/p/8af373981cfe
261+
262+
```
263+
###########全局配置#########
264+
global
265+
  log 127.0.0.1 local0 #[日志输出配置,所有日志都记录在本机,通过local0输出]
266+
  log 127.0.0.1 local1 notice #定义haproxy 日志级别[error warringinfo debug]
267+
  daemon #以后台形式运行harpoxy
268+
  nbproc 1 #设置进程数量
269+
  maxconn 4096 #默认最大连接数,需考虑ulimit-n限制
270+
  #user haproxy #运行haproxy的用户
271+
  #group haproxy #运行haproxy的用户所在的组
272+
  #pidfile /var/run/haproxy.pid #haproxy 进程PID文件
273+
  #ulimit-n 819200 #ulimit 的数量限制
274+
  #chroot /usr/share/haproxy #chroot运行路径
275+
  #debug #haproxy 调试级别,建议只在开启单进程的时候调试
276+
  #quiet
277+
278+
########默认配置############
279+
defaults
280+
  log global
281+
  mode http #默认的模式mode { tcp|http|health },tcp是4层,http是7层,health只会返回OK
282+
  option httplog #日志类别,采用httplog
283+
  option dontlognull #不记录健康检查日志信息
284+
  retries 2 #两次连接失败就认为是服务器不可用,也可以通过后面设置
285+
  #option forwardfor #如果后端服务器需要获得客户端真实ip需要配置的参数,可以从Http Header中获得客户端ip
286+
  option httpclose #每次请求完毕后主动关闭http通道,haproxy不支持keep-alive,只能模拟这种模式的实现
287+
  #option redispatch #当serverId对应的服务器挂掉后,强制定向到其他健康的服务器,以后将不支持
288+
  option abortonclose #当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接
289+
  maxconn 4096 #默认的最大连接数
290+
  timeout connect 5000ms #连接超时
291+
  timeout client 30000ms #客户端超时
292+
  timeout server 30000ms #服务器超时
293+
  #timeout check 2000 #心跳检测超时
294+
  #timeout http-keep-alive10s #默认持久连接超时时间
295+
  #timeout http-request 10s #默认http请求超时时间
296+
  #timeout queue 1m #默认队列超时时间
297+
  balance roundrobin #设置默认负载均衡方式,轮询方式
298+
  #balance source #设置默认负载均衡方式,类似于nginx的ip_hash
299+
  #balnace leastconn #设置默认负载均衡方式,最小连接数
300+
301+
########统计页面配置########
302+
listen stats
303+
  bind 0.0.0.0:1080 #设置Frontend和Backend的组合体,监控组的名称,按需要自定义名称
304+
  mode http #http的7层模式
305+
  option httplog #采用http日志格式
306+
  #log 127.0.0.1 local0 err #错误日志记录
307+
  maxconn 10 #默认的最大连接数
308+
  stats refresh 30s #统计页面自动刷新时间
309+
  stats uri /stats #统计页面url
310+
  stats realm XingCloud\ Haproxy #统计页面密码框上提示文本
311+
  stats auth admin:admin #设置监控页面的用户和密码:admin,可以设置多个用户名
312+
  stats auth Frank:Frank #设置监控页面的用户和密码:Frank
313+
  stats hide-version #隐藏统计页面上HAProxy的版本信息
314+
  stats admin if TRUE #设置手工启动/禁用,后端服务器(haproxy-1.4.9以后版本)
315+
316+
########设置haproxy 错误页面#####
317+
#errorfile 403 /home/haproxy/haproxy/errorfiles/403.http
318+
#errorfile 500 /home/haproxy/haproxy/errorfiles/500.http
319+
#errorfile 502 /home/haproxy/haproxy/errorfiles/502.http
320+
#errorfile 503 /home/haproxy/haproxy/errorfiles/503.http
321+
#errorfile 504 /home/haproxy/haproxy/errorfiles/504.http
322+
323+
########frontend前端配置##############
324+
frontend main
325+
  bind *:80 #这里建议使用bind *:80的方式,要不然做集群高可用的时候有问题,vip切换到其他机器就不能访问了。
326+
  acl web hdr(host) -i www.abc.com #acl后面是规则名称,-i为忽略大小写,后面跟的是要访问的域名,如果访问www.abc.com这个域名,就触发web规则,。
327+
  acl img hdr(host) -i img.abc.com #如果访问img.abc.com这个域名,就触发img规则。
328+
  use_backend webserver if web #如果上面定义的web规则被触发,即访问www.abc.com,就将请求分发到webserver这个作用域。
329+
  use_backend imgserver if img #如果上面定义的img规则被触发,即访问img.abc.com,就将请求分发到imgserver这个作用域。
330+
  default_backend dynamic #不满足则响应backend的默认页面
331+
332+
########backend后端配置##############
333+
backend webserver #webserver作用域
334+
  mode http
335+
  balance roundrobin #balance roundrobin 负载轮询,balance source 保存session值,支持static-rr,leastconn,first,uri等参数
336+
  option httpchk /index.html HTTP/1.0 #健康检查, 检测文件,如果分发到后台index.html访问不到就不再分发给它
337+
  server web1 10.16.0.9:8085 cookie 1 weight 5 check inter 2000 rise 2 fall 3
338+
  server web2 10.16.0.10:8085 cookie 2 weight 3 check inter 2000 rise 2 fall 3
339+
  #cookie 1表示serverid为1,check inter 1500 是检测心跳频率
340+
  #rise 2是2次正确认为服务器可用,fall 3是3次失败认为服务器不可用,weight代表权重
341+
342+
backend imgserver
343+
  mode http
344+
  option httpchk /index.php
345+
  balance roundrobin
346+
  server img01 192.168.137.101:80 check inter 2000 fall 3
347+
  server img02 192.168.137.102:80 check inter 2000 fall 3
348+
349+
backend dynamic
350+
  balance roundrobin
351+
  server test1 192.168.1.23:80 check maxconn 2000
352+
  server test2 192.168.1.24:80 check maxconn 2000
353+
354+
355+
listen tcptest
356+
  bind 0.0.0.0:5222
357+
  mode tcp
358+
  option tcplog #采用tcp日志格式
359+
  balance source
360+
  #log 127.0.0.1 local0 debug
361+
  server s1 192.168.100.204:7222 weight 1
362+
  server s2 192.168.100.208:7222 weight 1
363+
```
364+
365+
## 参考
366+
https://www.percona.com/blog/2019/10/31/postgresql-application-connection-failover-using-haproxy-with-xinetd/
367+
368+
https://www.jianshu.com/p/8af373981cfe
369+
370+
https://www.cnblogs.com/MacoLee/p/5853413.html
371+
372+
373+
#### [免费领取阿里云RDS PostgreSQL实例、ECS虚拟机](https://free.aliyun.com/ "57258f76c37864c6e6d23383d05714ea")
374+
375+
376+
#### [digoal's PostgreSQL文章入口](https://github.com/digoal/blog/blob/master/README.md "22709685feb7cab07d30f30387f0a9ae")
377+
378+
379+
![digoal's weixin](../pic/digoal_weixin.jpg "f7ad92eeba24523fd47a6e1a0e691b59")
380+

201911/20191101_01_pic_001.jpg

67 KB
Loading

201911/20191101_01_pic_002.jpg

68.2 KB
Loading

201911/20191101_01_pic_003.jpg

75.3 KB
Loading

201911/20191101_01_pic_004.jpg

75.5 KB
Loading

201911/readme.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<a rel="nofollow" href="http://info.flagcounter.com/h9V1" ><img src="http://s03.flagcounter.com/count/h9V1/bg_FFFFFF/txt_000000/border_CCCCCC/columns_2/maxflags_12/viewers_0/labels_0/pageviews_0/flags_0/" alt="Flag Counter" border="0" ></a>
2+
3+
### 文章列表
4+
----
5+
##### 20191101_01.md [《PostgreSQL HAProxy ha & load balance 代理》](20191101_01.md)

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ digoal's|PostgreSQL|文章|归类
5757

5858
### 所有文档如下
5959
----
60+
##### 201911/20191101_01.md [《PostgreSQL HAProxy ha & load balance 代理》](201911/20191101_01.md)
61+
----
6062
##### 201910/20191030_01.md [《PostgreSQL batch insert - jdbc reWriteBatchedInserts 批量写入 (copy,insert,begin commit,group commit)》](201910/20191030_01.md)
6163
##### 201910/20191027_04.md [《PostgreSQL timescaledb插件 pg_prometheus - PostgreSQL作为prometheus的时序数据库必备插件》](201910/20191027_04.md)
6264
##### 201910/20191027_03.md [《PostgreSQL WAL|redo mirror|multi mirror方法(wal 0丢失) - pg_receivewal+sync replication》](201910/20191027_03.md)

0 commit comments

Comments
 (0)