资讯详情

当我看源码的时候,我在想什么?

引言

斯坦福大学, 乔布斯做了我认为他最精彩的演讲之一 (另一种可能是iphone新闻发布会)。他讲了第一个故事 "connecting the dots"

你不能充满预见地把生活的点点滴滴联系起来;只有当你回头看的时候,你才会发现这些点点滴滴之间的联系。因此,你应该坚信,你现在所经历的将在你未来的生活中串联起来。你必须相信一些事情,你的直觉、命运、生活和命运……正是这种信念让我不失希望,让我的生活与众不同。

连接生命的点滴是什么?

我的理解:一个人的能力还在上升, 当模式和视野不够广阔时,他需要关注当前的事情,并将一切都达到当时能力的极限。也许当时没有那么大的成就感,但"蓦然回首,那人却在昏暗的灯光下"。

十年前刚进入IT当我在这个行业的时候,我是一个非常普通的工程师,我的头不聪明。我的工作总是没有要领。我的同学智商很高。他基本上会写一次代码。我必须花很长时间来消化和吸收它。我质疑我是否能在这个行业生存。

没无选择,只能勤能补拙,笨鸟先飞, 遇到问题时, 我都抱着死咬不放的心态去寻找最好的解决方案, 洗澡、睡觉、吃饭甚至上厕所都会很自然,"追"源代码也成为我程序生活的一部分。

读了很多源代码,和大家分享一些追源代码对我的职业影响很大的经验。

Druid 连接池

这是我2013年第一次重构彩票计算服务。原代码是C#版本每次计算订单金额需要2次~很多用户反馈体验很差(因为奖金很晚)三个小时。

当时采用druid作为新项目的数据库连接池,上线后重构效果明显,性能提升到原来的10倍。

不过,有一个问题是:每天第一次请求,就报链接错误。

当时不怎么看源码,就直接给了。druid作者温少(也是fastjson作者)发邮件:

温少给我回了邮件,我立即打开源码, 发现我配置数据库连接池的心跳有问题。

核心点是连接池需要每隔一段时间发送心跳包oracle为了节约资源,服务器, 每隔一段时间就会关闭长写的连接就会关闭。因此,客户端必须每隔一段时间将心跳包发送到服务端。

这次简单的源代码之旅给了我长期的激励,也让我更加关注技术背后的原则。

  • 在精神层面,问别人问题会上瘾

  • 了解连接池的实现原理:druid基于数组实现,后来使用jedis连接池基于commons-pool实现,netty连接池实现FixChannelPool

  • 在架构层面,客户端和服务端需要考虑心跳:定期任务线程发送心跳包(类似于druid连接池发送心跳机制),netty中的idleStateHandler

Cobar分库中间件

还是在2013年,接触cobar给我带来的震简直无法复加。

当时互联网大潮涌来, 各大互联网公司的数据爆炸式增长, 我曾在javaeye我看到淘宝订单技术人员分享分库表的帖子。如果我得到了宝藏,我想从字里行间探索分库表的解决方案。不幸的是,由于篇幅有限,文本总是文本,总是感到痒。

没曾想到,cobar横空出生(开源),用navicat配置cobar信息可以像连单一一样使用mysql同样,数据将均匀分布到多个数据库中。

**对于我当时技术思维薄弱的人来说,这就像三体水滴遇到人类舰队一样。**

由于对分库分表原理的渴望,我没有好的学习方法,花了大约三个月的时间,我把整个cobar复制核心代码一次。

智商真的不够,体力来凑。

但是光有体力真的不够,经常会陷入怀疑,怎么也看不懂,那也看不懂。

边抄代码边学习似乎没有那么明显的进步。

嗯,一定要找个突破口:

当时我做了一个决定,我想把它拿走cobar剥离网络通信层,深刻理解使用本土nio实现通信模式。

剥离的过程也很痛苦,但我有一个目标,不像无头苍蝇,然后我有了人生中的第一个github项目。

在写nio在工程的同时,我也学到了maven的asemble现在听起来很简单,但在2013年tomcat部署webapp war包模式流行,让我眼前一亮。

后来在2018年参与的直播答题系统中,采用了和cobar包装部署模式相同。

与此同时,我第一次理解了内存池的概念,后来netty里面ByteBuf也可以池化。这是一个非常实用的概念。

追cobar的过程中, 好像我和阿里的大牛面对面交流。虽然我的资质很差,但大牛认真地教我,耐心地回答我。 感谢打通我的任督二脉。

毫不夸张地说,这是我生命中最重要的开源项目。

后来在艺龙网工作,和艺龙分布式数据库的架构师沟通的时候,因为有学习cobar理解他的想法会很快, 后来,我到了数据中间件事务bug,提交给他修改。

再后来,cobar阿里云没有消亡。drds使用了cobar民间中间部件的分析器mycat大部分也用过cobar的源码, 当然mycat质量有待商榷。

metaq消息队列

2015年加入神州专车,当时神州专车正处于上升期。各系统瓶颈较大。

metaq故事精彩,相关知识点多。

当时我们使用的metaq是庄晓丹在github开源版。

2016年初,我checkout了metaq了解业务的源代码,深入了解业务metaq的机制。

集群消费

首先,影响我思维观念的概念是集群消费。我最初使用它activemq,rabbitmq,使用点对点模型, 每天新闻接近百万级也可以凑合处理。但假如不同的服务想要处理同样的消息, 点对点模型只能重复发送,看起来很好ugly。

在集群消费模式下,每个消息只会分发到一台机器上。不同的消费者有不同的组名,但他们可以消费相同的消息。对我来说,这是一个意识形态上的突破,metaq借鉴了kafka的模型

我经常想:"项目实现良好,技术理念创新更为重要",为什么许多先进的概念是由外国公司提出的, 这一切都值得我们深思。

在中国专车场景下,订单系统可以发送订单状态转换信息,可以由订单子系统、大数据团队或订单发送系统消费。不同的系统有不同的消费者group,消费进度offset存储在zk里面。多么精致的设计啊。我不禁感慨!

在专车推送系统中使用广播消息(经典模型)

有幸与架构部同事沟通专车推送是如何设计的。

一开始,他们使用极光推送,后来由于定制的需要,决定自主研究。

一开始,我的问题是:"如何将信息推送到每个连接的专车上?app呢?"。

他们给我的答案很简单:"采用metaq该功能可以通过广播模式实现"。

  • 业务系统将消息推送到metaq(rocketmq)

  • 消费metaq广播消息的tcp网关获取推送消息

  • tcp网关获取连接到服务器的网关channel连接引用,推送数据app

后来,我仔细研究了京麦tcp网关的设计,关于推送方面的实现和我们当初的实现非常相似,文章里有一句话:

在线通知是通过的MQ广播机制到所有服务器,所有服务器收到消息后,获得当前服务器持有的所有信息Session会话,数据广播下行通知

所以,技术的实现很多是相通的。

2018年,我服务的一家电子商务公司开发了直播答题系统,需要实现推送题目的功能。我花了大约3天的时间帮忙tcp网关研发学生实现了相关功能。

一场zk一系列由崩溃引起的知识点

我们也都知道metaq依赖zookeeper,metaq在zk里要保存。

突然有一天,整辆专车zk集群down掉了。架构负责人修改了。zk的jvm问题似乎解决了参数。

但问题随之而来。

metaq共享一组服务治理zk集群合适吗?

来公司后,阅读metaq在源码之后,我发现了metaq消费者多的时候,开始的时候会经常争抢。此外,消费过程也将是正确的offset频繁修改topic数量增多,partition当数量增加时,metaq对zk其实有写作的压力。

后来,神州的架构部确实是metaq的zk集群和服务治理zk集群分开了。当然,迁移也很熟练。目前不重复。

zk神州系统注册中心有瓶颈吗?

zk存储各种服务ip以及对外暴露的方法。

随着专车系统的服务越来越多,zk你真的能忍受吗?公司领导邀请京东研发团队的学生回答您的问题。

京东注册中心的服务信息是什么?

京东的学生回答是: mysql。

我在旁边听得目瞪口呆,什么?mysql!

后来,淘宝中间件博客发表了一篇文章:为什么阿里巴巴不用? ZooKeeper 做服务发现?

文章的结论是:

当数据中心服务超过一定数量时 (服务规模=F{服务pub数,服务sub数})作为注册中心 ZooKeeper 很快就会像下图中的驴子一样不堪重负

可以使用 ZooKeeper,但是大数据请向左,而交易则向右,分布式协调向左,服务发现向右。

后来,我参看了张开涛写的一篇博客,以及在github上零落的jsf代码, 手撸了一个基于AP模型,客户端使用berkeyDb的注册中心。

我们也知道2019年,阿里在spring cloud生态上发力,nacos也诞生了,nacos同时支持AP和CP两种模型。

开源世界的选择更有多样性了。

当我们使用zookeeper的时候,一定要注意集群规模和使用场景。

神州架构团队:metaq重构之旅

说实话,我挺佩服神州架构团队的。

核心成员也没有那么多,但还是有进取精神的。一个中间件的重构需要领导者的前瞻性和勇气。

虽然,我并不完全知道神州架构团队为什么要去重构metaq,但可以从下面几点来说一下:

metaq的网络通讯框架

metaq的通讯框架是庄晓周自研的。

在神州专车在使用过程中,确实也发生过服务假死的情况,需要重启metaq服务。淘宝的一位架构师加入了神州架构团队开始从网络通讯层着手提升metaq的稳定性,将网络通讯层替换为netty。

当然替换的过程并非一帆风顺,得益于庄晓丹的代码可读性,替换后,就在测试环境小规模使用了。

突然,我惊奇的发现我的测试服务器连接数暴增,可能的原因是metaq重构网络处理连接这块可能还待优化,后续这位架构师很快解决了问题。

我很佩服高水平的架构师。

消息管理的自动化

最开始metaq有一个简单的管理系统,申请主题后,还需要运维修改配置重启服务。

后续的做法是:做一个消息管理平台,各个业务线申请主题,分区都是通过这一个平台,并且可以监控消息服务器的生产消费情况。

我并不是metaq重构的参与者,但我内心触动的点在于: 

metaq vs rocketmq

很多同学在用rocketmq, 有一些我认为很重要的点,供大家思考。

  • rocketmq为什么将所有的数据存储在一个commitlog里,metaq多partition模式有瓶颈么?

  • rocketmq为什么要使用推拉结合的模式?相比metaq的拉模式有什么优势吗?

  • 阿里的ons系统有任意时延的消息,为什么rocketmq只支持固定的延迟消息。可否在rocketmq的基础上实现任意时延?可以参考 如何在MQ中实现支持任意延迟的消息?

  • rocketmq的控制台,你认为好用吗?能否支持多集群的模式,你要是设计该如何实现。

任务调度系统设计

xxljob(许雪里) , crane(美团),  schedulex(阿里云),这些都是任务调度系统。

时间已经到了2018年,技术部需要一个可靠的任务调度系统。最开始租赁团队使用的是xxljob,但不知道怎么搞的,老是使用有问题。

第一阶段: 坦率的讲,我看了xxljob的源码后,第一直觉是:"简单"。因为作者已经最大限度的将这个系统做成了开箱即用,去掉了quartz的集群调度模式,自研基于数据库的调度器。

但当前公司已经有自研的rpc服务,让其他团队配合xxljob添加jobhandler好像也不太容易。

所以最开始, 我修改了调度器的代码,使用了公司的rpc来执行。只不过将xxljob的jobHandler替换为公司的rpc的serviceId。

运行起来还行,能满足公司要求。

第二阶段: 为什么我想再优化一波?

因为当前的rpc调度是同步执行,xxljob的调度基于数据库锁,这两方面都有瓶颈。我想向大公司的同事取经。

所以,我找到了美团的朋友,向他请教他们公司是如何设计任务调度系统。

他给我演示了crane的执行过程,因为考虑到保密以及安全,他仅仅给我讲了其中的原理。我根据他的描述做了如下架构设计:

第三阶段: 光有架构设计没用,工程上如何实现呢?

我必须吃下定心丸,当前的设计模式确实可行。

我想到了阿里云的schedulex。假如我是一名阿里云的开发者,我怎么设计一个好的任务调度系统,支持每天千亿级别的任务调度。

我翻看schedulex的开放文档,以及schedulex client的源码。想不到真的是宝藏。

schedulex client里包含如下几点:

  • rpc调用类似rocketmq remoting

  • 任务调度通过rpc触发,任务调度有统一的注册中心(nameserver模式)

  • 支持多端口启动(若当前端口启动失败)

  • 任务执行和任务调度/回调线程池隔离

吃下了定心丸,无非是工程的实现了。

重构的效果还不错,技术同事们对当前的系统还算比较满意。

但我深知,当前的系统还有两个待解决的问题:

  • 任务调度重度依赖数据库, 当真正有10万,20万级别的任务的时候,任务的分配以及调度的触发肯定会有瓶颈。

  • 当前系统是容器的时候,是否可以正常使用。

于是,我在今年年初在github上写下了自己相对完整的一个任务调度系统,将quartz替换成了时间轮,将任务触发改成服务端推送模式。

在写任务调度的过程中, 实际上是不断超越自己的过程,我想把系统做成一个可以和行业对标的作品,就必须去向业界最先进的技术产品学习。

标签: cp114差压变送器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台