如何为副本集及/或分片模式的MongoDb配置反向代理?
核心前提说明
MongoDB副本集仅主节点支持写操作,读请求可按策略分发到从节点,普通无差别负载均衡会将写请求打到从节点导致报错,因此代理的核心是要么配合MongoDB驱动的副本集感知能力做透明转发,要么代理本身支持MongoDB协议解析,可识别请求类型和节点角色。
具体配置方案
方案1:Nginx 配置(TCP层透明转发,适配副本集感知驱动)
如果应用端的MongoDB驱动已开启副本集模式(连接串指定replicaSet参数),开源版Nginx只需做TCP层端口转发即可,无需自主判断节点角色,驱动会自动通过代理和节点通信,完成主从角色识别和请求路由。
注意:使用该配置需要Nginx编译时开启
--with-stream模块。
配置示例如下:
stream { # 定义MongoDB副本集所有节点上游 upstream mongodb_replica { server 192.168.1.10:27017 max_fails=2 fail_timeout=30s; server 192.168.1.11:27017 max_fails=2 fail_timeout=30s; server 192.168.1.12:27017 max_fails=2 fail_timeout=30s; # 开启TCP层长连接复用 keepalive 300; keepalive_timeout 60s; keepalive_requests 1000; } server { listen 27017; proxy_pass mongodb_replica; proxy_timeout 300s; proxy_connect_timeout 10s; } }
配置完成后应用的连接串写法参考:mongodb://<代理IP>:27017/?replicaSet=<你的副本集名称>&directConnection=false。
如果需要Nginx自主实现读写分离,需要使用Nginx Plus商业版,其内置$mongodb_command变量可识别MongoDB请求类型,开源版无该能力。
方案2:Envoy 配置(原生支持MongoDB协议解析,可自主实现读写路由)
Envoy原生支持MongoDB协议解析,可自动识别读写请求、感知副本集节点角色变化,无需依赖应用驱动的副本集感知能力。
核心配置片段示例如下:
# 监听器配置部分 listeners: - name: mongodb_listener address: socket_address: address: 0.0.0.0 port_value: 27017 filter_chains: - filters: - name: envoy.filters.network.mongo_proxy typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.mongo_proxy.v3.MongoProxy stat_prefix: mongodb access_log: name: envoy.access_loggers.stdout - name: envoy.filters.network.tcp_proxy typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy stat_prefix: tcp_mongodb cluster: mongodb_replica_cluster # 上游集群配置 clusters: - name: mongodb_replica_cluster connect_timeout: 10s type: STRICT_DNS lb_policy: ROUND_ROBIN load_assignment: cluster_name: mongodb_replica_cluster endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 192.168.1.10 port_value: 27017 - endpoint: address: socket_address: address: 192.168.1.11 port_value: 27017 - endpoint: address: socket_address: address: 192.168.1.12 port_value: 27017
如果要实现读写分离,只需在Mongo代理过滤器中补充路由规则,将insert、update、delete等写请求路由到主节点上游集群,find、count等读请求路由到从节点上游集群做负载均衡即可。
分片集群适配说明
上述配置方案完全适用于MongoDB分片集群,只需将上游节点替换为分片集群的mongos路由节点即可:
- 分片集群所有请求都由无状态的mongos节点路由,代理只需对mongos节点做普通TCP负载均衡和健康检查即可
- 分片路由逻辑完全由mongos和配置节点处理,无需代理额外适配。
内容的提问来源于stack exchange,提问作者Vinay Mundada

