Categories
程式開發

微服务编程范式


目前很多互联网公司都采用微服务架构,微服务的优点和缺点被反复说到,这里不在重复赘述,只结合工作中的一些实践,说说要用微服务要注意的点,厚颜写做编程范式,其实就是一些具体实践而已。

原则(道)

原则是比较抽象的一个概念,简单说是一些指导意见,在不同的组之间可以共享,是为了实现一个共同的目的,必须遵守的一些规则,或者叫做规矩。

这些规则(或规矩)对我们开发过程中有一定的约束作用,不容置疑,必须遵守。如果发现有那个团队或者个人没有遵守,一定要及时纠正,否则,原则就没有任何存在的意义。

现在用的很广的一个原则是Heroku的 **12-Factor“** 原则。具体内容如下:

I. 基准代码一份基准代码,多份部署II. 依赖显式声明依赖关系III. 配置在环境中存储配置IV. 后端服务把后端服务当作附加资源V. 构建,发布,运行严格分离构建和运行VI. 进程以一个或多个无状态进程运行应用VII. 端口绑定通过端口绑定提供服务VIII. 并发通过进程模型进行扩展IX. 易处理快速启动和优雅终止可最大化健壮性X. 开发环境与线上环境等价尽可能的保持开发,预发布,线上环境相同XI. 日志把日志当作事件流XII. 管理进程后台管理任务当作一次性进程运行

在我们团队中有一些原则可以和大家分享:

不要为了用而用,程序猿(或者叫攻城狮)是最喜欢尝鲜的人,有了新技术出来,就想用。这无疑是优点,但是在工作中这样,就有可能给系统带来灾难。所以如果想用某项技术,必须充分调研之后,经过一系列的验证,才能引入。战略目标明确,业务部门愿景清晰。作为开发团队,可能很少关心业务团队的想法,这是很致命的。我们开发的东西,不是业务部门想要的,顾客想要一个吃饭的勺子,你给做了一个铁铲,铁铲做的再好又有什么用。服务之间调用必须使用HTTP/RESTful方案,不能引入其他方案。不是说其他方案不好,而是最好协议一致,一致的协议能够减少系统的复杂性和沟通成本。

标准(术)

标准的定义会比原则更加具体,有点类似于道和术、战略和战术的关系,不同的技术栈、不同的团队可能会制定不同的标准。

我们团队都是使用的是Java技术栈,所以标准大体上采用的是《阿里巴巴Java开发手册》“,有一部分内容作了修改,这里对孤尽表示感谢。这个手册脱胎于《Effective Java》和《代码简洁之道》,其中加入了孤尽在阿里的一些实践,所以对于Java栈的同学是比较适用的。我们使用的是Spring Cloud,服务之间的调用,必须使用Feign Client形式,指定这个标准是为了以后使用K8s时改动最小。页面与服务之间的调用,HTTP返回状态码都是200,在返回的数据中,定义具体的状态码,这个状态码参照HTTP状态码,同时定义一个子级状态码,用来具体定义业务情况。比如,状态码等于500表示服务异常,子级状态码等于5001,表示操作数据库异常等。监控系统、日志系统、任务调度等,如果需要,也要指定明确是标准。比如打印日志时,日志开头必须以6位数字开头,因为我们的日志系统与监控系统对接,6位数字能够定位到不同的系统、模块、业务,直接定位问题位置。不一而足(每个团队有每个团队具体的标准,这里就不一一列举了)。。。

这些标准,最好形成文档,放在知识库中。这样,团队的成员可以随时查看,有新人加入时,也能避免老员工口口相传,传错了指令。

有些架构师认为,原则和标准就是一个东西。就我来看,这两个粒度不同,对于大的团队,最好分开。因为大的团队,技术栈更加多样化,标准没有办法做到一致,但是原则可以做到不会脱离大框。对于小的团队,因为技术栈比较单一,有可能就是一个技术栈(就像我现在的团队),因为标准只有一个,就是对原则的细化,所以两者就是一个东西。

标准的另外一个作用,就是告诉团队成员怎么做是对的,怎么做是更好的方案,更加直白的表述是,按照标准进行开发,bug更少。

有了开发标准之后,就需要将标准推广到所有人,但是每个人的理解力和执行力是有偏差的,所以需要一些手段来快速推广。具体的方法有:DEMO(示例)、代码模板(脚手架)。

DEMO(示例)

软件开发是一个比较有技术壁垒的行业,一个新人(没有经验或者有经验刚加入新团队的人)想要快速了解老系统所使用的标准,是比较困难的,毕竟每家团队采用的标准都不是百分之百一致。比较简单的做法就是,提供新人DEMO示例,然后告诉他,“就照着这个做”。

对于有经验的新人,一定是先接受,然后在了解清楚之后,才会提出自己的一些看法,而不是一上来,就搬出自己以前的经验,全盘否定团队指定的标准。

代码模板(脚手架)

代码模板的作用实现一个服务的集成方案,经过有效可靠的裁剪和定制。在需要新建服务时,就使用这个方案,直接进行业务代码开发即可,所以也被称为脚手架,比如SpringBoot的Starter和AutoConfiguration。

前面说过,我们团队使用的是Java技术栈,基于SpringCloud开发,所以我们对SpringCloud进行封装,定义了几根通用的组件,比如定义了一个web-misc组件,引入这个组件,就能够实现,引入实现WebMvc,并且提供了统一的获取Metric信息的接口,统一的异常处理的ExceptionHandler等。

及时清理技术债务

虽然我们都是代码洁癖,但是有时候迫于时间压力、业务压力,我们不得不背负一些技术债务。

比如我们知道硬编码会破坏系统灵活性,但是明天就要上线,根本没有时间做配置型服务,所以只能硬编码到系统中,这就是技术债务。第二天系统上线,正常运行,如果这个时候把硬编码事情抛之脑后,这个债务就会产生利息,不知道哪天就会变成炸弹。

对于技术债务,我们团队的做法是做一个技术债务清单,设置超时提醒功能,限期修复。这个清单是公开的,每一项都注明了,是谁,因为什么,于什么时间,产生的技术债务,需要在什么时候修复。如果是临时特性或功能产生的债务,也需要注明特性或功能过期时间,由专人检查债务是否已经没有了。

微服务编程范式 1