04 mongo在三节点如何通过LB对数据实现读写
mongo 集群模式下通过LB 地址访问集群异常¶
背景¶
问题描述
在集群内部搭建了一个mongo三节点集群,集群详细信息如下rs.status()
rs0 [direct: secondary] admin> rs.status()
{
set: 'rs0',
date: ISODate('2025-09-16T02:59:48.258Z'),
myState: 2,
term: Long('3'),
syncSourceHost: '192.168.101.100:27017',
syncSourceId: 2,
heartbeatIntervalMillis: Long('2000'),
majorityVoteCount: 2,
writeMajorityCount: 2,
votingMembersCount: 3,
writableVotingMembersCount: 3,
optimes: {
lastCommittedOpTime: { ts: Timestamp({ t: 1757991584, i: 1 }), t: Long('3') },
lastCommittedWallTime: ISODate('2025-09-16T02:59:44.482Z'),
readConcernMajorityOpTime: { ts: Timestamp({ t: 1757991584, i: 1 }), t: Long('3') },
appliedOpTime: { ts: Timestamp({ t: 1757991584, i: 1 }), t: Long('3') },
durableOpTime: { ts: Timestamp({ t: 1757991584, i: 1 }), t: Long('3') },
lastAppliedWallTime: ISODate('2025-09-16T02:59:44.482Z'),
lastDurableWallTime: ISODate('2025-09-16T02:59:44.482Z')
},
lastStableRecoveryTimestamp: Timestamp({ t: 1757991564, i: 1 }),
members: [
{
_id: 0,
name: '192.168.101.101:27017',
health: 1,
state: 2,
stateStr: 'SECONDARY',
uptime: 2159024,
optime: { ts: Timestamp({ t: 1757991584, i: 1 }), t: Long('3') },
optimeDate: ISODate('2025-09-16T02:59:44.000Z'),
lastAppliedWallTime: ISODate('2025-09-16T02:59:44.482Z'),
lastDurableWallTime: ISODate('2025-09-16T02:59:44.482Z'),
syncSourceHost: '192.168.101.100:27017',
syncSourceId: 2,
infoMessage: '',
configVersion: 1,
configTerm: 3,
self: true,
lastHeartbeatMessage: ''
},
{
_id: 1,
name: '192.168.101.102:27017',
health: 1,
state: 1,
stateStr: 'PRIMARY',
uptime: 2159021,
optime: { ts: Timestamp({ t: 1757991584, i: 1 }), t: Long('3') },
optimeDurable: { ts: Timestamp({ t: 1757991584, i: 1 }), t: Long('3') },
optimeDate: ISODate('2025-09-16T02:59:44.000Z'),
optimeDurableDate: ISODate('2025-09-16T02:59:44.000Z'),
lastAppliedWallTime: ISODate('2025-09-16T02:59:44.482Z'),
lastDurableWallTime: ISODate('2025-09-16T02:59:44.482Z'),
lastHeartbeat: ISODate('2025-09-16T02:59:48.152Z'),
lastHeartbeatRecv: ISODate('2025-09-16T02:59:48.152Z'),
pingMs: Long('0'),
lastHeartbeatMessage: '',
syncSourceHost: '',
syncSourceId: -1,
infoMessage: '',
electionTime: Timestamp({ t: 1754419909, i: 1 }),
electionDate: ISODate('2025-08-05T18:51:49.000Z'),
configVersion: 1,
configTerm: 3
},
{
_id: 2,
name: '192.168.101.100:27017',
health: 1,
state: 2,
stateStr: 'SECONDARY',
uptime: 2159021,
optime: { ts: Timestamp({ t: 1757991584, i: 1 }), t: Long('3') },
optimeDurable: { ts: Timestamp({ t: 1757991584, i: 1 }), t: Long('3') },
optimeDate: ISODate('2025-09-16T02:59:44.000Z'),
optimeDurableDate: ISODate('2025-09-16T02:59:44.000Z'),
lastAppliedWallTime: ISODate('2025-09-16T02:59:44.482Z'),
lastDurableWallTime: ISODate('2025-09-16T02:59:44.482Z'),
lastHeartbeat: ISODate('2025-09-16T02:59:48.154Z'),
lastHeartbeatRecv: ISODate('2025-09-16T02:59:48.153Z'),
pingMs: Long('0'),
lastHeartbeatMessage: '',
syncSourceHost: '192.168.101.102:27017',
syncSourceId: 1,
infoMessage: '',
configVersion: 1,
configTerm: 3
}
],
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1757991584, i: 1 }),
signature: {
hash: Binary.createFromBase64('tJ3y+ypCIZwN5wm0dYBJtcNw3/w=', 0),
keyId: Long('7514145735047118854')
}
},
operationTime: Timestamp({ t: 1757991584, i: 1 })
}
在外部需要使用python 的pymongo 来连接该集群
处理过程¶
1、 建立TCP 四层代理,这里使用云厂商提供的TCP 层的LB 进行实现,也可以使用nginx 来实现四层代理;例如:
公网IP地址为: real_public_ip
stream {
upstream mongodb_cluster {
server 192.168.101.100:27017;
server 192.168.101.101:27017;
server 192.168.101.102:27017;
}
server {
listen 27017;
proxy_pass mongodb_cluster;
proxy_timeout 60s;
proxy_responses 1; # 避免代理缓冲导致元数据延迟
}
}
2、使用python3 来进行连接验证
from pymongo import MongoClient
client = MongoClient("mongodb://username:password@real_public_ip:27017/test?replicaSet=rs0&authSource=test")
报错如下,在使用过程中还是使用了内网地址进行连接,需要进一步排查
>>> client.server_info()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.9/site-packages/pymongo/synchronous/mongo_client.py", line 2311, in server_info
self.admin.command(
File "/usr/local/lib/python3.9/site-packages/pymongo/_csot.py", line 125, in csot_wrapper
return func(self, *args, **kwargs)
File "/usr/local/lib/python3.9/site-packages/pymongo/synchronous/database.py", line 931, in command
with self._client._conn_for_reads(read_preference, session, operation=command_name) as (
File "/usr/local/lib/python3.9/site-packages/pymongo/synchronous/mongo_client.py", line 1885, in _conn_for_reads
server = self._select_server(read_preference, session, operation)
File "/usr/local/lib/python3.9/site-packages/pymongo/synchronous/mongo_client.py", line 1833, in _select_server
server = topology.select_server(
File "/usr/local/lib/python3.9/site-packages/pymongo/synchronous/topology.py", line 409, in select_server
server = self._select_server(
File "/usr/local/lib/python3.9/site-packages/pymongo/synchronous/topology.py", line 387, in _select_server
servers = self.select_servers(
File "/usr/local/lib/python3.9/site-packages/pymongo/synchronous/topology.py", line 294, in select_servers
server_descriptions = self._select_servers_loop(
File "/usr/local/lib/python3.9/site-packages/pymongo/synchronous/topology.py", line 344, in _select_servers_loop
raise ServerSelectionTimeoutError(
pymongo.errors.ServerSelectionTimeoutError: 192.168.101.100:27017: timed out (configured timeouts: socketTimeoutMS: 20000.0ms, connectTimeoutMS: 20000.0ms),192.168.101.102:27017: [Errno 111] Connection refused (configured timeouts: socketTimeoutMS: 20000.0ms, connectTimeoutMS: 20000.0ms),192.168.101.101:27017: timed out (configured timeouts: socketTimeoutMS: 20000.0ms, connectTimeoutMS: 20000.0ms), Timeout: 30s, Topology Description: <TopologyDescription id: 68c8dadce3986fbb2476422f, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('192.168.101.100', 27017) server_type: Unknown, rtt: None, error=NetworkTimeout('192.168.101.100:27017: timed out (configured timeouts: socketTimeoutMS: 20000.0ms, connectTimeoutMS: 20000.0ms)')>, <ServerDescription ('192.168.101.102', 27017) server_type: Unknown, rtt: None, error=AutoReconnect('192.168.101.102:27017: [Errno 111] Connection refused (configured timeouts: socketTimeoutMS: 20000.0ms, connectTimeoutMS: 20000.0ms)')>, <ServerDescription ('192.168.101.101', 27017) server_type: Unknown, rtt: None, error=NetworkTimeout('192.168.101.101:27017: timed out (configured timeouts: socketTimeoutMS: 20000.0ms, connectTimeoutMS: 20000.0ms)')>]>
3、通过deepseek 得知使用强制直接连接,可忽略mongo 的rs0 配置host 参数
优化后的连接语句如下:
from pymongo import MongoClient
client = MongoClient("mongodb://username:password@real_public_ip:27017/test?replicaSet=rs0&authSource=test",directConnection="true",retryWrites=True)
验证新语句能否达到想要的效果,显示连接成功
> client.server_info()
{'version': '7.0.21', 'gitVersion': 'a47b62aff2bae1914085c3ef1d90fc099acf000c', 'modules': [], 'allocator': 'tcmalloc', 'javascriptEngine': 'mozjs', 'sysInfo': 'deprecated', 'versionArray': [7, 0, 21, 0], 'openssl': {'running': 'OpenSSL 3.0.2 15 Mar 2022', 'compiled': 'OpenSSL 3.0.2 15 Mar 2022'}, 'buildEnvironment': {'distmod': 'ubuntu2204', 'distarch': 'x86_64', 'cc': '/opt/mongodbtoolchain/v4/bin/gcc: gcc (GCC) 11.3.0', 'ccflags': '-Werror -include mongo/platform/basic.h -ffp-contract=off -fasynchronous-unwind-tables -g2 -Wall -Wsign-compare -Wno-unknown-pragmas -Winvalid-pch -gdwarf-5 -fno-omit-frame-pointer -fno-strict-aliasing -O2 -march=sandybridge -mtune=generic -mprefer-vector-width=128 -Wno-unused-local-typedefs -Wno-unused-function -Wno-deprecated-declarations -Wno-unused-const-variable -Wno-unused-but-set-variable -Wno-missing-braces -fstack-protector-strong -gdwarf64 -Wa,--nocompress-debug-sections -fno-builtin-memcmp -Wimplicit-fallthrough=5', 'cxx': '/opt/mongodbtoolchain/v4/bin/g++: g++ (GCC) 11.3.0', 'cxxflags': '-Woverloaded-virtual -Wpessimizing-move -Wno-maybe-uninitialized -fsized-deallocation -Wno-deprecated -std=c++20', 'linkflags': '-Wl,--fatal-warnings -B/opt/mongodbtoolchain/v4/bin -gdwarf-5 -pthread -Wl,-z,now -fuse-ld=lld -fstack-protector-strong -gdwarf64 -Wl,--build-id -Wl,--hash-style=gnu -Wl,-z,noexecstack -Wl,--warn-execstack -Wl,-z,relro -Wl,--compress-debug-sections=none -Wl,-z,origin -Wl,--enable-new-dtags', 'target_arch': 'x86_64', 'target_os': 'linux', 'cppdefines': 'SAFEINT_USE_INTRINSICS 0 PCRE2_STATIC NDEBUG _XOPEN_SOURCE 700 _GNU_SOURCE _FORTIFY_SOURCE 2 ABSL_FORCE_ALIGNED_ACCESS BOOST_ENABLE_ASSERT_DEBUG_HANDLER BOOST_FILESYSTEM_NO_CXX20_ATOMIC_REF BOOST_LOG_NO_SHORTHAND_NAMES BOOST_LOG_USE_NATIVE_SYSLOG BOOST_LOG_WITHOUT_THREAD_ATTR BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS BOOST_SYSTEM_NO_DEPRECATED BOOST_THREAD_USES_DATETIME BOOST_THREAD_VERSION 5'}, 'bits': 64, 'debug': False, 'maxBsonObjectSize': 16777216, 'storageEngines': ['devnull', 'wiredTiger'], 'ok': 1.0, '$clusterTime': {'clusterTime': Timestamp(1757992924, 1), 'signature': {'hash': b'\xaeB\xebL\xb3\xee~R\xf2\xf8\x97\xa3`\x7f\x0fn\x066\xc5\xf2', 'keyId': 7514145735047118854}}, 'operationTime': Timestamp(1757992924, 1)}