一、产生背景
hulk框架是在“好看视频”服务端的go服务化架构升级背景下产生的。
1.1 为什么要做架构升级?当前架构面临哪些问题?
好看视频初期因业务需要快速、灵活的开发迭代,采⽤PHP作为开发语⾔实现后端服务,前期取得了⽐较好的开发迭代效果。但随着好看业务快速发展,服务端的项⽬(接⼝、代码等)急速膨胀,类单体的PHP架构在多个⽅⾯遇到了瓶颈和问题,主要体现在以下⼏个⽅⾯:
1.2 为什么不直接基于GDP2 ?
好看的go服务化升级工作开展时,GDP2还未正式发布,这也是其中一个因素。
1.3 hulk与gdp2能⼒对照
下⾯从三个⽅⾯与gdp2做⼀个简单的对照,初步了解hulk的整体能⼒及与gdp2的⼀些差异。
1.3.1 web server能⼒
1.3.2 功能/组件
1.3.3 框架周边及基础设施
NOTE:
1. 好看在做go化时,也调研了开源社区⾥⽐较优秀的⼀些⼯具系统和⽅案并引⼊, hulk中默认添加了对这些基础设施的集成;
1.3.4 对照总结
1.很多基础能⼒,hulk是复⽤gdp的,如:bns、net、codec等;
2.⼀些通⽤/扩展组件,hulk按照业务需求场景,进⾏⼆次封装和增强,如:httpserver、ral、redis、mysql等;
3.对于gdp⽬前没有⽀持的⼀些业务需求,进⾏开发集成,如:定时任务、配置中⼼、服务治理等;
4.参考业界开源实践,引入了一些新的基础设施:如prometheus+grafana集群、sentry集群、故障定位系统等;
GDP2由几十个模块共同构成,由于时间有限,可能个别功能点的对照有偏差。
二、了解hulk
2.1 设计思路
2.2 框架结构
2.2.1 基础组件
日志组件:默认支持与PHP兼容的打印格式(用于配置sia监控和报警),同时也兼容ftrace接入的格式(日志查询和问题定位);
云原生监控:默认支持prometheus,对所有接口请求、redis、ral等远程调用进行多维度的metrics采集,并通过grafana展示;
配置中心:通过配置中心,可以实时下发并生效配置。目前支持Apollo/iConf,支持功能包括-版本管理、热发布、灰度发布、权限管理、审核与审计等;
事件追踪/定位:借助sentry,对于一些故障,我们可以秒级感知。hulk在异常信息中保存了比较完整的现场信息-如调用栈、request、集群和实例信息等,通过这些信息,可以直接定位问题的原因;
2.2.2 通用组件
ral组件:hulk的ral模块封装了GDP2的ral主体功能,同时,对ral进行了增强- a) 提供了通过字符串而非文件来进行ral初始化和ral懒加载功能;b) 提供了多个hook能力,如prometheus的监控信息采集,熔断、降级等;
服务治理:框架的服务治理能力是基于Sentinel (阿里开源的高可用流量防护组件)和配置中心来构建的,主要以流量为切入点,从限流、流量整形、熔断、降级等多个维度来协助保障微服务的稳定性,并提供动态控制能力;
协程池:a) 可以自动调度海量协程,复用goroutines,减少gc,b) 可以优雅处理 panic,防止程序崩溃 c) 提供了:任务提交、获取运行中的 goroutine 数量、封装了WaitGroup支持协程任务编排等功能;
事件通知:框架与如流做了集成。用户将robot token配置在项目里,就可以直接使用ruliu组件向指定的如流群发送报警/通告。如流组件结合sentry,可以让我们第一时间知道程序出了问题并快速定位到问题;
2.2.3 扩展组件
2.2.4 http server
logger_middleware:用于记录http的请求、响应、耗时等信息,同时支持实时修改日志打印策略-如按idc/ip/百分比/uid/cuid等维度打印;
timer_middleware:用于http请求的监控埋点,可以输出可用性、tp99、流量、平响、错误码等metrics,维度包括服务级/idc/instance等;
recover_middleware:用于捕获http 请求链路中的painc事件,并可自定义panic handler逻辑,如通过结合sentry和如流,可以实时感知并定位panic事件;
flow_control_middleware:接口限流组件,可以通过配置中心或管理接口,对接口按idc/instance维度进行限流;
timeout_middleware:通过该middleware或与配置中心结合使用,可以对接口按idc维度进行超时控制;
其他middleware可以查看hulk文档
(如-internal_user_middleware、jager_opentracing_middleware、thirdparty_auth_middleware、b2logger_middleware等)
管理控制接口:如健康检查接口,服务治理-熔断、限流、降级接口,metrics接口,线上实例性能调试接口等;
2.3 框架生态
标准目录规范:避免各个项目结构不统一,减少项目维护难度和工作量;
代码生成器:基于hulk框架、标准目录规范、组件使用规范的代码生成器,目的是减少通用模块/组件使用不规范,解决通用流程编码、处理不一致的问题;
hklib:好看的通用lib库,提供了一些的通用功能(也包含了很多PHP转go过程中的一些orp通用/基础的函数/功能),也提供了50+对中台服务的调用client,减少重复代码,提升研发效率,提升可维护性;
基础设施:prometheus+thanos集群、sentry服务、apollo集群、pyroscope性能分析平台等;
iconf:好看自研配置中心,能力在对齐开源的Apollo之外,还增加/增强了一些功能,如-key维度的发布、更安全的配置获取、更简洁的操作页面、类分级发布等;
artemis:服务可视化与故障智能定位系统,可以在该系统中看到服务的部署架构、服务内部调用链、多维度细粒度的近实时监控和关键日志。在发生可用性故障时,一些故障问题可以秒级的定位到原因和具体代码;
2.4 框架应用情况
资源和性能收益,很大一部分要归属于PHP->Go的技术栈切换;而框架为服务应用相应技术栈特性提供了便捷和高效的方式。
2.4 hulk服务架构
框架中个各功能组件都是围绕业务各个场景和需求的,在业务逻辑中能够比较便捷的使用相关功能组件;
这些组件在启用后,也会与相应的基础设施进行交互融合,共同支撑服务的高效、可控和稳定的运行;
hulk组件初始化及与周边基础设施的集成,基本都可以通过环境变量/配置文件来完成。
三、框架能力与应用
3.1 如何提升代码质量?
代码质量会直接影响代码维护成本; 代码质量会影响程序出bug的概率; 代码质量会影响程序运行效率;
3.1.1 规范代码组织结构
降低项目维护成本,提升研发效率。
通过标准目录规范,定义通用(http服务)的项目layout,避免出现每人一种或多种layout,最终项目结构“百花齐放”的现象;
通过代码生成器,帮助开发者生成项目模板,对初始化流程,各目录/文件的使用进行潜在约定;
3.1.2 编码规范和静态检查
提升代码可读性,减少低级代码bug
遵循百度Go编码规范+业务编码补充规范;
使用GDP的代码检查工具:go_fmt、goc;
3.1.3 配套的压测和性能分析平台
确定服务的压力边界,发现潜在的性能问题。
压测和性能测试平台(测试环境):nGrinder
程序性能分析平台:pyroscope。可以通过hulk自集成的管理接口,实时打开或关闭线上实例的“continuous-prof”功能,定位线上性能问题:
3.2 如何提升开发迭代速度?
如何让开发者专注于业务逻辑与实现? 如何让开发者快速响应并完成产品需求?
3.2.1 丰富的实用组件/功能
提升研发效率,避免试错,减少出错。
程序增强组件:增强的redis/mysql功能,增强的ral调用等。例-下图中的redis监控,其监控指标是由hulk redis组件自动采集计算的:
优秀的开源组件:sentry、prometheus+grafana、apollo、协程池等。例-prometheus+grafana:hulk框架默认支持prometheus,可以对服务的可用性、QPS、耗时、错误码等metrics自动计算收集:
丰富的http middleware。
3.2.2 配置化、低代码支持
减少代码的修改和上线,提升需求的响应和完成速度。
hulk框架中大部分组件可以通过环境变量/配置文件来初始化;
业务逻辑中的可变数据与配置,可以通过apollo/iconf实时下发和生效,无需代码修改和长流程上线。例-可以通过开箱即用的配置中心功能,实时下发并生效配置:
3.3 如何快速感知并定位问题?
开发者如何快速感知服务中的问题,严重问题如何实时感知?
开发者如何能从监控、日志、报警中获得详细的问题信息,以快速定位问题?
3.3.1 完善的事件追踪定位与通告能力
能够实时追踪开发者自定义的错误并通告
实时事件追踪组件:sentry。hulk提供了开箱即用的sentry组件功能,可以像打印日志一样使用,sentry中的信息包含代码调用栈、上下文、自定义关键信息等:
通告组件:ruliu。一行token配置就可以开启如流功能,可以将一些需要立即关注的信息实时打到如流群里,同时还可以和sentry结合,实现异常问题实时感知和定位:
3.3.2 prometheus+sia监控支持
通过prometheus与noah的互补,支持多维度全方位监控,能够获得更多的服务稳定性相关信息
prometheus为开发者提供灵活的多维度的业务监控信息;
sia可以为开发者提供基于日志的采集的服务稳定指标和容器、网络等资源维度监控信息;
3.3.3 ftrace日志查询与分析功能
hulk默认支持ftrace平台的日志格式
通过ftrace,可以便捷高效的查询用户维度的日志信息;
通过pdo2命令,可以检索查询自定义规则的日志信息;
3.4 基于hulk的服务可视化和故障智能定位系统
3.4.1 服务部署架构
通过实例列表,可以获取服务的idc列表、instance列表和详情,并提供了便捷高效的调试入口和登录指令:
3.4.2 近实时多维度监控
artemis提供的近实时监控,能够提供更多维度信息,这些维度是sia和prometheus无法提供的,如:
某个URI下面的某个下游(或下游实例)RAL的QPS、耗时、可用性;
某个服务实例实例的URI或RAL的监控信息;
3.4.3 关键日志
由于与hulk的深度集成,在业务代码中打印warning级别以上的日志时,artemis能拿到更多的日志信息,如-各维度信息、调用栈、上下文等:
3.4.4 服务调用链
在hulk框架的协助下,artemis还可以获取到URI及URI所依赖的RAL调用信息,由此可以构建出请求调用链,并实时展示调用链上的相关metrics信息:
不同颜色的链路代表不同的可用性:红色-1个9及以下,黄色-2个9,蓝色-3个9,灰色-4个9。通过服务调用链,可以非常直观的看到服务里,哪个接口有问题,还可以看到哪些下游影响了这个接口的可用性。
3.4.5 使用案例
通过与报警系统的联动,可以在发生报警的第一时间,在artemis系统中找到受影响的服务及URI,确定是否是下游引起,错误是什么,哪一行代码报了错等,以下是一个artemis的实际应用示例。
四、总结
五、附录 (外网不可访问)
1. 框架及使⽤⽂档:http://hulk-go.baidu-int.com/
2. hulk底层是基于GDP2的,了解gdp也更有助于了解hulk:http://gdp.baidu-int.com/
会吹牛逼真的很重要
关于堆栈的讲解(我见过的最经典的)
写出高效代码的12条建议