基于Sermant聊聊源码阅读方法论
背景
有读者问我能不能总结一下源码阅读方法论。
其实我这个人最不擅长的就是方法论,而且我认为每个人都有自己的方法,很多东西只能靠自己悟,没有啥普适的方法论,比如每个人的DDD都不一样。但是想了想还是挤时间总结了一下,不知道能否对大家有帮助。
最近正好工作中用到了Sermant这个组件,所以分享一下我如何打算分析这个组件。
这个组件其实挺适合做无侵入服务治理的二开脚手架,不一定要用里面的所有功能,可以基于这个框架做很多事情。
一、前期准备
1、读官方文档
简介
基于Java字节码增强技术的无代理的服务网格,实现各种服务治理能力。
能力
文档中将Sermant的服务治理能力分为几个模块。
服务注册发现和实时配置:
- 无侵入接入配置中心;
- 无侵入接入和切换注册中心;
限流降级和可服务性:
- 流控,支持限流、熔断、隔离仓、错误注入与重试能力;
- 无损上下线,提供预热和延迟下线机制;
- 离群实例摘除,检测应用实例的可用性,并对异常的应用实例进行摘除操作;
应用流量路由:
- 负载均衡:无侵入动态修改宿主应用的负载均衡策略 ;
- 标签路由:支持流量匹配、标签匹配、流量染色三种路由规则;
- 流量标签透传:流量染色;
应用可观测:
- 监控:采集各种metrics,暴露12345端口给Prometheus拉取;
- 服务可见性:上报接口契约和血缘关系(接口依赖);
异地多活和容灾:
- 消息队列禁止消费;
- 数据库禁写;
总而言之,通过开发各种插件,可以对java应用进行无侵入增强。
架构
Sermant依赖3个组件:
- 配置中心:支持nacos、zookeeper、kie三种,Sermant javaagent可选择接入,提供动态配置能力;
- Sermant JavaAgent:增强宿主java应用,可选择上报数据给Sermant Backend;
- Sermant Backend:暴露6888端口,用于接收Sermant Agent上报数据;暴露8900端口,提供web ui展示部分Sermant Agent上报数据;
SermantAgent分为两层:
- 核心框架层,为各类插件提供基础服务;
- 插件层,各种服务治理插件;
2、选择版本
版本一般是X.Y.Z,小版本和修订版本都选最新,大版本看情况。
本次我选择2.0版本,虽然日常用的是1.x版本。
参考官方ReleaseNote,1.x到2.x没有什么不兼容升级,可以了解一下最新动态。
主要1.x接入配置中心,无法在Sermant Backend操作配置,不太方便。
另外官方提供了RoadMap,看看未来官方会提供什么能力。
3、快速开始
一般按照官方文档照做就行。
二、源码环境构建
1、工程结构
- sermant-agentcore:sermant javaagent核心框架;
- sermant-plugins:sermant javaagent的各种服务治理插件;
- sermant-common:为sermant-plugins中的插件服务以provided方式提供三方包,如fastjson;
- sermant-backend:即sermant后端,暴露6888端口接收agent数据,暴露8900端口提供dashboard展示;
- sermant-injector:基于k8s准入控制器特性,实现宿主应用自动挂载Sermant Agent,可忽略;
- report:代码覆盖率相关,可忽略;
对于每个plugin插件有两种子模块:
- plugin:定义增强点和增强逻辑,以provided方式引入宿主依赖;
- service:为增强逻辑提供高级服务,以provided方式引入plugin,可以以compile方式引入三方依赖;
sermant-package,用于打包构建sermant产物。
2、构建产物
主要看agent侧:
- common,对应sermant-common模块,将三方依赖打成一个jar;
- config,对应sermant-agentcore-config,配置文件;
- god,对应sermant-agentcore-god,这里面的类会加入到BootStrap顶层类加载器;
- core,对应sermant-agentcore-core,agent核心;
- implement,对应sermant-agentcore-implement,agent核心服务实现,如心跳、netty通讯、动态配置;
- pluginPackage,对应sermant-plugins,包含n个服务治理插件;
- sermant-agent.jar,javaagent,对应sermant-agentcore-premain
pluginPackage中每个plugin根据实际情况会有plugin和service。
3、本地启动
一般来说,一眼就能看出启动入口,否则根据产物->pom找入口。
对于Sermant Backend可以无参直接启动。
但2.x支持Backend操作配置中心,修改application.properties配置文件,使用ZooKepper作为配置中心,可以方便调试。
dynamic.config.namespace=sermant
dynamic.config.serverAddress=127.0.0.1:2181
dynamic.config.dynamicConfigType=ZOOKEEPER
对于Sermant JavaAgent需要采用远程Debug方式,业务项目可使用Sermant-examples官方案例。
其他配置参考快速开始。
java \
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 \
-javaagent:/path/to/sermant-agent.jar=serviceName=spring-flow-provider \
-jar /path/to/Sermant-examples/flowcontrol-demo/spring-cloud-demo/spring-provider/target/spring-provider.jar
配置流控规则(参考官方文档):
测试业务流控:
curl http://localhost:8003/flow
Rate Limited
三、源码阅读规划
1、问题
- sermant-agent如何设计类加载器;
- sermant-agent插件如何增强目标类;
- sermant-agent的基础能力如何实现,如无侵入接入配置中心;
- sermant-agent的各种服务治理特性如何实现,如流控、无损上下线;
- sermant-agent与sermant-backend如何通讯;
- sermant-backend如何分析和存储sermant-agent上报的数据;
2、拆解
我拆解的常见方式:
- 按客户端-服务端拆,先从自己熟悉的端入手,如Sermant对于业务开发更关注agent,要知道Sermant对于我业务代码的影响是什么;
- 按主-次拆,先从主干入手,主干是必要逻辑,其他都可以归类为特性,如:消息队列主要场景是普通消息,其他都归类为特性;SkyWalking/Sermant都是插件化架构,先看插件之外的东西;
- 按模块拆,如Nacos既能做配置中心也能做注册中心,可以分开看;
四、读代码
Sermant最核心的还是JavaAgent部分,所以从JavaAgent入口着手。
读代码看个人习惯,看多了其实都有自己的方法。
主要是将逻辑分块,开源项目一般代码分层结构都比较清晰。
针对关键点深入分析,细节放过,这个也看个人目标和经验,不好说。
主要看几个东西吧:
- 核心逻辑:这个是最重要的,帮助深入理解这个组件,不光会用,出问题好查;(另外看多了要能知道啥是主干啥是分支,比如默认配置未开启的特性都是分支)
- 设计模式:提升自己的代码水平,理解即可;
- 扩展点:用于二开;
- 异常流处理:这个在写文章的时候可能不会带出,因为文章是自上而下的很难说明异常处理逻辑,但是很多组件的异常处理方式可以借鉴,比如如何降级、如何流控、如何补偿;
另外我看代码不太打断点,除非是想快速定位一个问题,或者实在看不明白。
个人认为打断点看源码,一方面效率较低,另一方面不利于对框架整体思路的把握,容易陷进去。
转载自:https://juejin.cn/post/7393503669474099210