今天聊一聊channel的话题,最近几年从事的工作内容都跟消息流和数据通道有关系,

结合最近项目的调优,说说我对channel的认识。

ringbuffer

说到channel,就不能不提disrupter的ringbuffer,最近几年非常热门的开源项目。

ringbuffer强调对象的高度复用,减少GC的次数,有无数据的timeout的回调,方便实现batch逻辑,

多种策略的选择,应对多种业务时效场景。

selector

无论是实时流计算,还是消息通道,都会有一个类似selector的组件,基于某些字段对消息进行分类,

将event投递到不同的channel中,主要是为了解决一定程度的顺序问题,

比如将相同主键的消息顺序输出。flume中的selector就是针对header中的某个key进行mapping,

实现了灵活强大的分流功能。当然使用key也尽量不要出现热点,要不然整体的消费能力就会提早到达瓶颈。

broadcast

broadcast功能在channel中也是非常实用的,比如checkpoint相关的event向下游传递,如果下游有

多个channel,那么就需要一个broadcast功能。在业务中broadcast的应用也非常广,比如上游计算

导致了某种meta信息的变更,就可以通过broadcast的功能通知下游,这种方式比借助外部存储要高效的多,

而且天然不用解决多version的问题。

balance

如果你碰到了一拆N的channel场景,并且对数据的顺序不那么敏感时,肯定希望能最大限度的发挥下游

channel的能力,很多人都在selector上选择roundrobin,或者是基于timestamp取模的方法,如果下游

的消费能力非常强,这种做法是没有问题的。但如果你在下游sink是重IO类型的,这种做法就不会达到

你想要的效果了。你会发现流经常会因为某一条下游的blocking,导致整条链路卡主,你使用了多条通道

,但性能并没有成线性增长。这个问题在我的分发kafka消息至hdfs时就碰到了,一旦HDFS的响应速度下降

整个job的吞吐量大大降低,增加channel并没有解决这个问题,只能增加jvm实例来解决,非常耗资源。

这时,你需要的是类似负载均衡方面的WLC算法的解决方案。首先,你需要让下游的channel暴露出自己

的余量。然后根据余量的情况选择最为空闲的节点,这样你增加的channel才会有意义。当然如果你有

大量的broadcast消息,也会极大的影响你的性能。