zoukankan      html  css  js  c++  java
  • Storm通信机制(了解)

    Worker间的通信:经常需要通过网络跨节点进行,Storm使用ZeroMQNetty(0.9以后默认使用)作为进程间通信的消息框架。

    Worker进程内部通信不同workerthread通信使用LMAX Disruptor来完成。

    不同topologey之间的通信:Storm不负责,需要自己想办法实现,例如使用kafka等;

    1、worker进程间的通信

    worker进程间消息传递机制,消息的接收和处理的大概流程见下图:

    • 对于worker进程来说,为了管理流入和传出的消息,每个worker进程有一个独立的接收线程(对配置的TCP端口supervisor.slots.ports进行监听);

    对应Worker接收线程,每个worker存在一个独立的发送线程,它负责从workertransfer-queue中读取消息,并通过网络发送给其他worker

    • 每个executor有自己的incoming-queueoutgoing-queue。

    Worker接收线程将收到的消息通过task编号传递给对应的executor(一个或多个)incoming-queues;

    每个executor有单独的线程分别来处理spout/bolt的业务逻辑,业务逻辑输出的中间数据会存放在outgoing-queue中,当executoroutgoing-queue中的tuple达到一定的阀值,executor的发送线程将批量获取outgoing-queue中的tuple,并发送到transfer-queue中。

    • 每个worker进程控制一个或多个executor线程,用户可在代码中进行配置。其实就是我们在代码中设置的并发度个数。

    2、worker进程间通信分析

    1、 Worker接受线程通过网络接受数据,并根据Tuple中包含的taskId,匹配到对应的executor;然后根据executor找到对应的incoming-queue,将数据存发送到incoming-queue队列中。

    2、 业务逻辑执行现成消费incoming-queue的数据,通过调用Boltexecute(xxxx)方法,将Tuple作为参数传输给用户自定义的方法

    3、 业务逻辑执行完毕之后,将计算的中间数据发送给outgoing-queue队列,当outgoing-queue中的tuple达到一定的阀值,executor的发送线程将批量获取outgoing-queue中的tuple,并发送到Workertransfer-queue

    4、 Worker发送线程消费transfer-queue中数据,计算Tuple的目的地,连接不同的node+port将数据通过网络传输的方式传送给另一个的Worker

    5、 另一个worker执行以上步骤1的操作。

     

    3、worker内部通信技术(Disruptor

    ①来历:Disruptor在一个线程里每秒能处理600万订单!

    ②Disruptor是什么?

    1、 简单理解:Disruptor是一个QueueDisruptor是实现了“队列”的功能,而且是一个有界队列。而队列的应用场景自然就是“生产者-消费者”模型

    2、 JDKQueue有很多实现类,包括不限于ArrayBlockingQueueLinkBlockingQueue,这两个底层的数据结构分别是数组和链表。数组查询快,链表增删快,能够适应大多数应用场景。

    3、 但是ArrayBlockingQueueLinkBlockingQueue都是线程安全的。涉及到线程安全,就会有synchronizedlock等关键字,这就意味着CPU会打架。

    4、 Disruptor一种线程之间信息无锁的交换方式(使用CASCompare And Swap/Set)操作)。

    ③Disruptor主要特点:

    1、 没有竞争=没有锁=非常快。

    2、 所有访问者都记录自己的序号的实现方式,允许多个生产者与多个消费者共享相同的数据结构。

    3、 在每个对象中都能跟踪序列号(ring bufferclaim Strategy,生产者和消费者),加上神奇的cache line padding,就意味着没有为伪共享和非预期的竞争。

    ④Disruptor核心技术点:

    Disruptor可以看成一个事件监听或消息机制,在队列中一边生产者放入消息,另外一边消费者并行取出处理.

    底层是单个数据结构:一个ring buffer

    每个生产者和消费者都有一个次序计算器,以显示当前缓冲工作方式。

    每个生产者消费者能够操作自己的次序计数器的能够读取对方的计数器,生产者能够读取消费者的计算器确保其在没有锁的情况下是可写的。

    核心组件

    Ring Buffer 环形的缓冲区,负责对通过 Disruptor 进行交换的数据(事件)进行存储和更新。

    Sequence 通过顺序递增的序号来编号管理通过其进行交换的数据(事件),对数据(事件)的处理过程总是沿着序号逐个递增处理。

    RingBuffer底层是个数组,次序计算器是一个64bit long 整数型,平滑增长

    环形缓冲区中没有用到锁,而是用序号管理器Sequence来管理的,每次生产者要生产数据和消费者要消费数据都要请求序号管理器,只有当有空的时候,生产者才能生产,不能覆盖消费者没有消费的区域,只能等消费者消费完,才能去生产。消费者也只能等生产者生产了数据以后,才能去消费。更详细的解释可以去并发编程网学习。

  • 相关阅读:
    多级别过滤器
    MongoDBAppender
    org.slf4j.impl.SimpleLoggerFactory cannot be cast to ch.qos.logback.classic.LoggerContext
    简单引入logback
    Logback configuration
    PatternLayoutEncoder 输出格式
    ConsoleAppender
    FileAppender
    Linux学习笔记
    GitLab CI/CD 学习记录
  • 原文地址:https://www.cnblogs.com/ahu-lichang/p/6901530.html
Copyright © 2011-2022 走看看