暂无个人介绍
最近在实现一个基于RabbitMQ的消息总线。因为它提供了Client(客户端),这里就牵扯到凡是技术组件的client都无法回避的并发问题。本文借实现消息总线的client谈谈在实现过程中的想法以及最终的处理方式,当然这些都不仅仅适用于消息总线的client,其他通用组件的client也同样适用。
上次我谈了最近在写的一个基于RabbitMQ的消息总线的客户端在面对并发问题时的一些思考以及最终的实现方案。那是一种简单并且不容易产生并发问题的方案,如果你看过那篇文章,我曾在最终的实现方案之后给出了其利弊分析。
我曾在之前的一篇文章中对比过消息队列跟消息总线。它们其中的一个不同点就是:消息总线更关注通信安全,消息总线可以管控通信双方,对通信的管控是建立在授权的基础上。因此授权模型的设计是消息总线必须考虑的问题。
本文主要探讨了消息总线支持Thrift RPC的实现过程。鉴于RabbitMQ官方的Java Client提供了基于RabbitMQ的JSON-RPC,消息总线也顺道提供了JSON-RPC的API。
最近一段时间,我在琢磨消息总线除了能进行受管控的消息通信之外,还有哪些可以扩展的方向。这篇文章我们来探讨一下面向消息的数据集成是否可以作为一种尝试方向。 相关技术简介 XML 谈到XML我们的第一映像就是用它来做各种配置,当然如果你是Javaer,那么可能你印象最深的就是Spring的bena配置了。
近段时间,暂缓了消息总线feature的开发,花了部分时间对原先的pubsub机制进行了针对性的优化与重构。这里记录一下优化的过程以及相比原来的设计有哪些改观。 PubSub在消息总线内部的作用 PubSub在消息总线内部主要用于对所有在线客户端进行实时管控的作用。
问题简述 消息总线目前为Java编程语言提供了SDK,同时针对其他语言提供了一个称之为httpBridge的http代理。这基本可以满足大部分主流编程语言对消息总线的使用需求,但这也仅仅是对技术层面上的需求的满足。
Guava是Google开源的一个Java基础类库,它在Google内部被广泛使用。Guava提供了很多功能模块比如:集合、并发库、缓存等,EventBus是其中的一个module,本篇结合EventBus源码来谈谈它的设计与实现。
最近接手维护一个日志系统,它用于对应用服务器上的日志进行收集然后提供实时分析、处理并最后将日志存储到目标存储引擎。针对这三个环节,业界已经有一套组件来应对各自的需求需求,它们是flume+kafka+hdfs/hbase。
继续谈论最近接手的日志系统,上篇关于日志收集相关的内容,这篇我们谈谈日志存储相关的话题。 简介 我们首先来总结一下日志这种数据的业务特点:它几乎没有更新的需求,一个组件或一个系统通常有一个固定的日志格式,但就多个组件或系统而言它会存在各种五花八门的自定义的tag,这些tag建立的目的通常是为了后期查询/排查线上问题的需要,因此日志的检索字段也灵活多变。
继续闲聊日志系统,在之前的博文里已提到我们在日志收集上的选择是flume-ng。应用程序将日志打到各自的日志文件或指定的文件夹(日志文件按天滚动),然后利用flume的agent去日志文件中收集。 Deserializer简介 flume将一条日志抽象成一个event。
最近花了不少时间对消息总线进行了重构。重构的重点是在消息总线中加入了Guava的EventBus,并应用于以下两个场景: (1)改进广播通知 (2)业务逻辑串联,用事件驱动替代责任链模式 EventBus简介 EventBus是Google的开源项目Guava里的一个组件,有兴趣的人可以看我前不久的一篇博文解读。
简介 horae是一个基于redis和disque实现的轻量级、高性能的异步任务执行器,它的核心是disque提供的任务队列,而队列有先进先出的时序关系,顾得名:horae。 horae : 时序女神,希腊神话中司掌季节时间和人间秩序的三女神,又译“荷莱”。
前段时间重新对消息总线的通信模型进行设计&重构,这篇文章谈谈其中的一些想法。 RabbitMQ简介 消息总线对RabbitMQ的官方java client进行了定制、简化。这里首先谈谈RabbitMQ作为一个Message Broker的两个核心概念: Exchange Exchange(交换器),其实你可以简单得将它看成是Router(路由器),路由就是它的主要职责。
最近这段时间在设计和实现日志系统,在整个日志系统系统中Zookeeper的作用非常重要——它用于协调各个分布式组件并提供必要的配置信息和元数据。这篇文章主要分享一下Zookeeper的使用场景。这里主要涉及到Zookeeper在日志系统中的使用,但其实它在我们的消息总线和搜索模块中也同样非常重要。
最近我在日志收集的功能中加入了对docker容器日志的支持。这篇文章简单谈谈策略选择和处理方式。 关于docker的容器日志 docker 我就不多说了,这两年火得发烫。最近我也正在把日志系统的一些组件往docker里部署。
最近对日志系统的采集机制进行了重构,增强了对单一主机上多个日志源采集的便捷性。 重构之前 重构之前的设计以日志类型为中心,一个日志类型对应一个独立的flume的配置模板,一个日志类型的一个日志源(具体到某个节点上特定的日志文件)对应一个flume配置文件(也即一个flume agent)。
概述 在分布式实时计算领域,如何让框架/引擎足够高效地在内存中存取、处理海量数据是一个非常棘手的问题。在应对这一问题上Flink无疑是做得非常杰出的,Flink的自主内存管理设计也许比它自身的知名度更高一些。
回顾 上一篇文章我们谈了Flink自主内存管理的一些基础的数据结构。那篇中主要讲了数据结构的定义,这篇我们来看看那些数据结构的使用,以及内存的管理设计。 概述 这篇文章我们主要探讨Flink的内存管理类MemoryManager涉及到对内存的分配、回收,以及针对预分配内存而提供的memory segment pool。
Akka与Actor 模型 Akka是一个用来开发支持并发、容错、扩展性的应用程序框架。它是actor model的实现,因此跟Erlang的并发模型很像。在actor模型的上下文中,所有的活动实体都被认为是互不依赖的actor。
经常有人会问Flink如何处理背压问题。其实,答案很简单:Flink没用使用任何通用方案来解决这个问题,因为那根本不需要那样的方案。它利用自身作为一个纯数据流引擎的优势来优雅地响应背压问题。这篇文章,我们将介绍背压问题,然后我们将深挖Flink的运行时如何在task之间传输数据缓冲区内的数据以及流数据如何自然地两端降速来应对背压,最终将以一个小示例来演示它。
概述 最近这段时间在强化日志系统自身的稳定性和可靠性,一个稳定可靠的系统离不开监控,我们这里谈及的监控除了服务是否存活还有这些组件的核心metrics采集与抓取,为此我们将这些任务做成了定时任务来执行。
Flink中的数据交换构建在如下两条设计原则之上: 数据交换的控制流(例如,为实例化交换而进行的消息传输)是接收端初始化的,这非常像最初的MapReduce。 数据交换的数据流(例如,在网络上最终传输的数据)被抽象成一个叫做IntermediateResult的概念,它是可插拔的。
在源码解读前我们有必要先了解一下Flink的一些基本的但却很关键的概念。这有助于帮助我们理解整个架构。在翻译文档的同时,对于有争议的或者不是非常适合用中文表达的地方,我尽量保留原始英文单词。 程序和数据流 Flink程序的基本构建块是streams和transformations(注意,DataSet在内部也是一个stream)。
今天我们来解读一下Flink stream里的source模块。它是整个stream的入口,也是我们了解其流处理体系的入口。 SourceFunction SourceFunction是所有stream source的根接口。
window(窗口)是Flink流处理中非常重要的概念,本篇我们来对窗口相关的概念以及关联的实现进行解析。本篇的内容主要集中在package org.apache.flink.streaming.api.windowing下。
上一篇我们谈论了Flink stream source,它作为流的数据入口是整个DAG(有向无环图)拓扑的起点。那么与此对应的,流的数据出口就是跟source对应的Sink。这是我们本篇解读的内容。 SinkFunction 跟SourceFunction对应,Flink针对Sink的根接口被称为SinkFunction。
Window也即窗口,是Flink流处理的特性之一。前一篇文章我们谈到了Winodw的相关概念及其实现。窗口的目的是将无界的流转换为有界的元素集合,但这还不是最终的目的,最终的目的是在这有限的集合上apply(应用)某种函数,这就是我们本篇要谈的主题——WindowFunction(窗口函数)。
之前我们聊了Flink程序的source、sink就差transformation了。今天我们就来解读一下Flink的transformation。它们三者的关系如下图: 当然这还是从Flink编程API的角度来看的(编程视角)。
前面我们谈论了Flink stream中的transformation。你可以将transformation看成编写Flink程序并构建流式处理程序的必要组成部分(静态表现形式);而本篇我们将探讨transformation在Flink运行时对应的动态表现形式——operator。
因某些童鞋的建议,从这篇文章开始结合源码谈谈Flink Fault Tolerance相关的话题。上篇官方介绍的翻译是理解这个话题的前提,所以如果你想更深入得了解Flink Fault Tolerance的机制,推荐先读一下前篇文章理解它的实现原理。
继续Flink Fault Tolerance机制剖析。上一篇文章我们结合代码讲解了Flink中检查点是如何应用的(如何根据快照做失败恢复,以及检查点被应用的场景),这篇我们来谈谈检查点的触发机制以及基于Actor的消息驱动的协同机制。
上一篇文章我们探讨了基于定时任务的周期性检查点触发机制以及基于Akka的actor模型的消息驱动协同机制。这篇文章我们将探讨Zookeeper在Flink的Fault Tolerance所起到的作用。
上篇文章我们探讨了Zookeeper在Flink的fault tolerance中发挥的作用(存储/恢复已完成的检查点以及检查点编号生成器)。 这篇文章会谈论一种特殊的检查点,Flink将之命名为——Savepoint(保存点)。
上一篇文章我们谈论了保存点的相关内容,其中就谈到了保存点状态的存储。这篇文章我们来探讨用户程序状态的存储,也是在之前的文章中多次提及的state backend(中文暂译为状态终端)。 基于数据流API而编写的程序经常以各种各样的形式保存着状态: 窗口收集/聚合元素(这里的元素可以看作是窗口的状态)直到它们被触发 转换函数可能会使用key/value状态接口来存储数据 转换函数可能实现Checkpointed接口来让它们的本地变量受益于fault tolerant机制 当检查点机制工作时,上面谈到的这些状态将能够基于检查点一同持久化来保证数据不丢失并且得到可持续的恢复。
上篇文章我们分析了基于检查点的用户状态的保存机制——状态终端。这篇文章我们来分析barrier(中文常译为栅栏或者屏障,为了避免引入名称争议,此处仍用英文表示)。检查点的barrier是提供exactly once一致性保证的主要保证机制。
这篇文章是对Flinkfault tolerance的一个总结。虽然还有些细节没有涉及到,但是基本的实现要点在这个系列中都已提及。 回顾这个系列,每篇文章都至少涉及一个知识点。我们来挨个总结一下。 恢复机制实现 Flink中通常需要进行状态恢复的对象是operator以及function。
这篇文章介绍Flink的分区器,在流进行转换操作后,Flink通过分区器来精确得控制数据流向。 StreamPartitioner StreamPartitioner是Flink流分区器的基类,它只定义了一个抽象方法: public abstract StreamPartition...
之前我们谈到了Flink通过自主管理内存的方式来,避免了让JVM管理内存带来的一些问题。自主管理内存之后,JVM中原生的类型也就不适合使用了。因此Flink也对Java的类型进行了扩展,这就是我们本节关注的内容。
提交流程调用的关键方法链 用户编写的程序逻辑需要提交给Flink才能得到执行。本文来探讨一下客户程序如何提交给Flink。鉴于用户将自己利用Flink的API编写的逻辑打成相应的应用程序包(比如Jar)然后提交到一个目标Flink集群上去运行是比较主流的使用场景,因此我们的分析也基于这一场景进行。
概述 上文我们分析提交流程时,RemoteStreamEnvironment类的execute方法的第一步就是生成StreamGraph。 StreamGraph是用于表示流的拓扑结构的数据结构,它包含了生成JobGraph的必要信息。
对于处理时间类型的窗口(包含了翻滚窗口和滑动窗口),Flink会使用称之为”pane”的技术来优化这类时间窗口的计算。 pane:中文译为窗格。它将窗口划分成多个规则的部分,这些部分可看作子窗口,可简单理解为对窗口再次分片。
窗口算子WindowOperator是窗口机制的底层实现,它几乎会牵扯到所有窗口相关的知识点,因此相对复杂。本文将以由面及点的方式来分析WindowOperator的实现。首先,我们来看一下对于最常见的时间窗口(包含处理时间和事件时间)其执行示意图: 上图中,左侧从左往右为事件流的方向。
当前Flink将迭代的重心集中在批处理上,之前我们谈及了批量迭代和增量迭代主要是针对批处理(DataSet)API而言的,并且Flink为批处理中的迭代提供了针对性的优化。但是对于流处理(DataStream),Flink同样提供了对迭代的支持,这一节我们主要来分析流处理中的迭代,我们将会看到流处理中的迭代相较于批处理有相似之处,但差异也是十分之明显。
我们都知道Flink在可迭代的流处理中引入了反馈边来将本次迭代的结果反馈给迭代头以进行下一次迭代,这在执行拓扑中引入了环(反馈环)。Flink主要应对的执行拓扑还是有向无环图(DAG),最终它选择了将反馈环进行化解使其能够适配有向无环图的结构,而如何对反馈环进行化解是我们这一篇主要探讨的话题。
IterativeStream Flink在DataStream中也是通过一个特定的可迭代的流(IterativeStream)来构建相关的迭代处理逻辑,这一点跟DataSet提供的可迭代的数据集(IterativeDataSet)的是类似的。
前面我们分析过Flink对迭代在流图中的特殊处理,使得迭代中的反馈环得以转化为普通的DAG模型。这一篇我们将剖析运行时的流处理迭代任务的执行机制。这里涉及到两个任务类: StreamIterationHead:迭代头任务,它借助于反馈阻塞队列从迭代尾部接收参与下一次迭代的反馈数据。
网络环境(NetworkEnvironment)是TaskManager进行网络通信的主对象,主要用于跟踪中间结果并负责所有的数据交换。每个TaskManager的实例都包含一个网络环境对象,在TaskManager启动时创建。