使用sshtunnel实现python公网连接阿里云mongo服务器
背景:
公司使用阿里云的云数据库MongoDB。基于安全原因考虑,阿里云MongoDB云数据库目前只支持从阿里云ECS上访问,无法通过公网直接访问,不方便用户在本地开发环境里直接进行测试。
阿里云官方推荐使用rinetd搭建跳板系统,实现公网访问云mongo。使用过程中,发现,python程序在使用过程中如果没有正确释放连接,即使python程序退出后,该mongo连接仍然被rinetd占用。曾出现调用该地址的python程序全部退出后,rinetd仍占用100多个连接,导致云mongo可用连接数不足。此时,需要重启rinetd方可释放被占用的连接。
最终使用本机ssh连接阿里云ECS,再从该主机使用私网连接到mongo的方法,实现云mongo公网访问。这种方法可以使开发环境中的robomongo连接到mongo。
python连接云mongo:
1 依赖
python -m pip install sshtunnel==0.1.2
2 demo
# -*- coding:utf-8 -*- from __future__ import unicode_literals import pymongo from sshtunnel import SSHTunnelForwarder class AliyunMongoDebug(object): def __init__(self): self._record = {} def get_aliyun_mongo_client(self, only_read=True): # 跳板机参数 ecs_host = "<ecs ip>" ecs_user = "<ecs user>" ecs_password = "<ecs password>" # 云mongo 配置 aliyun_mongo_master_host = "<mongo 副本集 主服务器>" aliyun_mongo_slave_host = "<mongo 副本集 副本>" aliyun_mongo_database = "<mongo 数据库>" aliyun_mongo_account = "<mongo 账号>" aliyun_mongo_password = "<mongo 密码>" host = aliyun_mongo_slave_host if only_read else aliyun_mongo_master_host server = SSHTunnelForwarder( (ecs_host, 22), ssh_password=ecs_password, ssh_username=ecs_user, remote_bind_address=(host, 3717)) server.start() client = pymongo.MongoClient('127.0.0.1', server.local_bind_port) mongo_database = client[aliyun_mongo_database] mongo_database.authenticate(aliyun_mongo_account, aliyun_mongo_password) self._record[client] = server return client def return_aliyun_mongo_client(self, client): if client in self._record: server = self._record.pop(client) else: server = None client.close() if server: server.close() if __name__ == '__main__': mongo_debug_manager = AliyunMongoDebug() mongo_client = None try: mongo_client = mongo_debug_manager.get_aliyun_mongo_client(only_read=False) mongo_client["Test"]["ssh_test"].insert({"msg": "Hello World!"}) finally: if mongo_client: mongo_debug_manager.return_aliyun_mongo_client(mongo_client)