新来老大年前开会说:各位同学,公司业务越来越重,未来几年要成倍增长......,我们要梳理出一套新架构,才能更好的支持N万用户.....,以后升职加薪当上....打败.....
想想还有点小激动呢,于是过年时楼主趁等待相亲妹纸无聊的时候,反思了目前系统现状,构思设计新架构如下。
阅读目录:
鄙司业务比较重,系统也有些年头,各研发团队、系统都比较稳定了。所以不差也不太好,总之也能满足现有需求。但近2年O2O,移动互联网等大行其道,老大们也都心动了,开始磨刀霍霍了。而现有系统应对复杂的变化,在一些地方颇显不足:
逻辑架构图:
查看大图
解释说明:
这是新架构的核心部分,主要功能如下:
各系统通过Web管理页面进行服务配置发布。
也可以通过管理中心提供的组件,进行配置发布:
protected void Application_Start() { ServicePublisher.Pushlish(new ServiceConfig() { ServiceName = "获取预订单详情", Qps = 1000, Level = 1, Key = "xxxx-yyyy", Source = SubscribeSource.All, ServiceAddress = "/Order/GetDetail", //其他 }); } [ServiceFilter] void GetDetail() { }
各系统通过管理中心提供的组件,去获取订阅的服务,然后通过适配器去访问接口,服务变更在心跳里面做:
protected void Application_Start() { //获取服务列表 var serviceList = ServiceManager.GetServiceList(); GlobalService.ServiceList=serviceList; } void Heartbeat() { var serviceList = ServiceManager.GetServiceList(); GlobalService.ServiceList=serviceList; } ServiceAdapter.Access(GlobalService.ServiceList[0]);
这点是非常重要的,如果不能很好的重用已有的系统或侵入性太强,势必会导致:
基于这种考虑,才采用服务分布式而不是服务集中式。
好处是:A系统与B系统是直接交互的,服务调用不走中转路由,性能也好。而组件的作用仅是辅助性的约束。
由于侵入性较小,所以各个系统之间的服务变更,维护完全由各自研发团队维护。
本系统之间通讯不走服务,直接内部调用。调用通过ServiceAdapter组件访问,ServiceAdapter包含对进程内、WCF、WebApi等访问的封装,这样便于以后替换成其他服务。
各服务在扩展上不受管理中心节制,自行做负载、增加服务器即可。
当有个新需要过来时,会根据产品是否需要独立部署,和现有系统耦合性等因素,来评估是模块级还是系统级。
对于旧模块,根据重要程度、访问量等评估出分数。达标的由模块抽离出子系统,单独管理。
同样对于旧系统,不达标的进行降级处理,缩小成模块整合到其他系统里面。
这块其实很重要,如果不对项目做好评估的话,往往会导致一个系统越来越沉重。最后的结果就是维护越来越麻烦,经常出问题。最后逼不得已就推到重来,这个成本就较大些,当然成本的事情老大会考虑更多些。处于这种情况下猿类们会一边吐槽着之前的同类渣渣,一边跃跃欲试准备大展身手,让你们瞧瞧什么叫DDD、TDD、设计模式......。
前提是在需求开发时,按模块进行分小层而不是整个大层,这样方便协作开发和抽取成子系统。
ClientApi这个在前期用的比较多的办法。优点很明显:简单快捷,从Nuget上安装引用即可。这样后期会问题越来越多。
就拿缓存Redis来说,多个系统都使用客户端直接访问Redis服务器。如果有个系统连接数忘记关闭,就会影响整个大系统,原因就是Client权限过大,客户端是可以对redis服务器直接进行操控。这种情况下redis服务器本身是暴露在外的,哪怕客户端封装的再好也不行,只要研究下通信协议规范,就可以自己写个客户端连(参见:c#实现redis客户端(一))。 这个通信期间无法管控,无法做拦截,同样队列等其他也是同样情况。
ServiceApi:
我们在中间加了一层,在缓存系统里面做管控,同样依赖抽象,Redis可替换。缓存系统以服务的形式发布给其他系统使用。
避免不了的就是性能有损耗,当然这个损耗可以通过一些手段减小。
服务的颗粒度一直是SOA设计的头疼事情。太粗了就很难复用,太细了需要多次往返交互,其性能、事务处理都是个问题。
比如下订单服务,这个过程中包含创建用户资料,生成预订单、支付订单,更新账务关系,更新库存等一系列的操作。这是个粗粒度服务,里面包含若干子系统的提供的细粒度服务。
粗粒度服务下,多个子系统避免不了互相交互,长久下去会让系统过于沉重,变得职责混乱。
服务设计准则就是让服务高内聚,服务之间松耦合、边界清晰。所以我们抽离一个聚合服务系统,它专门负责把各系统提供的细粒度服务进行整合,提供给前端使用。而其他各个系统只做自己职责之内的事情。
在聚合服务系统中,方便我们更合理的把控服务的颗粒度,提高服务复用。
多个研发团队协作时,很难每个人都对全部业务熟悉。所以为了避免服务调用混乱,甚至循环依赖调用,增加了对服务的分级。
按图中所示,1级服务不能调2级服务,即低级不能调高级,高级可调低级,同级互相可调。
这个级别针对单个服务而分的。比如有个更新库存服务,它没有外部依赖的服务,只是更新自己的DB,这样我们就可以把它划分为1级服务。 而我们的聚合服务系统中有个下订单粗粒度服务,它内部调用更新库存服务,那么它就是2级服务。很明显这里的1级不应该调用2级,对服务分级也是这个目的。