MNS client性能提升1000+倍的方法

MNS是阿里云提供的开箱即用的 队列服务,容易上手。当数据量很大,特别是做大批量数据同步时,很多人就会遇到性能瓶颈。

下面就给大家介绍下,提升单机MNS client性能的几种方法。

1. 网络环境

首先考虑的是网络环境。

使用内网endpoint吧,不细说。

2. 多线程的正确姿势

其次,利用多线程提升并发度。

这个大家肯能都会想到,不过事情并没有那么简单。看看官网的多线程示例,我是例子

嗯。。。100个线程,tps怎么也得10+倍了吧。但是没卵用,多线程似乎失效?

so翻了翻源码,当看到MNS底层使用的http reactor模块,DefaultConnectingIOReactor、AbstractMultiworkerIOReactor时,问题逐渐变得明朗起来。

class AbstractMultiworkerIOReactor {
    private final int workerCount;
    private final ThreadFactory threadFactory;
    private final BaseIOReactor[] dispatchers;
    private final Worker[] workers;
    private final Thread[] threads;

原来事情的真相是这样:

MNS client性能提升1000+倍的方法

MNS client 是个singleton。官网的例子用这个singleton搞出了一大堆CloudQueue,想要发挥多线程的魔力。
其实看图可知,不论搞出多少CloudQueue,下面共用的是io 线程池和连接池,而它们才是真正干活的啊。
这种感觉就好比,一家饭店,找了大堆服务员在门口拉客,但后面就一个厨子。
所以,单纯增加CloudQueue没有用,相反,由于CloudQueue放任务到IO池里都是内存操作是很快的,并不要很多线程。

道理明白后,要做的事情就简单了,多线程的正确姿势是:增多worker。

ClientConfiguration clientConf = new ClientConfiguration();
clientConf.setMaxConnections(很多连接);
clientConf.setIoReactorThreadCount(很多线程);
CloudAccount account = new CloudAccount(
    mnsConfig.getAccessId(),
    mnsConfig.getAccessKey(),
    mnsConfig.getEndPoint(),
    clientConf);

3. Batch的Magic Number

再次,批量处理。像Kafka、flume等都是加大batch提升吞吐量的。

MNS client SDK也有类似的API,如

List<Message> batchPopMessage(int batchSize);
void batchDeleteMessage(List<String> receiptHandles);
batchPutMessage(List<Message> messages)

激动地给batch设了个100,Run,服务端异常,50,异常,20异常。说好的batch呢,难道是个假API?

当试到16这个Magic Number时,终于成功了。翻看下官网文档,也没有对magic number说明。

4. 测试小结

简单测试了下,4core8G,单条消息1k byte。
4线程: total send message 16000, cost 5681, tps 2816
8线程: total send message 16000, cost 4603, tps 3475
16线程:total send message 16000, cost 1973, tps 8109

敬告:对于那些一不小心就超过上面测试数据的同学,欢迎加入橙鹰数据(据说是杭州一个很牛x很低调的大数据公司)。

BTW, 优化的意义。下面是阿里云另一款高性能MQ产品,
MNS client性能提升1000+倍的方法

5. 坑货

5.1巨坑之PollingWaitSeconds

控制台创建MNS队列时,PollingWaitSeconds默认值是0。
这个值必须要设置
这个值必须要设置
这个值必须要设置
因为MNS会按请求次数收费。依稀记得那个晚上,几w块就灰飞烟灭了。推荐设10~30。

5.2 小坑之VisibilityTimeout

使用过Kafka,Metaq的同学知道,消息消费掉后,会commit offset告诉broker。
不同的地方是,在使用MNS时,为了不丢数据,通常是消费成功后,手动删除消息。
如果消息被消费后,超过了VisibilityTimeout,再去删除这个消息,就会遇到喜闻乐见的Not Found错误。

5.3 小坑之重建队列

常会有这种情景,给队列发送了很多消息,想把消息全部删除后重新灌批数据,但是由于没有一键清除的方法,用户会删除该队列,然后重建个同名的队列。
这样产生的问题是,原来的MNS client找不到该队列了,必须要重启。

上一篇:Mac环境pip install


下一篇:Centos 7 中文乱码