1.需求背景
目前市场上存在多种类型的分布式数据库,出于兼容性考虑,很多数据库都提供标准的 mysql 的访问接口; 其基本架构都是多节点分区存储数据,有的甚至采用存储和计算节点分离的模式,但无论怎样,出于高可用性以及支撑访问量水平扩展的需要,其前端都需要部署一个负载均衡设施。以 Apache Doris 为例,其配置文档中明确的指出了负载均衡设施的必要性,并给出了市场上常见的 4 层代理软件,如 NGINX,HAPROXY,或特定的 proxysql 的配置样例。
Doris 给出的配置样例,其仅仅采用配置文件,意味着数据库节点扩容时,必须修改配置文件,重启生效,会对业务有一定的影响,更重要的是 NGINX/HAPROXY 的配置,仅仅把后端的数据库节点当作一个 TCP 服务器,无法感知节点的状态,这样在节点状态异常时,会给客户端带来不好的访问体验。
针对此类数据库分布式访问的场景,以 NJet 作为数据库前端的负载均衡,其特有能力,可以大大简化分布式数据库的运维工作,提升使用者的体验。其一是动态成员维护,可以在数据库节点扩/缩容时,通过 API 自动进行成员变更,而正在进行的访问不受影响; 其二是特定的 sql 主动健康检查,可以预先发现问题节点,自动下线,避免使用者的故障感知;其三是可以使用 json 格式的配置文件,便于运维操作。
2.NJet 实现 Doris 负载均衡
以 Doris 为例,在 192.168.1.100 上部署 proxy,代理访问后端三个节点(192.168.1.101,102,103)利用 NJet 作为负载均衡设施,其初始配置和 NGINX 一致,不同的是在 njet.conf 中。
events {worker_connections 1024;}stream { upstream mysqld { hash $remote_addr consistent; server 192.168.1.101:9030 weight=1 max_fails=2 fail_timeout=60s; server 192.168.1.102:9030 weight=1 max_fails=2 fail_timeout=60s; server 192.168.1.103:9030 weight=1 max_fails=2 fail_timeout=60s; } server { # Proxy port listen 6030; proxy_connect_timeout 300s; proxy_timeout 300s; proxy_pass mysqld; }}
复制代码
在 njet 启动后,下面就可以利用 NJet 的特有能力,方便数据库的运维
2.1 NJet 动态成员维护
OpenNJet 可以通过动态 api 接口的方式,动态对 upstream 中的成员进行新增,删除,修改,查询。为支持动态成员维护,NJet.conf 和 njet_ctrl 文件需要做相关的配置变更,如下面配置样例中标黄色部分
helper broker modules/njt_helper_broker_module.so conf/mqtt.conf;helper ctrl modules/njt_helper_ctrl_module.so conf/ctrl.conf;
load_module modules/njt_http_upstream_member_module.so;
stream {
upstream mysqld { zone mysqld 16k; #必须配置共享内存 hash $remote_addr consistent; server 192.168.1.101:9030 weight=1 max_fails=2 fail_timeout=60s; server 192.168.1.102:9030 weight=1 max_fails=2 fail_timeout=60s; server 192.168.1.103:9030 weight=1 max_fails=2 fail_timeout=60s; } server { # Proxy port listen 6030; proxy_connect_timeout 300s; proxy_timeout 300s; proxy_pass mysqld; } }
复制代码
load_module modules/njt_http_sendmsg_module.so;load_module modules/njt_http_upstream_api_module.so; load_module modules/njt_helper_health_check_module.so;
http { server { listen 8081; location /api { dyn_module_api; } }}
复制代码
2.1.1 添加 upstream 成员
假设后续 Doris 做集群扩容,添加了节点 192.168.1.104:9030,可以通过下面 api 进行添加:
api url: POST http://{机器 ip}:8081/api/v1/upstream_api/stream/upstreams/{upstream_name}/servers/
curl -X POST http://127.0.0.1:8081/api/v1/upstream_api/stream/upstreams/mysqld/servers/ -d '{ "server": "192.168.1.104:9030", "weight": 2, "max_conns": 2, "max_fails": 1, "fail_timeout": "5s", "slow_start": "5s", "route": "", "backup": false, "down": false}'
复制代码
添加成员 192.168.1.104:9030 后,OpenNJet 会自动给该成员按顺序分配 id,可以通过该 id 后续对该成员进行查询,删除,修改等操作。
2.1.2 删除 upstream 成员
api url: DELETE http://{机器 ip}:8081/api/v1/upstream_api/stream/upstreams/{upstream_name}/servers/{id}
执行后删除对应 id 的成员。
curl -X DELETE http://127.0.0.1:8081/api/v1/upstream_api/stream/upstreams/mysqld/servers/3
复制代码
2.2 NJet 配置 mysql 健康检查
OpenNJet 默认安装是启用主动健康检查的,可以直接通过控制面提供的 api 接口(默认启用 8081 端口来提供配置服务)进行配置。,api url: http://{机器 ip}:8081/api/v1/hc/smysql/{upstreamname},具体样例如下:
curl -X 'POST' \ 'http://127.0.0.1:8081/api/v1/hc/smysql/mysqld' \ -H 'accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "interval": "5s", "jitter": "1s", "timeout": "5s", "passes": 1, "fails": 1, "sql": { "select": "select 1", "useSsl": true, "user": "root", "password": "123456", "db": "db" }}'
复制代码
配置后就可以定期执行,并在后端服务故障时自动下线(下线后仍然会执行检查,并在检查成功后自动恢复上线)
2.2.1 健康检查配置说明
字段介绍
sql 块配置字段详细介绍
2.3 Json 配置文件支持
目前常见的 nginx,haproxy 等代理设施,其配置文件,非常不方便维护,而 NJet 提供了 json 格式的配置文件,可以利用 jsonpath 快速定位,操作数据,方便运维。如上述的 njet.conf,可以方便的转换为 json 格式,并把 njet.conf 修改为 njet.json,就可以被 njet 使用(njet -c conf/njet.json)
[ { "cmd": "events", "args": [], "block": [ { "cmd": "worker_connections", "args": [ "1024" ] } ] }, { "cmd": "stream", "args": [], "block": [ { "cmd": "upstream", "args": [ "mysqld" ], "block": [ { "cmd": "hash", "args": [ "$remote_addr", "consistent" ] }, { "cmd": "server", "args": [ "192.168.1.101:9030", "weight=1", "max_fails=2", "fail_timeout=60s" ] }, { "cmd": "server", "args": [ "192.168.1.102:9030", "weight=1", "max_fails=2", "fail_timeout=60s" ] }, { "cmd": "server", "args": [ "192.168.1.103:9030", "weight=1", "max_fails=2", "fail_timeout=60s" ] } ] }, { "cmd": "server", "args": [], "block": [ { "cmd": "listen", "args": [ "6030" ] }, { "cmd": "proxy_connect_timeout", "args": [ "300s" ] }, { "cmd": "proxy_timeout", "args": [ "300s" ] }, { "cmd": "proxy_pass", "args": [ "mysqld" ] } ] } ] }]
复制代码
评论