文档章节

Apache Kafka源码剖析:第1篇 网络引擎漫谈(类比法)

强子哥哥
 强子哥哥
发布于 2017/08/11 09:11
字数 1885
阅读 83
收藏 1
点赞 0
评论 0

从这一篇开始,我们来研究kafka的网络引擎的源码。

可能很多读者有疑问,说好的Kafka讲解,怎么变成Thrift了?
答案: 原理都一样,先拿Thrift为例,讲解网络服务器的Reactor本质,后面会专门
针对这个开一篇博客讲解Kafka的源码,敬请期待!

==========================================

开始介绍kafka服务端之前,先从整体上了解架构。

本章会详细介绍每个组件的功能和实现!

网络层

如果以前看过网上的文章,就知道kafka的客户端会跟服务端的多个broker建立网络连接。

通过这些 socket连接传递各种信息,从而实现c/s交互!

客户端一般情况下不会碰到大数据量访问。

服务端则不同,面对高并发、低延迟的需求,Kafka服务端使用Reactor模式实现其网络层。

这一层不仅仅要管理producer,consumer,还要管理来自其它broker的连接(想一想为什么? :)

---Reactor模式

在聊这种模式之前,让我们快乐的想一想redis,netty,mina,thrift的网络模型

无一例外基本都是这种模型,特殊一点的是redis单线程操作,而它之所以敢这么做,原因就在于它是1个内存操作,否则必须死翘翘。

好,聊到reactor模式,那么这个到底是啥玩意?

我们先想一想如何写一个网络服务器,要解决哪些问题?

1)accept问题

2)I/O处理读写的问题,其中读是读取完整逻辑报文

3)业务逻辑处理,包含各种后端业务交互过程

任何1个网络服务器,都要解决这3个问题,否则就是耍流氓了。

 

那么,具体要怎么实现呢?

1)读取配置文件,生成listening socket,产生监听套接字,然后注册OP_ACCEPT事件到selector上

注意,针对监听套接字的可读,就是有client socket连接进来导致acceptable事件 :)

一般是启动1个Acceptor线程来处理这种事件

2)一旦有连接过来,服务端的Selector监听到此事件,触发accept事件。

3)创建socketChannel,设置为非阻塞模式,在别的selector上注册I/O事件

(其实这里才是Reactor事件的核心,利用Linux内核的机制高效监听各种socket可以操作的事件,不会造成浪费!!! socket设置为非阻塞模式也正是因为此!)

4)当客户端发送消息时,服务端的Selector监听到OP_READ事件,触发执行相应的处理逻辑。

当服务端可以写时,服务端监听到OP_WRITE事件,触发执行相应的处理逻辑。

这里一定要请读者考虑到TCP的字节流协议特性,你懂的

---

这里涉及到3种事情,ACCEPT,IO处理,业务处理,涉及到几种线程呢?

redis因为内存操作的特点,所以大胆的放在了1个线程,但是对于Kafka呢,怎么办?

对于kafka Producer/Consumer来说,是在1个线程里,适合客户端这种并发连接小,数据量小的场景

 

但是对于服务端来说,就不行,比如对某个socket请求的处理耗时,就会造成线程阻塞,后续其它请求都无法被处理,这业务要骂人了。。。

应该怎么做?
读取请求,处理请求,发送请求,应该在不同的线程里来实现
通常读取发送在1个线程,处理请求在另外1个线程。
处理请求的叫做业务线程池
netty不带业务线程池,所以自己要new一个出来。
thrift天生完美自带业务线程池,快速高效!
redis是一个另类,内存操作快速,全在1个线程搞定,按下不表!

这样,就充分发挥了多核多线程的优势,

一言以蔽之:调整架构,将网络读写的逻辑与业务处理逻辑拆分,由不同的线程执行,从而实现牛逼的多线程处理。

 

具体还有一些细节,针对kafka来说

1)Acceptor单独运行在1个线程里,thrift也是默认启动了1个线程。

先插入Thrift的Acceptor线程是如何启动的!

看来Thrift直接启动了一个线程,

其实用ExecutorService来启动单线程更好,因为线程异常退出时,会创建新线程进行补偿!

---

通过accept接收到的socketchannel,会注册OP_READ事件,负责服务端的 socket读取逻辑,这个时候

一个线程会处理多个socket,不然没法处理多socket啊,成功读取请求后,注意这里的成功读取是完整读取了1个socket请求体,这里涉及到业务协议,时刻注意TCP的字节流特性!!!

读取了完整的请求体后,怎么做?我们先看Thrift怎么做的,同类产品来个对比嘛

可见,这里是new了1个业务线程池,然后把请求抛到业务线程池里,

注意,我们都知道业务线程池内部有1个blockingqueue,其实是把请求放到了这个队列里!

然后我们再来看看 Kafka怎么做的,它是读到了1个完整的请求后,请求放到一个MessageQueue共享队列里,业务线程池中的线程会取出请求,然后执行业务逻辑对请求进行处理。

这种模式跟Thrift的模式基本一致,那么这种处理逻辑有什么好处呢?

因为采用了业务线程池,即使某个业务线程阻塞了,池中还有其它线程继续执行。

就不会堵塞请求,吞吐量才可以保证!

 

当业务线程处理完后,拿到了结果,怎么处理呢?抛回给IO线程池,至少Thrift是这么玩的

IO线程池的优势就是快速知道一个socket可以进行读写,然后才进行读写,整个Reactor框架的核心就在于此!!!

===

最后需要注意的是,当请求进入的速度与处理的速度不匹配时,MessageQueue的长度非常重要。

尤其是这个Queue的大小固定时,我们先看Thrift的队列大小是怎么选择的

不用我再多解释1个字了吧。

如果长度太小,放不进去,请求都不用处理直接失败了

如果不限制长度,可能请求太多涌入,导致内存溢出,需要业务人员自己设置参数

(擦,业务自己背锅啊)

如果同一时间出现大量IO事件,单个selector可能忙不过来,可以设置多个Selector,监听不同的IO事件

其实就是处理不同的socket,本质还不就是负载均衡么。。。

这个也没啥好说的!

=======================================================

一般情况下,Acceptor单独占用1个Selector,
通过accept得到的SocketChannel,通过一定的策略分发给IO线程里的Selector

还是以Thrift类比来讲解,我们看Thrift怎么实现的!

不用我解释了,轮询大法好!

强调1点,这个算法是用来选择IO线程的,IO线程自己会注册到自己线程专属的Selector上。

-------------------------------------------------------------------

 

 

 

 

 

© 著作权归作者所有

共有 人打赏支持
强子哥哥

强子哥哥

粉丝 856
博文 551
码字总数 647493
作品 8
南京
架构师
apache kafka技术分享系列(目录索引)

目录索引: Kafka使用场景 1.为何使用消息系统 2.我们为何需要搭建ApacheKafka分布式系统 3.消息队列中点对点与发布订阅区别 kafka开发与管理: 1)apachekafka消息服务 2)kafak安装与使用 ...

dannyhe ⋅ 2015/09/06 ⋅ 1

Kafka文章索引(入门)

目录索引: 1)apache kafka消息服务 2)kafka在zookeeper中存储结构 3)kafka log4j配置 4)kafka replication设计机制 5)apache kafka监控系列-监控指标 6)kafka.common.ConsumerRebala...

阿莱倪士 ⋅ 2014/11/27 ⋅ 0

漫谈Deep PCA与PCANet

  又到了无聊的写博客的时间了,由于电脑在跑程序,目前无事可做,我觉得把昨天我看的一些论文方面的知识拿出来和大家分享一下。   美其名曰我是在研究”深度学习“,不过由于本人是穷屌...

u013088062 ⋅ 2015/12/29 ⋅ 0

剖析 “‘最好的模板引擎’Beetl剖析及与Tiny模板引擎对比”

http://blog.csdn.net/cndes/art ... 88771 这有一篇文章,说是剖析beetl模板引擎,并与同为国内的tiny模板引擎做对比(以下简称“剖析beetl”),其剖析过程公正,但结论却不正确(文中暗示的...

闲大赋 ⋅ 2016/07/14 ⋅ 9

深度学习微信精选文章

公众号——深度学习每日摘要 所有文章(持续更新中): 聊聊语音识别的发展历程 说说重要的贝叶斯公式吧 我对入门深度学习的切身体会 聊聊隐马尔科夫模型(HMM) 关于防止过拟合的一些想法 ...

断桥残雪断桥残雪 ⋅ 2016/12/02 ⋅ 2

消息中间件(Kafka/RabbitMQ)收录集

本篇主要整理工作中遇到的一些消息中间件的相关知识,包括Kafka, RabbitMQ, RocketMQ, ActiveMQ等,不排除收录其他消息中间件的可能。 这里会持续收录相关知识,包括安装、部署、使用示例、监...

u013256816 ⋅ 2017/01/26 ⋅ 0

源码圈 365 胖友的书单整理

🙂🙂🙂关注微信公众号:【芋道源码】有福利: RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表 RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址 您对于源码的疑问...

芋道源码掘金Java群217878901 ⋅ 2017/09/21 ⋅ 0

大数据和云计算技术周报(第9期)

写在第9期周报 坚持是一种品格!社区祝大家新年快乐! “大数据” 三个字其实是个marketing语言,从技术角度看,包含范围很广,计算、存储、网络都涉及,知识点广、学习难度高。 #大数据和云...

znzqhb07nr ⋅ 01/01 ⋅ 0

Mina源码阅读笔记(一)-整体解读

今天的这一节,将从整体上对mina的源代码进行把握,网上已经有好多关于mina源码的阅读笔记,但好多都是列举了一下每个接口或者类的方法。我倒是想从mina源码的结构和功能上对这个框架进行剖析...

Gaischen ⋅ 2012/11/19 ⋅ 19

大数据和云计算技术周报(第7期)

坚持是一种品格! “大数据” 三个字其实是个marketing语言,从技术角度看,包含范围很广,计算、存储、网络都涉及,知识点广、学习难度高。 #大数据和云计算技术社区#希望通过坚持定期分享能...

znzqhb07nr ⋅ 2017/12/25 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

JPA入门,配置文件的设置

<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http......

码农屌丝 ⋅ 16分钟前 ⋅ 0

Java基础——面向对象和构造器

声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权;凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记。 静态成员介绍 为什么要有静态成员?静态成员用来...

凯哥学堂 ⋅ 18分钟前 ⋅ 0

vmware中Centos 7 linux的LVM磁盘扩容

系统是RHEL7(centos7差不多一样) 关闭系统,在vmware、设置、硬盘、扩展、输入数字大于当前系统内存、点击扩展。 开机再查看磁盘信息 fdisk -l 注意:可以看出sda磁盘增加了,但是根目录还...

gugudu ⋅ 29分钟前 ⋅ 0

JAVA线程sleep和wait方法区别

昨天面试,突然被问到sleep 和 wait的区别,一下子有点蒙,在这里记一下,以示警戒。 首先说sleep,sleep就是正在执行的线程主动让出cpu,cpu去执行其他线程,在sleep指定的时间过去后,cpu...

徐玉强 ⋅ 31分钟前 ⋅ 0

vuex学习--模块

随着项目复杂性增加,共享状态也越来越多。需要对转态操作进行分组,分组后在进行分组编写。学习一下module:状态管理器的模块组操作。 首先是声明: const moduleA={ state,mutations,g...

大美琴 ⋅ 33分钟前 ⋅ 0

Selenium 简单入门

安装 pip install selenium 驱动下载 https://chromedriver.storage.googleapis.com/index.html 下载最新的驱动,放入path中,可以放入Python的scripts目录下,也可以放入Chrome安装目录,并...

阿豪boy ⋅ 34分钟前 ⋅ 0

292. Nim Game - LeetCode

Question 292. Nim Game Solution 思路:试着列举一下,就能发现一个n只要不是4的倍数,就能赢。 n 是否能赢1 true2 true3 true4 false 不论删除几,对方都能一把赢5 t...

yysue ⋅ 今天 ⋅ 0

6.5 zip压缩工具 6.6 tar打包 6.7 打包并压缩

zip压缩工具 zip命令可以压缩目录和文件,-r 压缩目录。 zip使用方法 zip 1.txt.zip 1.txt //压缩文件 zip -r 123.zip 123/ //压缩目录 unzip 1.txt.zip //解压 unzip 123.zip -d /root/456...

Linux_老吴 ⋅ 今天 ⋅ 0

react-loadable使用跳坑

官方给react-loadable的定义是: A higher order component for loading components with dynamic imports. 动态路由示例 withLoadable.js import React from 'react'import Loadable fro......

pengqinmm ⋅ 今天 ⋅ 0

记录工作中遇到的坑

1、ios safari浏览器向下滚动会触发window resize事件

端木遗风 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部