netty40源码
A. Netty 源码解析 ——— ChannelConfig 和 Attribute
嗯,本文与其说是ChannelConfig、Attribute源码解析,不如说是对ChannelConfig以及Attribute结构层次的分析。因为这才是它们在Netty中使用到的重要之处。
在 Netty 源码解析 ——— 服务端启动流程 (下) 中说过,当我们在构建NioServerSocketChannel的时候同时会构建一个NioServerSocketChannelConfig对象赋值给NioServerSocketChannel的成员变量config。
而这一个NioServerSocketChannelConfig是当前NioServerSocketChannel配置属性的集合。NioServerSocketChannelConfig主要用于对NioServerSocketChannel相关配置的设置(如,网络的相关参数配置),比如,配置Channel是否为非阻塞、配置连接超时时间等等。
NioServerSocketChannelConfig其实是一个ChannelConfig实例。ChannelConfig表示为一个Channel相关的配置属性的集合。所以NioServerSocketChannelConfig就是针对于NioServerSocketChannel的配置属性的集合。
ChannelConfig是Channel所需的公共配置属性的集合,如,setAllocator(设置用于channel分配buffer的分配器)。而不同类型的网络传输对应的Channel有它们自己特有的配置,因此可以通过扩展ChannelConfig来补充特有的配置,如,ServerSocketChannelConfig是针对基于TCP连接的服务端ServerSocketChannel相关配置属性的集合,它补充了针对TCP服务端所需的特有配置的设置setBacklog、setReuseAddress、setReceiveBufferSize。
DefaultChannelConfig作为ChannelConfig的默认实现,对ChannelConfig中的配置提供了默认值。
接下来,我们来看一个设置ChannelConfig的流程:
serverBootstrap.option(ChannelOption.SO_REUSEADDR, true);
我们可以在启动服务端前通过ServerBootstrap来进行相关配置的设置,该选项配置会在Channel初始化时被获取并设置到Channel中,最终会调用底层ServerSocket.setReuseAddress方法来完成配置的设置。
ServerBootstrap的init()方法:
首先对option和value进行校验,其实就是进行非空校验。
然后判断对应的是哪个常量属性,并进行相应属性的设置。如果传进来的ChannelOption不是已经设定好的常量属性,则会打印一条警告级别的日志,告知这是未知的channel option。
Netty提供ChannelOption的一个主要的功能就是让特定的变量的值给类型化。因为从’ChannelOption<T> option’和’T value’可以看出,我们属性的值类型T,是取决于ChannelOption的泛型的,也就属性值类型是由属性来决定的。
这里,我们可以看到有个ChannelOption类,它允许以类型安全的方式去配置一个ChannelConfig。支持哪一种ChannelOption取决于ChannelConfig的实际的实现并且也可能取决于它所属的传输层的本质。
可见ChannelOption是一个Consant扩展类,Consant是Netty提供的一个单例类,它能安全去通过’==’来进行比较操作。通过ConstantPool进行管理和创建。
常量由一个id和name组成。id:表示分配给常量的唯一数字;name:表示常量的名字。
如上所说,Constant是由ConstantPool来进行管理和创建的,那么ConstantPool又是个什么样的类了?
首先从constants中get这个name对应的常量,如果不存在则调用newConstant()来构建这个常量tempConstant,然后在调用constants.putIfAbsent方法来实现“如果该name没有存在对应的常量,则插入,否则返回该name所对应的常量。(这整个的过程都是原子性的)”,因此我们是根据putIfAbsent方法的返回来判断该name对应的常量是否已经存在于constants中的。如果返回为null,则说明当前创建的tempConstant就为name所对应的常量;否则,将putIfAbsent返回的name已经对应的常量值返回。(注意,因为ConcurrentHashMap不会允许value为null的情况,所以我们可以根据putIfAbsent返回为null则代表该name在此之前并未有对应的常量值)
正如我们前面所说的,这个ConstantPool<ChannelOption<Object>> pool(即,ChannelOption常量池)是ChannelOption的一个私有静态成员属性,用于管理和创建ChannelOption。
这些定义好的ChannelOption常量都已经存储数到ChannelOption的常量池(ConstantPool)中了。
注意,ChannelOption本身并不维护选项值的信息,它只是维护选项名字本身。比如,“public static final ChannelOption<Integer> SO_RCVBUF = valueOf("SO_RCVBUF");”👈这只是维护了“SO_RCVBUF”这个选项名字的信息,同时泛型表示选择值类型,即“SO_RCVBUF”选项值为Integer。
好了,到目前为止,我们对Netty的ChannelOption的设置以及底层的实现已经分析完了,简单的来说:Netty在初始化Channel时会构建一个ChannelConfig对象,而ChannelConfig是Channel配置属性的集合。比如,Netty在初始化NioServerSocketChannel的时候同时会构建一个NioServerSocketChannelConfig对象,并将其赋值给NioServerSocketChannel的成员变量config,而这个config(NioServerSocketChannelConfig)维护了NioServerSocketChannel的所有配置属性。比如,NioServerSocketChannelConfig提供了setConnectTimeoutMillis方法来设置NioServerSocketChannel连接超时的时间。
同时,程序可以通过ServerBootstrap或Boostrap的option(ChannelOption<T> option, T value)方法来实现配置的设置。这里,我们通过ChannelOption来实现配置的设置,ChannelOption中已经将常用的配置项预定义为了常量供我们直接使用,同时ChannelOption的一个主要的功能就是让特定的变量的值给类型化。因为从’ChannelOption<T> option’和’T value’可以看出,我们属性的值类型T,是取决于ChannelOption的泛型的,也就属性值类型是由属性来决定的。
一个attribute允许存储一个值的引用。它可以被自动的更新并且是线程安全的。
其实Attribute就是一个属性对象,这个属性的名称为AttributeKey<T> key,而属性的值为T value。
我们可以通过程序ServerBootstrap或Boostrap的attr方法来设置一个Channel的属性,如:
serverBootstrap.attr(AttributeKey.valueOf("userID"), UUID.randomUUID().toString());
当Netty底层初始化Channel的时候,就会将我们设置的attribute给设置到Channel中:
如上面所说,Attribute就是一个属性对象,这个属性的名称为AttributeKey<T> key,而属性的值为T value。
而AttributeKey也是Constant的一个扩展,因此也有一个ConstantPool来管理和创建,这和ChannelOption是类似的。
Channel类本身继承了AttributeMap类,而AttributeMap它持有多个Attribute,这些Attribute可以通过AttributeKey来访问的。所以,才可以通过channel.attr(key).set(value)的方式将属性设置到channel中了(即,这里的attr方法实际上是AttributeMap接口中的方法)。
AttributeKey、Attribute、AttributeMap间的关系:
AttributeMap相对于一个map,AttributeKey相当于map的key,Attribute是一个持有key(AttributeKey)和value的对象。因此在map中我们可以通过AttributeKey key获取Attribute,从而获取Attribute中的value(即,属性值)。
Q:ChannelHandlerContext和Channel都提供了attr方法,那么它们设置的属性作用域有什么不同了?
A:在Netty 4.1版本之前,它们两设置的属性作用域确实存在着不同,但从Netty 4.1版本开始,它们两设置的属性的作用域已经完全相同了。
若文章有任何错误,望大家不吝指教:)
圣思园《精通并发与Netty》
B. netty 一个server有可以建多少个连接
1. 应用在netty建连接的过程中做了耗时的事;
因此我先mp了应用的线程,看到一切正常,boss线程看起来非常空闲;
2. backlog太小;
首先问了下开发代码里有没有设置过backlog,开发告诉我没设置过,于是我翻了下netty的源码确认下默认值,看到backlog的默认值为读取自系统的/proc/sys/net/core/somaxconn,于是查了下系统的这个值,确认系统的这个值已经是调整过的,设置为了2048,然后确认了系统上的tcp_max_syn_backlog是4096,也就是最后work的会是2048(为什么是这样具体可见 这篇文章 ),也就是说应该是够的。
用ss -s观察连接的状况,看到的是synrecv是0,也印证了上面的不是backlog的问题。
到这一步就彻底傻眼了,不知道该用什么方法排查了,于是开始一堆的google,看到的各种说解决新建连接并发低的解决办法,除了调整backlog外,主要是以下两种:
1 关闭tcp_tw_recycle,尝试了(话说这里充分体现了”病急乱投医“的心态,其实我自己都不相信改这参数有用,但想着只是改下参数这种小代价的事,还是试试吧),没任何作用;
2 关闭window scaling ,也尝试了,一样没任何作用;
查到这个阶段觉得自己已经无法理解了,于是求助了厂内内核团队对网络这块比较精通的同学,然后又求助了“神”,“神“帮忙看了会后,说主要的问题是现在是每epollWait唤醒一次,只建了一个连接,这导致在大量新建连接请求并发的时候,效率不够高,因此我翻了下代码,发现我本机上看到的代码不是这样的,我本机上看到的netty代码在epollWait唤醒后,是会尝试一直去accept的,但这个应用使用的netty确实不是这样,于是查了下应用的jar包库,发现里面有两个版本的netty(一个是3.2.1.Final,一个是3.6.3.Final),3.2.1确实是每次epollWait后就处理一个,于是通知开发同学把3.2.1去掉,满心期待的认为应该是好了,等开发更新好了后,自己也确认了一次epollWait唤醒后会连续处理很多个建立连接的请求,但悲催的还是没解决问题,具体的netty在这块的改造感兴趣的同学可以看看NioServerSocketPipelineSink这个类(重点看select唤醒后)…
到这步,就彻底郁闷了,话说其实到这步的时候我已经被这个问题困扰了2天多了,于是只好继续google,发现又有提到打开syn cookies的建议,于是尝试了下,竟然真的work了,打开了这个参数后新建连接的并发请求轻松超过100+了。
到此以为已经解决了,但很快开发给我反馈,整个集群开启了这个参数后,连接确实是能建上了,但客户端出现了发了请求后,等不到任何响应的现象,当时还不确定服务器端到底有没有收到请求,于是只好又先关闭了这个参数(话说这个我到现在都不明白为什么这个参数打开后,会出现发请求没响应的现象,求高人解答)。
尽管还是没解决,但毕竟有进展,有的进展就是打开了syn cookies后连接就能建上,而syn cookies只有在backlog满了后才会生效,那也就是说还是backlog满了,从kern的日志也能确认syn cookies确实是work了,到这步就觉得诡异了,明明netty用的默认值就是somaxconn,而每秒新建40多个连接,且boss线程还很空闲的情况下显然不应该出现backlog满的现象,这个时候仔细看了下本机查看的netty代码,才发现我看的是netty 4的代码,而应用用的是netty 3.6.3,悲催,赶紧把netty 3.6.3的代码捞下来看了,才发现在3.6.3里backlog的默认值处理时不一样的,在3.6.3里默认值是50,不是netty写的默认值,是java本身,50那估计真的不一定够,于是就通知开发在代码里先强制设置下backlog为1000。
在开发改代码的过程中,还有一个怀疑点想确认,就是既然是backlog满了,为什么看到的synrecv会是0呢,于是再用netstat -na | grep [port] | grep SYN_RECV -c统计了下,结果发现值基本一直是64,java层面默认设置的是50,linux会将这个值调整为大于这个值的2的n次幂的值,那也就是64,好吧,看到这就彻底可以确定真的是因为backlog太小了造成的(只是话说我不明白为什么ss -s统计出来的synrecv会是0呢,求高人解答)。
等开发改完代码重新发布后,稍微增加了点引流测试了下,轻松支撑每秒200+,客户端建立连接后发请求获取响应也完全ok,问题到此宣告解决。
题外话: 这应用之所以会比较容易出现较多的synrecv,主要是因为手机网络通常是不太稳定的,另外一个原因是这种对外的都很容易带来攻击,而当时刚好这个应用前面的一个用来防syn flood的由于有bug临时关闭了,所以问题暴露的比较明显。
从这个折腾了4天的case的排查过程,大家可以看到其实如果一开始我仔细确认过应用用的netty版本和我本机看的代码是不一致的话,估计很快就会排查出原因就是backlog值太小造成的,所以说折腾了这么多天其实也是自己造成的,这个告诉自己,以后排查问题的时候一定要对出现问题的应用所在的环境更加清楚的确认。
ps: 最后再多啰嗦几句,从这个case还能看到的是netty的版本其实在细节上是一直在改进的,就像这个case里的不同版本的netty在处理连接事件唤醒上,还有backlog的默认值上,所以我一直很强调,对于需要存活很多年的软件而言,选择一个使用范围较广的开源软件是非常重要的,如果自己开发,也许短期能超越,但放到三年、五年这样的范围来看,通常是很难和开源软件去抗衡的(原因是商业公司没多少人会专注在一个领域做三五年的,而开源界这样的人实在是多,说实话,这种case看过太多),所以如果觉得你能做的比开源软件好,还不如去帮助已有的(当然,如果这个领域目前完全没有什么使用面较广的、靠谱的,那自己做一个开源是挺好的),软件的可持续发展能力(除非是一次性软件、做的玩的或就玩个一两年的)是非常非常重要的。
C. netty 如何阻塞主线程
1 netty本身的 worker线程的个数是根据CPU来的,直接在 worker线程里做业务逻辑处理不好么?
2 如果不想并发,修改源码,让worker线程个数为1,就没有并发了,这一点跟redis一样的,redis单线程的处理能力貌似也够用了,redis的作者是这么说的。
3 为啥要自定义多个业务逻辑线程?netty本身的worker线程拿到消息后就可以处理了啊
D. Netty核心组件之NioEventLoop(一)
在接下来几篇文章,我会通过Netty的源码深入讲解NioEventLoop的实现机制。
特别说明:基于4.1.52版本的源码
先来看下NioEventLoop的类关系图和重要的属性,对其有一个整体的感知,便于后面详细分析。
首先来看NioEventLoop的构造函数
默认情况下,会创建MPSC,即多生产者单消费者的队列,这里最终会用到JCTools库,这里不过多介绍,感兴趣的可以自己去了解。
如果设置了优化开关(默认优化选项是开启的),则通过反射的方式从Selector中获取selectedKeys和publicSelectedKeys,将这两个成员设置为可写,通过反射,使用Netty构造的selectedKeySet将原生JDK的selectedKeys替换掉。
我们知道使用Java原生NIO接口时,需要先调Selector的select方法,再调selectedKeys方法才可以获得有IO事件准备好的SelectionKey集合。这里优化过后,只通过一步select调用,就可以从selectedKeySet获得需要的SelectionKey集合。
另外,原生Java的SelectionKey集合是一个HashSet,这里优化过后的SelectedSelectionKeySet底层是一个数组,效率更高。
EventLoop的职责可以用下面这张图形象的表示
下面详细解析:
每次循环,都会检测任务队列和IO事件,如果任务队列中没有任务,则直接返回SelectStrategy.SELECT;如果任务队列中有任务,则会调用非阻塞的 selectNow 检测有IO事件准备好的Channel数。
nextScheledTaskDeadlineNanos 方法返回下一个将要被执行的定时任务的截止时间
NioEventLoop的定时任务队列是一个优先级队列,队列中存储的是ScheledFutureTask对象
通过ScheledFutureTask的 compareTo 方法可以看出,优先级队列中的元素是以任务的截止时间来排序的,队首元素的截止时间最小,当截止时间相同时,以任务ID排序,ID小的排在前面。
当定时任务ScheledFutureTask执行后,会根据 periodNanos 的取值决定是否要将任务重新放回队列。从netty的注释可以清晰看到:
看下ScheledFutureTask的 run 方法
当任务的执行时间还未到,则判断任务是否已经取消,如果已取消则移除任务,否则重新加入队列。对于只执行一次的任务,执行完了不会再放回队列。其他的任务,则根据 periodNanos 的类型,重新计算截止时间,重新放回队列,等待下次调度。
定时任务的优先级队列到此介绍完毕,接着看NioEventLoop的 run 方法
在调用 select 之前,再次调用 hasTasks() 判断从上次调用该方法到目前为止是否有任务加入,多做了一层防护,因为调用 select 时,可能会阻塞,这时,如果任务队列中有任务就会长时间得不到执行,所以须小心谨慎。
如果任务队列中还是没有任务,则会调用 select 方法。在这个方法中会根据入参 deadlineNanos 来选择调用NIO的哪个select方法:
到这里,可能有人要问了: 在上面的方法中,如果调用了Java NIO的无参的 select 方法,就会进入阻塞,除非检测到Channel的IO事件,那么在检测到IO事件之前,加入到任务队列中的任务怎么得到执行呢?
好,你想,在检测到IO事件之前,可以退出阻塞的方法是什么?对,调用 wakeup 方法。那么我们来搜一下NioEventLoop中有调用Selector的 wakeup 方法的地方吗:
还真搜到了,再看一下这个方法被调用的地方
看到SingleThreadEventExecutor的 execute 方法了吗,就是说在调 execute 方法,向EventLoop提交任务时,会将EventLoop线程从Java NIO的select阻塞中唤醒。
到这里,NioEventLoop的run方法的职责之一:检测Channel的IO事件就讲解完毕。
至于IO事件的处理以及任务队列中任务的处理会在后面的文章中解析,敬请期待。
在本文中,对Netty的NioEventLoop进行了深入的解读,并且详细讲解了它的三大职责之一:检测Channel的IO事件的机制。
NioEventLoop是Netty最核心的概念,内部运行机制很复杂,在接下来的两篇文章中会继续分析。
E. 《Netty实战NettyINACTION》epub下载在线阅读,求百度网盘云资源
《Netty实战》(诺曼·毛瑞尔(Norman Maurer))电子书网盘下载免费在线阅读
资源链接:
链接:
书名:Netty实战
作者:诺曼·毛瑞尔(Norman Maurer)
译者:何品
豆瓣评分:7.5
出版社:人民邮电出版社
出版年份:2017-5-1
页数:276
内容简介:
编辑推荐
- Netty之父”Trustin Lee作序推荐
- 阿里巴巴中间件高级技术专家为本书中文版作序推荐
- 系统而详细地介绍了Netty的各个方面并附带了即用型的优质示例
- 附带行业一线公司的案例研究
- 极实用的Netty技术书
无论是构建高性能的Web、游戏服务器、推送系统、RPC框架、消息中间件还是分布式大数据处理引擎,都离不开Netty,在整个行业中,Netty广泛而成功的应用,使其成为了Java高性能网络编程的卓绝框架。
Netty的现Tech Lead Norman在本书中循序渐进地讲解了Netty的各个关键部分,在看完本书后,你不但可以熟练地使用Netty来构建以上系统,并且还可以避免很多常见的陷阱。
无论是想要学习Spring 5 、Spark、Cassandra等这样的系统,还是通过学习Netty来构建自己的基于Java的高性能网络框架,或者是更加具体的高性能Web或者游戏服务器等,本书都将是你的超强拍档。
本书中文版基于Netty4.1.9做了修订,希望本书能够给你带来一个接近完美的阅读体验,并能帮到你。
内容提要
本书是为想要或者正在使用Java从事高性能网络编程的人而写的,循序渐进地介绍了Netty各个方面的内容。
本书共分为4个部分:第一部分详细地介绍Netty的相关概念以及核心组件,第二部分介绍自定义协议经常用到的编解码器,第三部分介绍Netty对于应用层高级协议的支持,会覆盖常见的协议及其在实践中的应用,第四部分是几个案例研究。此外,附录部分还会简单地介绍Maven,以及如何通过使用Maven编译和运行本书中的示例。
阅读本书不需要读者精通Java网络和并发编程。如果想要更加深入地理解本书背后的理念以及Netty源码本身,可以系统地学习一下Java网络编程、NIO、并发和异步编程以及相关的设计模式。
本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。
作者简介:
Norman Maurer,是苹果公司的资深软件工程师,同时也是Netty的核心开发人员。
Marvin Allen Wolfthal,是Dell Services的顾问,他使用Netty实现了多个任务关键型的企业系统。
何品,目前是淘宝的一名资深软件工程师,热爱网络、并发、异步相关的主题以及函数式编程,同时也是Netty、Akka等项目的贡献者,活跃于Scala社区,目前也在从事GraphQL相关的开发工作。
F. 为什么学习集合关系
集合可以说是学习 Java 中最重要的一块知识点了,无论做任何业务系统,集合总是最为基础的那块 API。我第一次接触集合,是在我大三的时候,那时候去面试,面试官问我:你了解过集合吗?可惜那时候没什么项目经验,所以基本没有了解过,因此也错失了机会。
到了现在,我已经工作了5年了,也做过了大大小小十几个项目。这些项目中有简单的 SSH 项目,也有分布式高并发的复杂项目。无论在哪个项目中,关于集合的时候是必不可少的。但我现在慢慢回顾过去做的项目,我发现自己使用到的集合还是比较少,基本上只有:ArrayList、HashSet、HashMap 这几个。
但当我开始深入去了解 JDK 集合的整个体系时,我发现之前的我了解得确实非常浅显。例如关于 List 的实现有 ArrayList、LinkedList、Vector、Stack 这四种实现,但我们很多时候只是直接使用 ArrayList,而不是根据场景去选择。
1.学习集合源码,能够让我们使用得更加准确。
当我们深入学习了源码之后,我们就能够了解其特性,从而能够根据我们的使用场景去做出更好的选择,从而让我们的代码运行效率更高。
我们举一个最简单的例子 —— ArrayList 和 LinkedList。它们两者底层采用了完全不同的实现方式,ArrayList 使用数组实现,而 LinkedList 则使用链表实现。这使得 ArrayList 的读取效率高,而 LinkedList 的读取效率低。但因为 LinkedList 采用链表实现,所以其增加和删除比较方便,而 ArrayList 则比较麻烦。所以 ArrayList 比较适合用于读场合较多的情况,而 LinkedList 比较适合用于增加、删除较多的场景。
我们来看另外一个例子 —— HashMap 和 TreeMap。乍看之下,他们都是 Map 集合的实现,但是它们内部有着截然不同的实现。HashMap 是 Map 接口的哈希实现,其内部使用了链表和红黑树实现。而 TreeMap 是 Map 接口的有序实现,其内部使用了红黑树实现。所以 HashMap 一般用来存储 key、value 的实现,而 TreeMap 常用存储需要排序的元素。
除了我们举的这两个例子之外,还有许多这样的例子,比如:HashMap 与 LinkedHashMap 的区别,HashMap 与 WeakHashMap 的区别,LinkedList 与 ArrayDeque 的区别。
2.学习集合源码,让我们学习经典的设计方式。
在集合的整个架构设计中,其类继承体系非常简单,但是却很经典。例如:Collection 接口设计了集合通用的操作,每个集合类型都有对应的接口(List、Set、Map),每个集合类型都有对应的抽象实现(AbstractList、AbstractSet、AbstractMap)等。
当我们阅读这些源码的时候,这种设计方式都会潜移默化地影响我们。当我们之后自己设计一个框架的时候,我们就会不知不觉地用上去。所有的创新都是从模仿开始的,所以阅读优秀的集合源码很重要。
3.帮助通过面试,获得更高的薪酬。
现在关于集合的原理是 Java 工程师面试的家常菜,几乎每一个企业的面试都会问到。如果你连这块东西都没搞清楚,那么你就不需要聊其他了,直接被干掉。而如果你能将整个 Java 集合体系清晰地说出去,并且举一反三地对比,那么你就比其他人优秀了。
4.学习经典的数据结构。
还记得大学在学习数据结构的时候,我们都是从理论上去记忆。但是当我看完集合源码之后,我忽然发现——JDK集合源码简直就是数据结构的最佳实践呀!
数据结构中最为基础的几个结构为:顺序表、单链表、双向链表、队列、栈、二叉堆、红黑树、哈希表。这些所有的实现都能在 JDK 集合的实现中找到。例如:ArrayList 就是顺序表的实现,LinkedList 就是双向链表的实现,Stack 就是栈的实现,HashMap 就是哈希表的实现,TreeMap 就是红黑树的实现,PriorityQueue 就是二叉堆的实现。
5.所有技术的基础
集合源码可以说是 JDK 所有源码中最为简单的一块了,而且也是其他所有源码的基础。例如线程池的源码中也大量使用了阻塞队列,如果你连集合源码都搞不懂,那么线程池的源码你也肯定看不懂的。而如果线程池源码看不懂,那么你 netty 的源码也看不懂的。netty 源码看不懂,那么 bbo 的源码也是看不懂的。
看明白了么?这些技术都是一换扣着一换的。如果你想要后续学习更加快速,那么你就必须把最基础的东西学明白了。如果连最基础的东西都没学明白,就直接去学其他更复杂的东西,最后只会越来越难,最终逃脱不了放弃的命运。
读到了这里,我相信你也对集合的重要性有了不一样的认识。那么接下来一段时间,就让我和你一起来深入学学集合源码吧。如果觉得读了有用,那么请给我一个赞吧。你们的赞是我继续写下去的动力!
G. 这几个大数据GitHub项目,太强了吧
大家好,我是 梦想家 Alex 。我们都知道 github 对于程序员们而言,就是一个巨大的“聚宝盆”,上面不仅有很多优质的开源项目,还有很多热爱开源分享的开发者。但如何从浩如烟海的宝藏中,筛选出适合自己的优质项目呢?本期内容,我就为大家推荐几个我认为还不错的大数据学习必备的 牛 X 项目,希望大家看完有所收获。
首推 heiying 的 BigData-Notes,该项目目前已经有高达 10.2K 的star,正如该仓库的介绍上简短几个字:大数据入门指南。这个项目也是我认为目前 最适合初学者学习和参考的项目 。
为什么说这个项目适合大数据初学者呢,可以通过观察项目的介绍文档,该项目包含了大数据学习必须要掌握的几种组件,包括 Hadoop,Hive,Spark,Flink,Kafka,Zookeeper,Flume,Sqoop,Azkaban,以及 Scala 函数式编程语言的教程 ,可谓是非常的系统全面
我们再借助谷歌插件 Octotree 观察项目的结构,可以看到该项目主要分为 code,notes,pictures,resources 四个目录
其中 code 目录主要用来存放各个组件使用相关的代码,正如统计的结果一样,这个项目中 Java 代码占了 94.8%,Scala 占了 5.2%,所以对于喜欢用 Java 编写代码的小伙伴们来说,这是一个不容错过的宝藏学习机会。
notes 部分主要存放相关组件的介绍和使用文档,其中 installation 子目录主要存放了相关组件编译,以及在Linux环境下各个组件的安装,单机/集群环境搭建的教程,我看过了内容,介绍的非常清晰详细。
另外两个目录 pictures 和 resources 就不做过多介绍了,一个是存放相关的图片教程,另一个是存放编写的代码中所需要用到的文本文件。
这个项目同样给力,是由 BAT 高级大数据架构师 王知无 创建的,该项目目前也已经斩获高达 5.2k star,是为数不多, 集基础学习和进阶实战 于一体的优质项目。
该项目按照大数据不同阶段的学习,所列举不同的文章干货
大数据开发基础篇
大数据框架学习篇
大数据开发实战进阶篇
大数据开发面试篇
从不同的分类足以见 王老师 的用心。同时,王知无前辈也是 51CTO 上的认证讲师,来看看官方的介绍 。
相信很多同学在学习大数据的过程中,不清楚 Java 需要学习哪些内容,掌握到什么程度,这个时候完全可以借鉴王老师的这个仓库内容。
同时,学习这个仓库的内容,可以学习到作者作为架构师本身对于 JVM,分布式理论和基础,大数据框架基石之网路通信Netty,以及各个框架的源码学习,可谓“ 真.宝藏仓库 ”
除了基础的理论学习以外,还有大量实战性的内容可以借鉴参考
以及大量的面试题,还有自己从零到大数据专家一路走来的心路历程,学习路径指南,和自己对于技术学习的一些深入思考,相信大家拜读过后一定能收获满满,
这个项目比较特殊,是一个国外开发者开源的项目,英文翻译过来的意思是“很棒的大数据”,实际上呢~他列举的是很多很棒的大数据框架、资源和其他很棒的精选列表。灵感来自 awesome-php 、 awesome-python 、 awesome-ruby 、 hadoopecosystemtable 和 big-data 。目前也已经斩获 10.2K 的 star,非常强势。
为了方便阅读,我将其全部翻译成中文进行展示。
我们跳转到 分布式编程,可以看到很多我们熟悉的技术,例如 Flink,Spark,Pig,MapRece 等等 ....
亦或者“分布式文件系统”,我们所熟知的 HDFS,Ku,GFS ...
点击对应的链接,可以跳转到对应的官方介绍页,方便我们减少搜索成本,快速了解不同领域大数据常用的技术组件,为我们之后做技术调研省了很多的时间。
让我厚颜无耻的夹带一下“私货”。这是我在今年年初的时候,创建的一个仓库,目前也已经有了快 200 的star 。从资历和star的数量显然不能跟前面几个大佬相比,但却是我第一次花费了大量精力,将一个项目像孩子一样进行“培养”。
为了设计一个好看的图标,还花了不少的精力。设置不同媒体平台的徽标设计,还参考了像 JavaGuide 这样的头部项目,也算是在亲力亲为的这个过程中,学到了不少东西。
可以放点内容给大家show一下
另外,我还开设了“福利”专栏,将自己学习过程中收集到的学习干货毫无保留地分享给大家,方便大家获取。
显而易见,这个是专注于 flink 学习的开源项目,其中的内容包含Flink 入门、概念、原理、实战、性能调优、源码解析等等,目前已经斩获了 10.5k 的 star,非常强势。
其维护的开发人员也是非常用心负责,一路跟随 flink 的版本,不停的在维护更新 。
同时,主要维护者 zisheng 还将 flink 的研究做到了极致,不仅有 flink 成体系的博客链接,还有对应的源码系列。
还自己创建了专栏《从1到100深入学习Flink》,并将大家学习过程中有疑惑的地方解决过程统一记录下来,方便有需要的同学查看。虽然是付费的星球专享,但我觉得是真的值!感兴趣的话大家可以自行去了解。
H. 如何实现Netty框架中服务器端的消息推送
netty框架是用在服务器端,客户端是嵌入式编程,通过自定义的tcp通信协议进行连接的,现在需求是这样的,服务器端只是用来和客户端进行通信,现在有第三方如微信端进行支付成功后在数据库里生成了一条数据,表示要往某个客户端发送指令,以下两种方式可供参考:1、微信端生成通讯指令后调用TCP端的接口(负责通讯程序和数据库交互的),在接口程序中通过定义Socket连到通讯程序服务器端,根据通道编号去发送,但是这种会导致服务器端的tcp客户端连接变得更多。
2、直接在netty框架中定义了scheleAtF。
当然也可借助第三方工具来完成推送。例如极光推送,极光推送具有以下功能:
1、多种消息类型
开发者可以轻松地通过极光发送各个移动平台的系统通知,还可以在控制台编辑多种富文本展示模板; 极光还提供自定义消息的透传,客户端接到消息内容后根据自己的逻辑自由处理。
2、用户和推送统计
完整的消息生命周期查询,并且可以形成“推送报表”与“用户统计报表”呈现给开发者,用来观察推送的效果和应用发展趋势。
3、短信补充
通过极光后台推送APP通知消息,对于一些重要又不能遗漏的信息可以调用极光短信的后台对未收到的客户端发送短信通知,保证消息的可靠性。
4、A/B 测试
合理的推送能够激活用户,提高用户粘性,使用A/B分组测试的科学方法,根据测试反馈的结果,帮助开发者选择最优化的推送方案。
5、极光推送安全包
为金融、新闻、政务及其他对推送安全要求极高的客户提供安全严谨、稳定可靠的信息推送解决方案
6、可定制的私有云
对于安全性要求更高,希望推送数据和系统存储在自己服务器的客户,及个性化需求需要定制开发的,性能更高要求的,或者想拥有自己推送平台的甚至要求源码授权二次开发的开发者,极光提供全功能的私有云解决方案。
深圳市和讯华谷信息技术有限公司(极光 Aurora Mobile,纳斯达克股票代码:JG)成立于2011年,是中国领先的开发者服务提供商,专注于为开发者提供稳定高效的消息推送、一键认证以及流量变现等服务,助力开发者的运营、增长与变现。同时,极光的行业应用已经拓展至市场洞察、金融风控与商业地理服务,助力各行各业优化决策、提升效率。