redisのリバプロとしてhaproxy設定


これは何

redis+sentinelの前段にhaproxyを置いてクライアントがあんまりnode poolを意識しなくてもよさそうな感じにしたい。

方針

redis slaveにgetを負荷分散したりするほど負荷は高くない系に使えるかも。
常にmasterに接続しに行き、slaveは待機系。

設定ファイル

ansible templateの形。

global
  {# chroot内で動いているため/dev/logへアクセスできない。そのためUDP経由でrsyslogにログを渡す。-#}
  log         127.0.0.1 local2
  chroot      {{ HAPROXY_JAIL_DIR }}
  user        {{ HAPROXY_USER }}
  group       {{ HAPROXY_GROUP }}
  daemon
  {# maxconn: redisで設定しているものより大きければよい。このレイヤでは特に制限はかけない。 -#}
  maxconn     10000

{# stats: haproxyのステータスを取れるようにするための設定 -#}
listen stats 
  {# bind: ポート9000への外部からの経路はないが念のためback側からのみ疎通可能としておく。-#}
  bind :9000 interface eth0
  mode http
  stats enable
  stats uri /haproxy_stats 
  {# refresh: stats画面の自動リフレッシュを有効にする -#}
  stats refresh 10    

defaults
  mode                    tcp
  log                     global
  option                  dontlognull
  {# retries: バックエンドサーバへ接続失敗した時の再試行回数-#}
  retries                 3
  {# timeout queue: maxconnを超えたリクエストはキューに入る。そのキューに入った接続を開放するまでの時間。そんなに待たせても意味が無いのであまり大きな値じゃなくてよい。 -#}
  timeout queue           10s
  {# timeout connect: haproxyのbackendへの接続のタイムアウト。近いネットワークにいれば基本的に短い時間で接続できるはず。 -#}
  timeout connect         5s 
  {# timeout check: コネクションが確立したあとの追加のヘルスチェックのタイムアウト。これに時間がかかるということはラグの大きなサーバなので、長い時間待つ必要はない。-#}
  timeout check           5s
  {# timeout client-fin/server-fin: 正しく接続断しなかった場合に切る(こちらからFIN送信したがクライアントがFINを送ってこなかった場合)。FIN_WAIT状態が続くのを防ぐ。 -#}
  timeout client-fin      10s
  timeout server-fin      10s

{# その他入れない設定について。いれるのが推奨のようなので要検討。
* timeout client: 非活性なクライアントからの接続を切る設定。redis設定に合わせて設定しない。 
* timeout server: haproxyから非活性backendへの接続を切る時間。redis設定に合わせて設定しない。 
-#}


frontend  main
  bind *:5000
  default_backend             myredis

backend myredis
  {# balance: どれか1台だけがコネクションを受け付ける設定(first)。id設定があれば一番値が小さいもの。なければリストの1番上から優先される。負荷分散よりも1台のmasterにキャッシュがのることを優先する。 -#} 
  balance    first
  {# 通常時のヘルスチェック間隔はredisのマスター昇格のタイムスケールにあわせて秒単位でよい。haproxyのreload直後などでヘルスチェックをしていない場合には即座に行う(fastinter)。-#}
  {% for srv in HAPROXY_BACKEND_LIST -%}
  server  redis{{ loop.index }} {{ srv }} check inter 1s fall 2 rise 1 fastinter 10ms
  {% endfor %}

  option tcp-check
  tcp-check connect
  tcp-check send info\ replication\r\n
  tcp-check expect string role:master
  tcp-check send QUIT\r\n
  tcp-check expect string +OK

ちなみに rsyslog設定のansible taskはこんな感じ

# haproxyのログ出力のためのrsyslog設定
- name: enable UDP log acceptance for rsyslog for haproxy 
  lineinfile:
    dest: "/etc/rsyslog.conf"
    line: "{{ item }}"
  with_items:
    - "$ModLoad imudp"
    - "$UDPServerRun 514" 
    - "local2.* {{ HAPROXY_LOG_DIR }}/haproxy.log"