当前位置: 首页 > 科技观察

技术负责人教你源码精髓

时间:2023-03-18 11:51:36 科技观察

前面提到了技术负责人的几个特点,今天想和大家分享的是,作为技术负责人,必须要懂得研究和引进技术。引入的前提必须是Hold。为什么叫抱?就是能够熟练使用它,深入理解它的结构和原理,能够分析它的核心源码。以学习Nacos为例。这次分享的是研究技术的方法,授之以渔。希望大家有所收获。当然也欢迎大家留言讨论更好的技巧。01官方文档,搭建demo使用很多人喜欢买书看别人的博客。其实都是剩菜,别人也看官方文档。作为一个合格的技术人员,尽量从源头上看,看官方文档,原汁原味,耐心看完。怎么看Nacos官方文档的流程就不说了。基本上就是遍历目录,然后按照官方的例子进行构建,了解它的基本功能。关注里面的架构设计和模型概念。02了解功能设计主线,确定研究主线,高维抽象功能模型阅读官方文档基本会用后,确定深入研究主线。Nacos不仅包括服务管理功能,还包括配置管理和元数据管理。看到这里,其实也能理解为什么Nacos会成为未来注册中心的趋势,因为它同时包含了注册中心和配置中心两套微服务。使用它可以节省一个配置中心。下图来自官方文档:图片来源:nacos官方文档本篇我们研究的主线是注册中心,所以只研究它是如何实现注册中心的。这时候,我们就得高维地看待它了。注册中心需要什么功能?这些功能是任何一个注册中心都需要实现的功能,必须要掌握清楚。显然,注册中心的一般功能模型包括:1.服务注册2.服务心跳保活3.服务下线(正常下线,异常下线)4.服务发现基本实现了以上四点,单个注册中心是实现了。那么如果考虑分布式的话,还需要设计它是如何实现CP/AP模式的。03下载源码,提取精华。许多人阅读源代码并学习源代码。他们常常读书是为了寂寞,寂寞是为了寂寞。看什么?1.源码看什么?看源码要看作者是怎么构造、设计、实现的,想想为什么要这样实现。只有通过源码看到了它的本质,才能真正读懂源码。否则,你看着一个西瓜吃了,它就没了,你就是吃瓜群众。反之,看源码,细化模型、原理、机制、设计模式、并发体验、网络体验、OS存储机制等,才是真正的读懂了源码,吸取了它的营养。2.源代码呢?除了技术积累和经验因素,方法也是很重要的一环。很多人没有看源码的经验。当他们看到源码复杂,代码很多的时候,一看就懵了,不知从何下手。先分享三个经验:(1)找源头,就是从源头入手。这从剧本上一般都能看出来。大多数中间件封装了启动脚本。您可以从启动脚本中找到启动类。让源码跑起来,然后调试验证。(2)只看主线代码。就是我们上面提取的功能模型。那些日志、统计分析、异常分支、非主线分支不要第一时间看。(3)先静态看源码,不要动态调试,调试容易卡在细节和各种分支上。静态看源码就是不断锻炼自己,让自己只看主线代码,跳过明显的分支,这样才能快速通过主线。实在有疑惑,再调试验证。我们来看看Nacos的源码,版本是1.4.2,分析一下我是怎么看的。(1)服务注册是如何实现的?如何保证高并发?客户端启动时会通过http请求发送注册请求,请求链接采用restful方式。服务端收到注册请求后,会将请求参数封装起来放入一个阻塞队列中,然后基于一个线程不断获取阻塞队列的信息,放入注册中心。可以看到高并发设计的一个关键点:异步。这里也可以对比扩展一下,zookeeper是怎么实现的呢?Eureka是如何实现的呢?这些实现之间的优缺点是什么?他们能做到高并发吗?它也是异步的吗?这些留给读者去探索。(2)服务注册中心是如何设计的?为什么要这样设计?以及如何防止多节点读写并发冲突?Nacos支持CP和AP模式。CP和AP不懂就是百度,这个简单的概念我就不普及了。①在AP模式下,是基于内存存储的,底层其实是一个doublemap结构。在CP模式下,数据存储在文件中。这里主要研究AP模式。因为在大多数场景下,我们的注册中心更适合AP模式。看到这个地图结构,有没有想过为什么要这样设计呢?命名空间的目的是什么?团体的目的是什么?如果有一定DevOps经验的同学知道,我们往往会有多套项目环境,比如开发环境、测试环境、预发布环境、线上环境。每个环境都部署一个注册中心不是很麻烦吗?所以这里命名空间的目的是为了使用同一个注册中心来隔离这些基于命名空间的不同环境。那么这个群的目的是什么?如果我们用过dubbo,就会知道这个概念和集群服务。有的时候我们的服务一开始是一个大的服务,但是随着业务的扩大,有的时候需要拆分成几个小的服务,这样才能设置成一个组。这些在设计时考虑了可扩展性。我们来看看官方文档的数据模型:图片来源:nacos官方文档②如何防止读写冲突?核心点:读写分离,使用copy-on-write方式提高高并发。即写的时候,复制一个老实例,修改复制的数据,修改后复制,直接读取老实例。读写分离模式避免了锁冲突,提高了高并发。看了Eureka源码,它的实现是基于多级缓存,然后缓存之间进行数据同步。时效性明显不如Nacos。这里还有一点需要思考,这里复制的是什么?如果是copy-on-write,把所有的数据都拷贝过来,显然内存太多了。这里我们研究一下官网的服务模型。service下的package是cluster,cluster是example。为什么会有集群的概念?大公司的同学会知道,为了容灾和高可用,一个服务可能部署在多个机房。比如一个服务可能在亦庄机房部署一个集群,兆威机房也有一个集群。这里可以看出nacos模型的设计非常巧妙,基本上考虑了很多点。图片来源:nacos官方文档我们也可以验证一下源码。可以看到Service下面封装了一个clusterMap。集群下,封装了具体的实例集合,画横线。所以这里的copy-on-write是复制这个实例所属的集群结构。我把核心代码截图了,先复制旧的实例,放到一个oldmap中。对老图进行一系列操作,比如下线一个实例,然后把结果放到ips中。最后,分配回新的服务实例集。可以看到里面有很多技巧,可以学习,以后设计中间件或者自己写代码的时候可以直接拿来用。(3)服务心跳如何保持存活?客户端每5s向服务端发送一次心跳,通过http请求调用发送给服务端。服务器启动健康检查任务,每5s检查一次。如果发现超过15s还没有收到心跳,则设置健康状态为false。如果超过30s没有收到心跳,则直接移除该实例。这里我们思考一个问题,服务器启动健康检查任务,如果是集群模式,是不是每个服务器都要判断?这会消耗性能吗?我们看到在健康检查任务中有这么一段代码,会根据服务名对哈希运算后的机器节点数取模,判断是否执行健康检查代码。也就是说,在集群模式下,无论启动多少个服务实例,通常只有一个节点执行任何服务的健康检查代码。但是你可能会觉得它是时效性的,如果其他节点再执行一次,影响不会太大吧?当然这里面还有一些细节可以深推。服务发现对时间有多敏感?(4)线下服务如何?如果超过30s没有收到心跳,则删除。上面我们知道,deregister调用其实就是我们自己的deregister方法:跟进看一下,发现delete方法也对服务进行了加锁,也就是说对于同一个服务做了修改,以防止并发。最后删除也是基于异步的性质,和注册逻辑类似。(5)客户端如何发现服务,服务修改是如何感知的?①客户端先从本地缓存中获取服务实例,如果为空则从服务端拉取。并启动定时任务定时更新服务器的最新实例信息。②服务端修改后,通过udp协议推送,一方面在udp推送的基础上提高了实时性,另一方面虽然udp可能会丢包,但是客户端的常规拉取可以用作封面。这个设计真的很巧妙。那么Nacos的CP模式是基于raft协议实现一致性的。还有就是它的配置中心架构是怎么设计的。限于篇幅,就不展开了。只要按照我的想法做一些研究。记得看源码,按照主线读,然后学习它的机制和原理。不要只看代码。3、摘取源码的精华看完源码,需要摘取精华的总结。下面是一些例子。你可以按照自己的逻辑去提炼精华,不断提炼精华,不断内化为自己的经验,这样技术才能得到质的提升。飞跃。维度核心点描述总结接口版本设计/nacos/v1/ns/instance设计接口时考虑版本设计模式代理模式DelegateConsistencyServiceImplNamingClientProxyDelegate根据临时节点是否为Distro选择一致性协议的具体实现,持久节点是raftClient代理工厂模式NacosFactory这个类统一提供创建ConfigService(配置中心服务)、NamingService(注册中心服务)和NamingMaintainService(注册中心实例运行服务)的实例化方法,并采用反射机制架构设计可扩展设计数据模型命名空间支持环境隔离服务分组服务实例支持集群高并发设计异步、读写分离、写时复制、缓存机制熟悉基本套路,考虑高并发时可以应用高可用设计来自client、server的心跳机制和多角度保证高可用机制。客户端重试机制、客户端本地缓存文件和故障转移机制、服务器集群、一致性协议(AP)分层架构设计。嗯,服务注册发现也不错,架构层次分明比如服务注册发现:Controller->ServiceManager->ConsistencyService中间件底层源码机制,高并发容器ArrayBlockingQueue,ConcurrentHashMap,大部分中间底层本质都是高并发容器,线程池,定时任务,网络,以及其余为具体业务。线程池ThreadPoolManager线程池生命周期管理、ThreadPoolExecutor定时任务ScheduledThreadPoolExecutor4.学以致用学了源码,吸取精华不是目的,学以致用才是目的。常见路径包括:参与开源社区、将自研中间件投入生产实践、对内分享经验、对外演讲分享等。学以致用才是根本!本文以Nacos的学习为例,将研究技术的方法与实践步骤进行分享;关于微服务架构,后续会有其他同学分享ServiceMesh,敬请期待!