JStorm 源码解析:基础线程模型

在具体开始分析 Storm 集群的启动和运行机制之前,我们先来看一下基础的线程模型,在整个 Storm 的实现中有很多地方用到它,所以将其单独拎出来先分析说明一下,后面看到相应的类就大致知道其内在的运行过程啦。

在 Storm 的实现中,有很多实现了 RunnableCallback 类的子类,这些类实例化之后都被传递给了 AsyncLoopThread 对象,

阅读全文

JStorm 源码解析:拓扑任务的资源分配过程

上一篇我们分析了 topology 构建和提交过程在客户端的逻辑,并最终通过 submitTopology 方法向 Storm 集群的 nimbus 节点提交任务。Nimbus 以 Thrift RPC 服务的方式运行,相应 thrift 接口方法实现位于 ServiceHandler 类中,下面我们从 ServiceHandler#submitTopology 方法切入,分析 nimbus 节点之于客户端提交任务的资源分配过程,该方法包装了 ServiceHandler#submitTopologyWithOpts 方法。

Storm 集群的任务提交主要分为三种类型:新任务提交、热部署,以及灰度发布。ServiceHandler#submitTopologyWithOpts 方法统一处理这三种情况,但是不管哪种提交方式都会首先验证 topology 名称和配置的合法性,然后基于具体提交类型分而治之。

阅读全文

JStorm 源码解析:拓扑的构建和提交过程

我们按照 Storm 规范开发的 spout 和 bolt 需要使用 TopologyBuilder 构建成有向无环图(拓扑),并指定消息的分组方式,然后提交给 Storm 集群执行,本篇我们将分析 topology 的构建和提交过程。前面分析 Storm 的编程接口时曾介绍过 StormTopology 这个 thrift 类,topology 在构建完成之后会封装成一个 StormTopology 对象,并通过 RPC 方法提交给 Storm 集群的 nimbus 节点。

阅读全文

JStorm 源码解析:编程接口

Storm Topology 是由 spout 和 bolt 构建的有向无环图,其中 spout 是图的起始节点,用于发送数据,而 bolt 是图的中间节点和末端节点,用于对数据进行处理。下面我们先用一个简单的 wordcount 示例来回忆一下 Storm 的基本使用,然后对示例中涉及到的 Storm 编程接口从源码层面分析其内在实现。

阅读全文

JStorm 源码解析:整体架构

Apache Storm 是一个基于 ZK 协调的分布式任务实时调度系统,属于流式(实时)计算引擎的一类。在目前的大数据和人工智能背景下流式计算是公司大部分业务的刚性需求,能够实现在百十毫秒内完成对用户行为的计算并执行具体的策略,例如依据用户的行为对其实施风控等。

当下市面上已有很多流式计算引擎产品,但是 Storm 的出现基本上统一了这一领域,不过近几年也出现了一些新的产品可以撼动 Storm 的地位,比如 Apache FlinkApache Spark-Streaming 等。不可否认的是,现阶段还是有很多公司的业务运行在 Storm 集群上,这样一个毫秒级延迟的分布式实时计算引擎还是有很多地方值得我们一起去探寻其设计与实现原理。

阅读全文

深入理解 JUC:ThreadPoolExecutor

线程池是 JUC 中的核心组件之一,在并发编程中我们一般都会引入线程池,一方面考虑是为了减少线程创建、销毁,以及频繁上下文切换所带来的性能开销,另一方面也是为了简化对线程创建、复用,以及消亡等过程的管理。ThreadPoolExecutor 是 JUC 线程池的核心实现,但在实际编码时我们可能很少直接使用该类,而是通过工具类 Executors 来创建线程池实例。

阅读全文

深入理解 JUC:关于线程安全队列的若干总结

前面的几篇文章中,我们对于 JUC 包中提供的线程安全队列的设计与实现进行了全面的分析。JUC 包为 java 开发人员提供了丰富的线程安全队列实现,以满足不同的性能和应用场景需求。然而,不知道你是否与我一样,在学习了各个线程安全队列的实现机制之后,反而有点犯迷糊,这些线程安全队列我们在具体编码时该如何选择呢?于是我打算写一篇总结性的文章,对各个线程安全队列的特性进行总结。

阅读全文

深入理解 JUC:LinkedTransferQueue

上一篇我们分析了 SynchronousQueue 队列的设计与实现。在 SynchronousQueue 内部定义了一个 Transferer 抽象类,并继承该类基于 Dual Queue 和 Dual Stack 数据结构分别实现了 SynchronousQueue 的公平模式和非公平模式。本篇我们将要介绍的 LinkedTransferQueue 队列在设计思路上与 SynchronousQueue 的公平模式十分相似,二者在底层存储结构选型上都引入了 Dual Queue 数据结构。

LinkedTransferQueue 在 jdk 1.7 被引入,是一个基于 Dual Queue 数据结构实现的无界线程安全队列,其作者 Doug Lea 描述 LinkedTransferQueue 从功能上来说是 ConcurrentLinkedQueue、SynchronousQueue(公平模式),以及 LinkedBlockingQueue 的超集,并且更加实用和高效。

阅读全文

深入理解 JUC:SynchronousQueue

本文我们一起来分析一下 SynchronousQueue 的设计与实现。不同于前面介绍的一系列线程安全队列,SynchronousQueue 从真正意义上来说并不能算是一个队列,而将其理解为一个用于线程之间通信的组件更为恰当。SynchronousQueue 没有容量的概念,一个线程在执行完入队列操作之后,必须等待另外一个线程与之匹配完成出队列后方可继续再次入队列,反之亦然。此外,有别于我们通常理解的队列中的结点只承载元素,SynchronousQueue 中的结点还需要附着对应的操作线程,这些线程在对应的结点上等待被匹配(fulfill)。

阅读全文

深入理解 JUC:DelayQueue

延迟队列 DelayQueue 用于存放具有过期属性的元素,被添加到 DelayQueue 中的元素只有在到达过期时间之后才会出队列,常用于延迟任务调度。DelayQueue 本质上是一个无界的阻塞队列,底层依赖于优先级队列 PriorityQueue 作为存储结构,并使用 ReentrantLock 锁保证线程安全。

阅读全文