问题
I am trying to setup a load balancing for postgres database. We have a postgres master and slave. I configured HA proxy to achieve load balancing. Simple load balancing is working fine.
This database is used for bitbucket.
When bitbucket is writing data to database over the loadbalancer it is fine if it is hitting master, but problem encounters when it is hitting slave(which is in read mode) as it cant update the database.
How can i say HAproxy to route requests to postgres master.
Select * from pg_stat_replication to be executed on master and slave and based on the output it has to route the request to the streaming master, is there any way that we achieve it using HAproxy ?
Thanks, Karthik
回答1:
This can be done using a custom health check, which only succeeds if the server is the master. All the other slave servers will be marked down.
backend pgsql
mode tcp
option tcp-check
tcp-check send-binary 0000002c # length
tcp-check send-binary 00030000 # version
tcp-check send-binary 75736572 # 'user'.bytes.map { |c| c.to_s(16) }
tcp-check send-binary 00 # string terminator
tcp-check send-binary 6170706c69636174696f6e # 'application'
tcp-check send-binary 00 # string terminator
tcp-check send-binary 6461746162617365 # 'database'
tcp-check send-binary 00 # string terminator
tcp-check send-binary 706f737467726573 # 'postgres'
tcp-check send-binary 00 # string terminator
tcp-check send-binary 00 # name/value terminator
tcp-check expect string R
tcp-check send-binary 51 # 'Q'
tcp-check send-binary 00000020 # length
tcp-check send-binary 73656c6563742070675f69735f696e5f7265636f7665727928293b # 'select pg_is_in_recovery();'
tcp-check send-binary 00 # string terminator
tcp-check send-binary 58 # 'X'
tcp-check send-binary 00000004 # length
tcp-check expect string f
tcp-check expect string Z
server pg1 1.2.3.4:5432 check
server pg2 5.6.7.8:5432 check
The ''tcp-check'' lines are sending and receiving binary packets using the Postgres client protocol, which is defined in their documentation.
In addition, you can also have a secondary 'readonly' backend that is only used if the primary fails. Here's the extra frontend/backend config for that.
frontend pgsql
mode tcp
bind *:5432
acl readonly.pgsql nbsrv(pgsql) eq 0
use_backend readonly.pgsql if readonly.pgsql
acl pgsql nbsrv(pgsql) gt 0
use_backend pgsql if pgsql
<...primary backend...>
backend readonly.pgsql
mode tcp
option tcp-check
tcp-check send-binary 0000002c # length
tcp-check send-binary 00030000 # version
tcp-check send-binary 75736572 # 'user'.bytes.map { |c| c.to_s(16) }
tcp-check send-binary 00 # string terminator
tcp-check send-binary 6170706c69636174696f6e # 'application'
tcp-check send-binary 00 # string terminator
tcp-check send-binary 6461746162617365 # 'database'
tcp-check send-binary 00 # string terminator
tcp-check send-binary 706f737467726573 # 'postgres'
tcp-check send-binary 00 # string terminator
tcp-check send-binary 00 # name/value terminator
tcp-check expect string R
tcp-check send-binary 58 # 'X'
tcp-check send-binary 00000004 # length
server pg1 1.2.3.4:5432 check
server pg2 5.6.7.8:5432 check
It's debatable if marking slaves as 'down' is a good use of HAProxy health checks. The above does work, but there other ways of doing this without HAProxy.
来源:https://stackoverflow.com/questions/41571150/how-can-we-achieve-route-requests-to-postgres-master-using-haproxy