项目SOA化

如何把项目SOA化系列之一:计划

背景

公司的项目,在设计之初其实就一定程度的引入了服务的概念,当时的出发点更多的是因为:团队协同和项目进度分期,不过还有一个重要的原因,是因为要完成的目标有点太大太虚,很多细节不可能一次性全部想到位,所以就采用了把大系统拆成一个一个的小系统来完成,这样来做,系统之间自然就产生了通信的必要性。

期初为了快速搭建原型和团队成员的技能分布,选择使用php作为开发语言。确实也在初期达到了快速开发的目的,拿到了一血后也踏上了小系统逐渐变大的不归路。系统和系统之间的通信使用的就是简单的http+cache,简单粗暴能运行,是当时的重要哲学。

工期的紧张,人员流动,再加上员工心态和情绪的波动等原因,映射在项目上就会成为功能缺失,代码质量下降,依赖混乱,抽象不足等。除此之外,开发人员毫无节制的重复发明服务,使前面说到的问题进一步放大,一度成为毫无解决希望的技术债务。

由于公司业务变更,团队大部分成员投入到了一个新项目的开发上,这给这个项目和我都留出了一个非常完美的空档期,在获得了领导的授权后,我调整状态,踏上了系统重构的大道,也就产生了该系列文章。

其实早在13年后半年,项目组开会时就已经提到了关于服务化的设想,无奈当时并没有如今这样好的条件,也就不了了之。经历了14年的php转java,项目soa的条件逐渐成熟,是时候大展身手了。

计划

依照前辈大神们的心得体会,需要在项目中首先确定一些有价值的业务进行SOA重构,什么叫有价值的?就是那些项目的核心模块么?

其实不全对,为了保证开门红,建议从项目中选择一些复杂度相对较低,重要度适中的一些模块来下刀,避免造成骑虎难下的尴尬局面,而且也可以更快的积累经验和信心,当然,也不要选择太简单太无所谓的模块来搞,这样既无法积累经验,也不利于团队推广。

那么我们该怎么选呢?我考虑了一下,决定以下面三个维度来作为选择的基准:

  • 重要度:■ ■ □ □ □
  • 复杂度:■ ■ □ □ □
  • 频度:■ ■ ■ □ □

确定了这个标准后,我又进一步给自己安排了一个重构流程:

  1. 从需求书中寻找服务,并依照基准分类
  2. 梳理服务之间的关系,确定哪些是原子服务,哪些是复合服务
  3. 设计服务接口,以及协议类型(RPC?REST?)
  4. 代码实现

技术选型

了解soa的童鞋,自然会问:你基于哪些技术来实现SOA?其实SOA的技术骨架也无非就是:服务发现,服务治理,数据通信等几大块,商业的解决方案中还会提供强大的服务总线,工作流等功能(这些仅代表我个人理解,不喜勿拍)。

相信关注我博客的朋友肯定知道我要使用的框架是什么,没错,就是dubbox,其细节请参看我博客中的相关文章

指标

我们引入dubbox的目标,不仅是改善系统间依赖的混乱局面,还要标准化一些开发流程,提升开发效率,提升系统的可用性,性能,可伸缩,扩展性,重用性等。

下面我们具体来定一些指标,由于缺乏经验和相关数据,所以列出的指标会过于笼统,不过有生于无嘛。

  1. 标准化服务开发流程,从流程视角杜绝服务的重复,以及确保服务质量;
  2. 提高服务的可用性,确保每个服务都有冗余,并提供针对应用的监控工具;
  3. 提高服务响应时间,根据实际的复杂度来度量,尽可能保证服务响应时间在100ms–500ms之间(不启用缓存的情况下);
  4. 提升代码的重用性,并尽可能降低代码的耦合度;
  5. 提升代码的质量,提供更完善的代码检测工具和流程。

如何把项目SOA化系列之二:业务梳理

好吧,按照计划,我们接下来要做的就是根据项目现有的功能,依照相关的标准抽离出相关的服务。

把这个任务根据我们公司的实际情况,还可以细分,不过不确定是否对大家有参考价值,但是为了记录下每一步重构流程,我还是坚持要写出来的,所以如果你觉得不耐烦,请移步到该系列其它文章,谢谢合作。

服务发现

首先,小弟花了三天的时间,把公司相关的项目文档和代码粗略的滤了一遍,方法简单粗暴,谈不上合理,但个人感觉还是有点用的,根据之前提到的基准,整理出了个文档,如下:

其中每个维度的满分为5(不建议选用过大的分值范围),粗略的解释一下每个分值的含义:

重要度:

1分:作用程度几乎可以不考虑

2分:出现问题不影响业务正常工作

3分:普通,出现问题允许在1天的时间内给予修复即可

4分:重要,不允许失效

5分:核心,不允许失效,且要保证高的执行效率

复杂度:

1分:简单的直接操作一张表,或表达为入职一个月的普通应届生就可完成的任务(这么说可能容易被拍)

2分:需要同时操作多张表,存在一对多关系的数据组合

3分:包含较多的业务逻辑,但全部操作都在同一个上下文中完成(单进程单线程)

4分:产生RPC调用

5分:使用了多线程

复用度:

1分:只有自己使用,这里的“自己”表示自身所在的单个系统中的个别操作使用

2分:自身所在的单个系统中不超过5个操作使用

3分:自身所在单个系统中超过5个操作使用

4分:2个以上的系统都使用

5分:可预见的所有系统都会使用

频度:

1分:偶尔会用,或叫几乎不用(其实大多数操作都属于这一类,又一次验证了二八定理)

2分:普通操作,但并非日常必须

3分:通用操作,正常用户日常会经常使用的

4分:热门操作,所有用户日常会经常使用的

5分:必经操作,所有用户一定会频繁使用的

类型:

原子:基础服务,可以理解为自包含,有明确边界的功能

复合:组合服务,需要由1个以上的原子服务组合出来的功能

以上打分并不是非常的严谨,只是争取做到了有个粗略的标准来区分服务的目的。

服务关系梳理

粗略的数了数,我们公司的在使用项目大概也有十四个之多,上一篇文章介绍过,由于初期设计时就考虑到了系统间的依赖,所以单独在某个项目自身上去发现服务,是不准确的,很可能A系统中的一些功能是依赖B系统的,这样上述的列表中就会有大量的重复内容,所以我们下一步需要做的,就是梳理服务之间的关系

既然要研究关系,视角就不能只局限在某个系统,而是应该上升到平台上,自嘲的说,我们团队现有的项目用”平台”二字有点小题大做,不过意思到了就行了,不要在意细节,咱们聊的是方法论。

其实在服务发现时,根据基准,就可以第一轮筛选出一部分较为合适的服务集合了,我们只需要把选中的服务的关系整理出来即可。依然采用图的方式,如下:

如何把项目SOA化系列之三:架构设计

已经到了这一步,进度还算比较快。只是悲剧的是,当我整理完项目调用关系后才“恍然大悟”,妈蛋,年前某个时间我已经做过一次这样的工作了。而且更夸张的是,那一次做的比现在还彻底,哇哈哈哈哈,我这种记性,也是醉了。值得庆幸的是,两次流程的大致方向还是一致的(不然就麻烦了,精神分裂~)。

言归正传,本来计划接着上一篇,直接开始写服务的详细设计呢,但是感觉还是缺少什么,应该就是对平台的整体设计规划吧。先上一张图:

图解:

  • 客户端和运营平台之间的通信统一基于Http的REST API,这类API尽可能保证完整业务逻辑,以粗颗粒度提供(意味着复用性较差)
  • Rest API内部会负责业务编排,以dubbo提供的高性能协议与运营平台中的数据应用服务进行通信
  • 数据应用服务之间允许相互依赖,同样基于dubbo
  • 数据应用服务之间的依赖应该尽可能的少,应该尽可能放在Rest API层来做处理这种依赖
  • 后方的各个数据系统之间不存在直接依赖,所有依赖都需要通过运营平台的数据应用服务来提供,通信同样基于dubbo
  • 计费和权限认证等逻辑尽可能的异步化或并行(后面详细讨论)

这是年前设计出的一张图,现在来看依然是很满意的,唯一值得考虑的就是“微服务”概念,我一直比较赞同这个概念,尤其是在做SOA筹备的时候更是如此。上图中,数据应用服务是比较适合以微服务方式设计的,不过还需要结合dubbo更仔细的琢磨琢磨。

接下来再来说一下关于上图中一些特殊的服务:计费,认证授权等。我提到了异步和并行,如图:

图解:

  • 虚线表示异步调用,实线表示并行调用
  • 计费和余额查询分离,会产生一个不一致的时间窗口,这需要结合业务来衡量可行性
  • 余额查询,权限认证和获取数据并行调用,最终会在API层合并后给予最终裁决
  • 图中省略了SLB的相关部分

最后,我们讨论一下系统中另外一种场景的通信:消息通知。稍微复杂一些的系统,都会对消息队列有强的需求。这是因为,系统之间的通信在排除了人类参与的情况下,并不需要非常之高的即时响应指标,相反,对消息的最终可达性要求确实100%的。这也是消息中间件的战场,各种各样的开源产品可供我们选择。

我们跳出具体的消息中间件,从业务层面来梳理一下我们目前的平台中要如何设计这部分场景,如下图:

重构团队的开发工作流

靠近年根儿,手上的工作其实还有很多,不过还是要总结一下,展望一下,这就是人类。

在公司的年会上,我代表开发部做了一个简短的工作汇报,在PPT里写了很多14年的业绩和不足,也包含了15年的计划和方案。与往年不同,今年不仅是公司发展的一年,也是团队壮大的一年,也是个人成长最快的一年。

其实自己确实有思考过很多,也收获了很多,找到了团队的痛点,也拿到了公司的授权,所以在15年初,要落实一些新的计划。想要强调的是,这些改革并不是我个人的主观意愿,并非我个人想为而为之的,而是包含了开发部各个层面的景愿的。我把我ppt中相关的一页截了个图,给大家展示一下:

你可能会诧异,这些都是围绕这工具的,是的没错,我们的团队以往一直都是靠人海战术来完成这些工作的,尽管团队也就才11个人而已。也许身在大公司的你觉得不可思议的是,没有这些工具,那开发人员要怎么活?项目质量怎么可能有保证?产品怎么可能如期交付?

这些问题其实在任何一家小公司,创业公司都很常见,像我们这种小城市的创业小团队就更习以为常了,我这么说并非妄自菲薄,纯粹是尊重事实而已!刚到公司,刚走上这个岗位的时候,也曾看过一些敏捷开发,摩拳擦掌想要试试,甚至激进的和大领导申请SOHO办公。

后来在InfoQ上看了一些关于团队协作的分享后,确实得到了很多启发,也迫使自己真的第一次思考了一下所处的真实环境。尊重现实吧骚年,妄想那些远在天边的不切实际,最终只是浪费青春。

废话不多说,我们回过头来继续聊主题,如何完成幻灯片上提到的那些点。

代码质量

深入思考以后,我把代码质量分为两个方面:

  • 业务
  • 代码本身

判断程序员写的代码的质量高低,以我们现在的能力和认知,从上述两个方面最容易做到。业务指的是程序员完成项目需求的程度,是否存在功能缺失,是否存在业务理解错误等方面,而代码本身则指的是程序员提交的代码是否满足团队的代码规范等相关要求。

可以看出来,前者需要有经验的人来检验团队中的其他参与者,有点像师傅带徒弟的模式,在我们的团队(我相信很多公司都如此),师傅带徒弟模式反而是一种非常高效的培养骨干的方式。

后者则可以交给一些现成的工具来完成,下面我就简单聊一下我脑子里的一些计划。首先要引入两个开源工具:

前者是类似github那样的一个基于git的协同开发平台,提供了功能完善的web界面。之所以选择它,而不是直接使用git,是因为gtilab提供了许多辅助文档化的功能,比方说可以让问题和代码更好的关联在一起,具体做法,可以参见gitlab flow

后者提供了强大的代码质量监督功能,不仅支持多种语言,而且也有很好的统计以及社交界面。不过也有些许的不如意,可能是用的不熟的原因吧,具体问题可以看这里

这两个工具都支持与持续集成套件协作,这就为日后的工作提供了衔接。

在借鉴了一些成熟的work flow后,结合我们团队目前的真实情况,我草拟了一个工作流,如下图:

[

](http://pic.yupoo.com/kazaff/EqOi8ovp/medish.jpg)

](http://pic.yupoo.com/kazaff/EqOi8ovp/medish.jpg)

有兴趣的童鞋可以留言一起讨论哇~

只有解决了这些问题,才可以为PPT上后面两项最好工具基础。

自动化测试

还在我写垃圾网站的那些岁月了,我就已经对持续集成这个概念热血沸腾了,不过那个时候更多的只是被其逼格所吸引。随着团队的壮大,项目的成长,慢慢觉得持续集成不仅仅是搞个工具,定个流程那么简单地问题。这玩意儿是需要很多理论支撑的,需要团队成员有相当的职业素养和扎实的技能。甚至也需要其他部门的大力配合,毕竟是一件有得有失的事儿。

我们团队目前的痛点集中在测试环节上,他们已经被手工测试作业折腾的苦不堪言了,更不要说每次修改完bug后的回归测试了,那感觉简直就像是被轮奸,特酸爽。

当然,也不是说自动化就意味着能够把测试完全交给机器来做,凭借公司现在的实力也不可能像模像样的成立一个专门的测试部门,而且我比较认可一个观点:己所不欲勿施于人。如果只是因为程序员不喜欢做测试,而把测试工作交给别的部门来做,那问题依然存在,其他部门也会恶心于这份工作的枯燥乏味。

那么如何能够增加测试的趣味性呢?这个恐怕真的很难做到,不过倒是可以让测试变得不再那么枯燥,引入测试驱动是一个很好的方法,不过这其实并不是减轻了工作量,从某种角度来看反而是加大了代码量,毕竟测试代码也是要交给程序员来完成的。

优势在于回归测试,如果上升到理论的话,程序员还会因为这种思维模式而在编程思想上得到升华。omg~~

自动化测试中包括的关键词有:单元测试,代码覆盖率等,早在以前我也花了一些时间去了解这些玩意儿,不过一直没有投入使用。15年要迫使自己带头推行测试驱动开发。

测试又要分为:前端,后端。前端又分为:交互,兼容,逻辑。当然,这种分类是源于我个人的粗浅理解。至于使用什么具体的工具来搭建自动化测试平台和工作流程,目前无解。

目前目标锁定在:Junit,Jenkins,Mockito等框架。

哇哈哈哈哈哈哈哈哈~实践后再来补充吧。

运维监控

这里想说的主要还是监控预警,至于日志分析什么的,并不在这个主题下。我也不曾做过运维相关的职位,也没有太多使用云平台的经验,在这个主题下,我只能说自己的认知很片面,停留在架设一套开源运维监控系统来搞定,目前目标锁定在:Nagios。

至于应用的监控,可能会尝试花一些时间看一下:kafka,flume,kibana等工具。

猜你喜欢

转载自my.oschina.net/oosc/blog/1791151
SOA