新来老大年前开会说各位同学,公司业务越来越重,未来几年要成倍增长......,要梳理出一套新架构,才能更好的支持N万用户.....,以后升职加薪当上....打败..... 
想想还有点小激动呢,于是过年时楼主趁等待相亲妹纸无聊的时候,反思了目前系统现状,构思设计新架构如下。

阅读目录:

  1. 现有系统
  2. 新架构    
    2.1 逻辑架构图 
    2.2 解释说明
  3. 系统实施
    3.1 SOA管理中心
    3.2 发布服务
    3.3 订阅服务
    3.4 采蘑菇示例
  4. 设计目标
    4.1 尽可能少的侵入
    4.2 服务自治&&水平扩展
    4.3 系统升级降级
  5. 常见问题
    5.1 ClientApi VS ServiceApi
    5.2 聚合服务
    5.3 服务分级
  6. 总结心得

现有系统

鄙司业务比较重,系统也有些年头,各研发团队、系统都比较稳定了。所以不差也不太好,总之也能满足现有需求。但近2年O2O,移动互联网等大行其道,老大们也都心动了,开始磨刀霍霍了。而现有系统应对复杂的变化,在一些地方颇显不足:

  • 接口没有统一管理
  • 很多组件无法复用/重复造轮子
  • 模块间职责不清,耦合过深
  • 联调排查问题比较慢
  • 开发前规划不足,形成堆积
  • 缺乏API规范/文档较少

新架构

逻辑架构图:

查看大图

解释说明:

  • A开头:是系统级别,可以独立部署。即可寄宿在IIS/WindowsService等上面。
  • B开头:是模块级别,不可独立部署。相对独立的功能模块,而又不大,所以依附其他系统或者和多个模块组成一个子系统。模块级别在项目中可以分多层,可根据分数升级成子系统(见系统升级降级)。
  • C开头:是组件级别,不可独立部署。大多数是公共性组件,一般是单独类库存在,以DLL提供使用。一些开源组件也归到这里,例:Autofac,FluentData。 需要自搭Nuget服务器,进行统一版本管理。
  • 字母后面的数字:是代表服务的级别,见服务分级。
  • 系统通信: 各系统之间尽量走内网Wcf/Tcp,对外合作单位及各移动端走WebApi/Http。
  • 传输格式: Protobuffer、Json。
  • 数据交换: 优先通过数据服务接口,其次SSIS、Job。
  • 基础平台: 缓存Redis,队列RabbitMq等。依赖抽象,框架可替换。
  • DB 层: 每个子系统拥有自己的子DB,原则上不能跨库读其他的。
  • 高可用 : 子系统自行做负载,服务变更通知使用zookeeper。
  • 单向2级:只能订阅服务,不能发布服务,2级只能订阅2级服务。
  • 定点:某个客户端只能订阅某个服务端提供的服务。

系统实施

SOA管理中心

这是新架构的核心部分,主要功能如下:

  • 提供发布/订阅/ServiceAdapter组件
  • 提供Web管理界面
  • 对服务访问的各种配置
  • 在高峰期对服务限流/报警
  • 服务访问授权、描述

发布服务

各系统通过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]);

采蘑菇示例

设计目标

尽可能少的侵入

这点是非常重要的,如果不能很好的重用已有的系统或侵入性太强,势必会导致:

  • 新架构周期过长,长期维护二套结构。这种情况下,成本太高,不好推行下去或者还未推行就被砍了。
  • 开发人员的抵抗,每个猿类内心都有桀骜的脾气、造轮子的天赋、重组世界的梦想...。如果太复杂、约束太强,天知道你们这群猿类会干出什么事情!

基于这种考虑,才采用服务分布式而不是服务集中式。

  • 每个系统在需要时,去订阅服务,然后拉取服务地址/MyNeedServcie.list。
  • 然后通过ServiceAdapter访问服务,ServiceAdapter中会做权限等一些校验。
  • 在服务上增加ServiceFilter,Fileter会做权限校验及服务被调用的信息采集。
  • 然后在管理中心添加服务,文档描述。

好处是:A系统与B系统是直接交互的,服务调用不走中转路由,性能也好。而组件的作用仅是辅助性的约束。

服务自治&&水平扩展

由于侵入性较小,所以各个系统之间的服务变更,维护完全由各自研发团队维护。
本系统之间通讯不走服务,直接内部调用。调用通过ServiceAdapter组件访问,ServiceAdapter包含对进程内、WCF、WebApi等访问的封装,这样便于以后替换成其他服务。 各服务在扩展上不受管理中心节制,自行做负载、增加服务器即可。

系统升级降级

当有个新需要过来时,会根据产品是否需要独立部署,和现有系统耦合性等因素,来评估是模块级还是系统级。
对于旧模块,根据重要程度、访问量等评估出分数。达标的由模块抽离出子系统,单独管理。
同样对于旧系统,不达标的进行降级处理,缩小成模块整合到其他系统里面。

这块其实很重要,如果不对项目做好评估的话,往往会导致一个系统越来越沉重。最后的结果就是维护越来越麻烦,经常出问题。最后逼不得已就推到重来,这个成本就较大些,当然成本的事情老大会考虑更多些。处于这种情况下猿类们会一边吐槽着之前的同类渣渣,一边跃跃欲试准备大展身手,让你们瞧瞧什么叫DDD、TDD、设计模式......。

前提是在需求开发时,按模块进行分小层而不是整个大层,这样方便协作开发和抽取成子系统。

常见问题

ClientApi VS ServiceApi

ClientApi这个在前期用的比较多的办法,优点很明显:简单快捷,从Nuget上安装引用即可,但这样后期引发的问题会越来越多。
就拿缓存Redis来说,多个系统都使用客户端直接访问Redis服务器。如果有个系统连接数忘记关闭,就会影响整个大系统,原因就是Client权限过大,客户端是可以对redis服务器直接进行操控。这种情况下redis服务器本身是暴露在外的,哪怕客户端封装的再好也不行,只要研究下通信协议规范,就可以自己写个客户端连(参见:c#实现redis客户端(一))。 这个通信期间无法管控,无法做拦截,同样队列等其他也是同样情况。

ServiceApi:

这里在中间加了一层,在缓存系统里面做管控,同样依赖抽象,Redis可替换。缓存系统以服务的形式发布给其他系统使用。 避免不了的就是性能有损耗,当然这个损耗可以通过一些手段减小。

聚合服务

服务的颗粒度一直是SOA设计的头疼事情。太粗了就很难复用,太细了需要多次往返交互,其性能、事务处理都是个问题。 比如下订单服务,这个过程中包含创建用户资料,生成预订单、支付订单,更新账务关系,更新库存等一系列的操作。这是个粗粒度服务,里面包含若干子系统的提供的细粒度服务。 粗粒度服务下,多个子系统避免不了互相交互,长久下去会让系统过于沉重,变得职责混乱。
服务设计准则就是让服务高内聚,服务之间松耦合、边界清晰。所以需要抽离出一个聚合服务系统,它专门负责把各系统提供的细粒度服务进行整合,提供给前端使用。而其他各个系统只做自己职责之内的事情。 在聚合服务系统中,方便我们更合理的把控服务的颗粒度,提高服务复用。

服务分级

多个研发团队协作时,很难每个人都对全部业务熟悉。所以为了避免服务调用混乱,甚至循环依赖调用,增加了对服务的分级。
按图中所示,1级服务不能调2级服务,即低级不能调高级,高级可调低级,同级互相可调。
这个级别针对单个服务而分的。比如有个更新库存服务,它没有外部依赖的服务,只是更新自己的DB,这样就可以把它划分为1级服务。 而聚合服务系统中有个下订单粗粒度服务,它内部调用更新库存服务,那么它就是2级服务。很明显这里的1级不应该调用2级,对服务分级也是这个目的。

总结心得

  • 好架构是不断进化来的
  • 尽可能考虑到每个细节
  • 注重整体平衡性,而非局部最优
  • 依赖抽象,而不是具体哪个框架技术
  • 先考虑人、资源,在考虑用哪个技术
  • 跟妹纸相处时不要想程序那点事

SOA相关资料整理分享

作者:蘑菇先生 出处:http://mushroom.cnblogs.com/

本文版权归作者和博客园共有,欢迎转载。未经作者同意下,必须在文章页面明显标出原文链接及作者,否则保留追究法律责任的权利。
如果您认为这篇文章还不错或者有所收获,可以点击右下角的【推荐】按钮,因为你的支持是我继续写作,分享的最大动力!

设计的SOA架构的更多相关文章

  1. 给公司部门设计的SOA架构

    新来老大年前开会说各位同学,公司业务越来越重,未来几年要成倍增长......,要梳理出一套新架构,才能更好的支持N万用户.....,以后升职加薪当上....打败..... 想想还有点小激动呢,于是过年 ...

  2. 给公司部门设计的SOA架构(转)

    新来老大年前开会说:各位同学,公司业务越来越重,未来几年要成倍增长......,我们要梳理出一套新架构,才能更好的支持N万用户.....,以后升职加薪当上....打败..... 想想还有点小激动呢,于 ...

  3. SOA架构简介

    一. 什么是SOA 架构 SOA是一种架构模型,它可以根据需求通过网络对松散耦合的粗粒度应用组件进行分布式部署.组合和使用.服务层是SOA的基础,可以直接被应用调用,从而有效控制系统中与软件代理交互的 ...

  4. 企业SOA架构设计理论

    SOA简介 SOA(Service-Oriented Architecture,面向服务架构)是一种将信息系统模块化为服务的架构风格.拥有了服务之后,我们就可以迅速地将这些服务按不同方式重新组合,从而 ...

  5. IDDD 实现领域驱动设计-SOA、REST 和六边形架构

    上一篇:<IDDD 实现领域驱动设计-架构之经典分层> 阅读目录: SOA-面向服务架构 REST 与 RESTful 资源(Resources) 状态(State) 六边形架构 DDD ...

  6. SOA架构设计经验分享—架构、职责、数据一致性

    阅读目录: 1.背景介绍 2.SOA的架构层次 2.1.应用服务(原子服务) 2.2.组合服务 2.3.业务服务(编排服务) 3.SOA化的重构 3.1.保留服务空间,为了将来服务的组合 4.运用DD ...

  7. SOA架构设计(转发)

    阅读目录: 1.背景介绍 2.SOA的架构层次 2.1.应用服务(原子服务) 2.2.组合服务 2.3.业务服务(编排服务) 3.SOA化的重构 3.1.保留服务空间,为了将来服务的组合 4.运用DD ...

  8. SOA之(2)——SOA架构基础概念与设计框架

    SOA的设计框架 设计框架与架构相关的概念紧密相连,原则.模式和架构始终是与设计共舞的. SOA服务设计的原则中记录了一个基础的设计框架: 设计特性(Design Characteristic)——由 ...

  9. [转]SOA架构设计经验分享—架构、职责、数据一致性

    阅读目录: 1.背景介绍 2.SOA的架构层次 2.1.应用服务(原子服务) 2.2.组合服务 2.3.业务服务(编排服务) 3.SOA化的重构 3.1.保留服务空间,为了将来服务的组合 4.运用DD ...

随机推荐

  1. 寻找对象在父元素下的index

    方法一. window.onload=function(){    //寻找对象在父元素下的index    function getIndexParent(element){         var ...

  2. 【并查集】PKU-1182 食物链

    食物链 Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不 ...

  3. 到目前为止,Linux下最完整的Samba服务器配置攻略

    关 于Samba,大家有没有这种感觉,弄了N久丫的死活不喘气儿.找来各种“哥”和“姐”,发现全是“详解…配置专题”,看了半天不知道别个在说什么,好不 容易找了个简单的教程,从头到尾跟着做,尼玛,浪费时 ...

  4. asp:弹出警告框,并重定向的自定义过程

    因为制作的需要写了这样一个简单的函数,重定向可以是指定的页.也可以是前一页! 有两个参数:messtr,警告框的信息;urlstr:转向的网页,为""时,返回到前一页! 程序代码 ...

  5. Beyond Compare 相同文件对比结果仍显示红色 解决方案

    转载:http://blog.sina.com.cn/s/blog_4d4bc1110100zj7x.html   1. 问题详细描述如下. 下图显示对比结果中,两侧的aaa.xml是一模一样,会话中 ...

  6. poj1274 匈牙利算法 二分图最大匹配

    poj1274 题意: 有n个奶牛, m个畜舍, 每个畜舍最多装1头牛,每只奶牛只有在自己喜欢的畜舍里才能产奶. 求最大产奶量. 分析: 其实题意很明显, 二分图的最大匹配, 匈牙利算法. #incl ...

  7. HW--漂亮度

    描述 给出一个名字,该名字有26个字符串组成,定义这个字符串的“漂亮度”是其所有字母“漂亮度”的总和.每个字母都有一个“漂亮度”,范围在1到26之间.没有任何两个字母拥有相同的“漂亮度”.字母忽略大小 ...

  8. Google Map JavaScript API V3 实例大全

    Google Map JavaScript API V3 实例大全 基础知识 简单的例子 地理位置 语言 位置 坐标 简单的投影 事件 简单事件 关闭事件 多次添加事件 事件属性 控制 php禁用ui ...

  9. QT/C++ 智能指针

    什么是智能指针? 为什么用智能指针? 还有哪些关于内存管理方面的知识点,需要注意的?

  10. 第8条:覆盖equals时遵守通用约定

    如果不需要覆盖equals方法,那么就无需担心覆盖equals方法导致的错误. 什么时候不需要覆盖equals方法? 1.类的每个实例本质上是唯一的. 例如对于Thread,Object提供的equa ...