说明
虽然不想在完成量化系统的构建前再去分叉搞别的东西,但是在批量计算指标时需要频繁的使用MongoAgent,而这个服务只能做成单线程异步的,所以计算60万次指标需要2~3天时间。
考虑到之后可能会有重刷的情况,所以我想还是给MongoAgent"扩容"。
内容
1 分析
部件是稳定的:MongoAgent从上一版本推送之后,可能有大半年或者一整年都没有任何的更新,所以我认为做了不至于会返工。
手动分配端口:目前都在采用2字头的端口,所以约定3字头给到类似nginx的服务。
手动启动多个服务:从目前的需求看,提速10倍比较容易满足需求(2~3天 ⇒ 0.3天 = 2.4小时)。另外我服务器的计算核可以认为有10+个,所以正好。
需要1个nginx容器,以及10个mongoagent容器。比较麻烦的是,需要一个个手动启动容器。
未来(等量化的主体完成了)在继续完善架构时,应该优先把容器管理部分先做掉,这样启动分身什么的比较容易。架构还有一部分是web开发环境,以后再说。
2 MongoAgent
简单看了一下MongoAgent的连接管理,MongoAgent当时设计还是依赖pickle文件工作的。
- 1 每次需要连接新数据库时需要建立connection_hash
- 2 接口根据连接的信息计算hash,然后看看有没有在数据库中,如果有那么就跳过,否则就存库(24003),也存pickle,然后保存在本地
- 3 再之后,每次提交操作时都伴随着connection_hash即可。
这些设计当然不那么完善,当初甚至没有考虑使用Redis,不过问题不大。
最简单的方法,就是让所有的分身都挂载一个文件夹,文件夹下面由一个程序获取某些主机的所有connection_hash。
还有一个在线的笨办法,就是将数据库的配置读出来,然后向服务不断的发起建立连接的试探,这样自动化一些。
在指定了端口后,可以精确的向每个mongo_agent发起连接创建。(虽然麻烦了点,但是比较可靠,先这样吧)
因为MA是无状态的服务,所以可以直接在原项目文件下启动,改个端口号就行。
3 Nginx测试
容器方面已经有了,所以主要看配置。
这个是大致的结构,我就不细看了,全局块和events暂时不管。
主要是在http下进行配置
新的Nginx分配34011端口,测试时可以使用24011和24021两个服务。
先启动一个nginx试一下,镜像随便写一个都行,我只是固定了一个版本放在自己仓库
docker run -it --rm -p 34011:80 【IMAGE nginx:v1】
内网中发起测试(第二次就不下载index.html了)
nginx启动成功
现在迅速挂载对应的目录和配置,进行负载均衡mongoagent.conf
(似乎也可以不配置http模块,直接配置server)
配置如下
events {
#设置工作模式为epoll,除此之外还有select,poll,kqueue,rtsig和/dev/poll模式
use epoll;
#定义每个进程的最大连接数,受系统进程的最大打开文件数量限制
worker_connections 1024;
}
http{
upstream multi_ma {
# fair;
server 172.17.0.1:24021 ;
server 172.17.0.1:24011 ;
}
server {
listen 34011;
location / {
proxy_pass http://multi_ma;
}
}
}
坑1:挂载nginx的配置文件(会报一些错误[emerg] 1#1: "events" directive is not allowed here in /etc/nginx/conf.d/mongoagent.conf
,我一开始没明白)
答案在这,挂载的配置文件不对
坑2:fair要进行第三方安装才能用。所以我先不使用fair(以后有机会再看吧),应该是可以使用了。
之后启动多个MA,然后将端口固定就行。计划使用35000~35009这十个端口服务。
4 启动
先按照端口35000~35009启动10个MA,然后修改nginx,配置改为在这10个MA上进行负载均衡。
因为是在当前的MA(24011)上直接挂载启动的,我发现24011生成的连接字典也被同步挂载过来了。
从一般性使用的角度上,还是要写一个程序来全量刷新连接字典。
拿到库里所有的连接记录
ng_ma = 'http://172.17.0.1:34011/'
query_dict = {'connection_hash':None,'filter_dict':{'is_enable':1},'tier1':'MongoAgent','tier2':'mConnections','limits':1000}
recs = req.post(ng_ma + 'query_recs_v2/',json=query_dict).json()['data']
剔除和数据库连接无关的字段
db_conf_list = []
for rec in recs :
tem_dict = {}
for k in rec.keys():
if not k in ['connection_hash','create_time','is_enable']:
tem_dict[k] = rec[k]
db_conf_list.append(tem_dict)
做一个嵌套循环,逐个刷新MA的Shard
for i in range(35000,35010):
tem_ma = 'http://172.17.0.1:%s/' % i
for db_conf in db_conf_list:
resp = req.post(tem_ma + 'add_a_connection/',json ={**db_conf}).json()
print(resp)
5 总结
这样就好了,比想象中的简单一些。
未来可以通过服务(docker manager)来实现类似的批量启动分身的方法(再通过前端集成管理),这样就比较完美了。