微服务已经成为过去几年软件架构设计的“事实标准”,大多数企业在推动内部数字化转型的过程中,服务软件系统开始由单一或者SOA服务向微服务转型,那么转型过程应该如何落实,需要遵循什么原则呢?本文结合过往微服务落地实践经验,分享微服务落地实践的过程中思考。

目前当技术人员提及微服务的时候,首先想到的是spring cloud,Dubbo等实现服务的技术框架。这在我们采用微服务的初期阶段,这也是最先考虑的因素。可是随着服务化的进行,我们并没有享受到由框架的便利性与快捷性带来业务的突飞猛进的成就感,恰恰相反,过多的服务化以及服务间冗余且多元化通信机制反而加重了业务处理的负担。这必然不是我们想要的微服务,却是大多数企业在执行的微服务。

因此我们开始重新审视整个行业,审视微服务的发展历程。与过往不同的是:前期阶段,我们把更多的精力投入到业务上,而一定程度上“忽略”技术,因为此时我们建立的信念是无论何种形式的“服务形态”一定是为业务服务的。

当我们站在全局的角度,观看整理后的服务,发现了一个极其优美的图形化结构,各个节点的边界清晰,职责分明;节点间的链路畅通,协议规整。这时我们知道我们终于走在了正确的道路上。

我们遵循的原则

当经过一定时间的挣扎以后,我们觉得微服务的关注点不在于技术本身,但并不意味着不关注技术。在反思过程中,我们认为微服务实践中有两个原则不能变:服务一定是围绕业务的,服务的交互是标准的。我们把原则分为两个阶段:初期阶段和实践阶段。

初期阶段

初期阶段,遵循第一条原则,服务一定是围绕业务的。微服务初期阶段,重要的是业务梳理,而不是花费大量时间在RPC、Service Discovery、 Circuit Breaker这些概念或者Eureka,Docker,Gateway,Dubbo等技术框架的调研上。此时我们重心关注服务的边界与职责划分。

这是遵循的两条原则:
(1)保证单一业务服务高效聚合;
(2)降低服务间的相互调用(此举是避免陷入大量分布式业务的处理)。这样的原则下,DDD为我们提供了帮助,但也依据业务本身的特性实现了服务初期阶段的整理。同时我们发现就算借助DDD的指导,在不同的业务应用中,各个服务也有不同的聚合形态和调用方式。因此我们觉得微服务本身没有一成不变的模式,一切都是围绕业务动态变化的。合理性也仅仅体现在一点阶段的时间范围之内。

实践阶段

当业务建模完成,我们能够清晰的指导各个业务的职责以及与其他业务的关联关系,从理论层面我们完成了业务微服务建模。此时我们开始着手服务的落地实践,在落地实践阶段我们更多关注点同样不在于技术框架,而是在于技术框架的内涵——即服务交互标准。

此时我们遵循了第二条原则:服务的交互是标准的。所谓服务交互标准从三个层面解读:协议标准、框架标准、接口标准。

  • 协议标准

    目前网络应用的协议也比较复杂,因此我们希望选取能够符合业务场景的协议作为通信标准。因此我们考虑了统一的认证鉴权协议,加密解密协议,内部接口交互协议,外围接口服务协议等,各个协议各司其职,用来支撑服务通信的标准化。协议标准不仅仅为平台自身服务,同时与其他业务单元进行通信时,只需要遵循协议标准,就可以实现业务单元之间的快速联动。

  • 框架标准

    为了支撑业务,我们没有依赖任何的自动化代码生成框架,而是根据我们的协议支持情况,选择最小的服务运行框架,来构建统一的业务单元支撑框架。这里需要说明的一点,框架标准需要考虑业务特性,协议特性,不能一概而论,因此它的有效性也许只在当前构建的业务平台本身。构建标准框架的好处是针对应用内的所有业务单元可以快速复制,简化因为各自开发框架不同导致联调阶段出现问题。

  • 接口标准

    接口分两种:业务内部接口,业务服务接口。无论哪种接口同样遵循标准化原则。

    业务内部接口的核心在于压缩协议,加快业务的处理流程,因此可以采用rpc等高效率的协议支持的接口模式;业务服务接口的核心在于表明业务携带的信息,因此采用restful接口规范更合适一些。接口设计需要涵盖但不限于标准化的请求方式,统一的参数处理,统一的结果返回,统一的异常处理,统一的日志处理等。

服务拆分与聚合

前提:服务拆分与聚合本篇文章中暂时不考虑web的微服务化设计,只说明后端服务的拆分与聚合实践。

服务拆分与聚合需要遵循的原则:服务一定是围绕业务的。但事实情况是在现在追求“开源整合”的背景下,纯粹的业务单元在不借助第三方工具的前提下,需要消耗巨大的代价才能实现业务需求,同时也出现不同业务单元对同一个工具的强依赖性。因此在服务拆分与聚合时,我们考虑了两种形态的实现方式:业务支撑和工具支撑。

业务支撑

业务支撑需要考虑的是业务服务对象,业务内部逻辑。业务服务对象作为整个业务单元的对外形态,通过命名能够清晰的表达其涵盖的业务范围;业务内部逻辑需要对业务单元进行细粒度的拆分,类似一个实体类可以包括多个其他相关联的实体对象(当然如果服务拆分的足够细化,也可以把内部逻辑作为独立的业务单元,但是这样会加重业务直接的通信负载)。基于业务内部逻辑构建业务服务对象的真实场景。具体的拆分细节可以依赖DDD的实践方法进行(当然也需要根据业务做相应调整,没有普世之道)。

工具支撑

工具支撑需要结合业务考虑,分为两种:通用性工具和专用性工具。通用性工具旨在为所有业务单元运行提供统一的支撑平台,从而减少由于工具维护花费的精力,使得业务开发人员聚焦业务实现,一般通用工具包包括统一日志处理,统一拦截处理,返回数据统一封装,异常统一处理等等;专用性工具聚焦某个具体的业务单元,由业务单元自身维护(例如迭代升级)。工具支撑层面不会提供对外restful或者rpc的接口,对外的表现形式为编译好的依赖工具包(例如Github的管理接口的封装)。

服务架构选型

依照执行原则完成服务拆分以后,我们需要考虑的是合适的落地选型。选型方案要考虑的因素有很多:技术背景(尤其是团队内编程语言的设定),服务支撑工具(注册中心,网关,服务调用,负载均衡数据库等),服务运行工具(tomcat,jetty,jboss等),服务部署工具(物理部署,虚拟化,容器等),工具的协议支撑集合(http,rpc,mtqq,idoc等)。但是无论如何选型最终一定要结合团队开发人员当下的技能支撑,这也是我们选型的核心因素,因为白盒相对来说始终比黑盒安全,也相对可控。这里给出我们的技术栈选型框架(仅限我们熟悉的内容),暂时不涉及技术框架的对比说明。

服务开发框架:springboot,dubbo,grpc,ServiceMesh(基于ServiceMesh的开发服务框架)
分布式存储/注册中心:Zookeeper,Consul,Eureka,Etcd
服务网关:Kong,Openresty,Spring cloud Zuul,Spring cloud gateway
负载均衡:nginx,spring cloud Ribbon,haproxy,Kubernetes service
服务远程调用:Spring cloud feign
缓存服务:memchace,redis
数据库:mariadb,mysql
消息服务:RabbitMQ,NATS,Kafka
配置中心:spring cloud config,Apollo,Consul
事件机制:Cloud Event
服务编排:Conductor ,Kubernetes
服务治理:spring cloud,Dubbo,ServiceMesh
基于消息机制的分布式事务处理(遵循CAP或者BASE理论模型的实现)
业务运行工具:jvm,nginx或者其他可运行环境支撑
开发编译工具:Jenkins,maven,gitlab
接口文档:Swagger

部署工具:物理部署(jar包或者可运行的编译的二进制文件)虚拟化部署(虚拟镜像模板)容器化部署(Docker)
我们在落地的过程中,根据团队技术特点开发阶段重点选择了Spring cloud中涵盖的技术栈。方便易用,能够快速入手。运行阶段选择具备服务编排能力的Kubernetes容器化运行环境。并且结合Devops工具链能够快速迭代部署。

服务接口设计

服务接口是对外展现业务逻辑的唯一入口,接口定义的规范与否也是微服务落地的关键指标之一,我们在实践的过程中参考了多个开源项目的接口设计,针对任何一个资源对象,整体分为几类场景:资源集合类操作,资源实体操作,异常处理,参数处理,统一数据返回,审计日志以及其他具体场景。

统一的接口请求与响应标准

其中业务单元绝大多数端口围绕着资源集合类,资源实体类进行操作,因此我们从restful接口规范出发,结合具体场景,规范了请求方式,请求url,请求参数,请求header,响应header,响应值等信息。

请求参数涵盖默认语义,包括:Get(获取信息),Post(创建),Put(全量修改),Patch(部分修改),Delete(删除)

以Students实体对象的新建为例,给出请求与响应标准。

URL

URL请求包括三部分:请求方式,统一前缀以及具体url,统一前缀具备一定含义的命名规则,包括api申明,供应商标识,版本说明等必要信息,例如:     
  
Post /api/cloud/v1/students?exist={skip,replace}

请求header

Content type
    aplication/json:用于single和bulk时,用来表示请求数据为json格式
    application/vnd.ms-excel:从excel格式的文件导入创建
  Accept
    aplication/json:接受json格式的响应数据
  Authorization
    Oauth2.0的access token(bearer token)
  Accept-Language(可选)
可接受的语言,国际化,en-US表示美国英语

请求数据格式+类型

json格式:{items:[]}
    请求创建students对象json(表达):
     请求(批量)创建student对象列表json(表达)
     请求(批量)创建student信息excel文

响应header

Content-Type
     aplication/json
   Content-Language(可选)
     内容语言
   Last-Modified
     数据最近一次修改的时间戳信息

响应值

Success message:多种类型
     Error message:多种类型
     Exception:多种类型

统一异常处理

统一异常处理包括状态码以及状态码涵盖的异常信息,具体部分定义如下:

  • 200/201+success message(含资源数量信息+uri信息):创建成功,适用于数量不多(比如小于500)的创建操作,大于设定的值时进行异步处理,参加返回值202
  • 202+success message with status uri:异步处理,返回进度查询资源uri(/api/vendor/v1/status/{id})
  • 400+success+errors(含出错项index的错误列表):批量创建时部分成功,返回成功信息和错误信息
  • 401+exception{error_code+message}:缺乏认证信息
  • 403+exception{error_code+message}:未授权访问,访问被拒绝
  • 406+exception{ error_code+message}:不支持client要求的格式或语言时返回该信息(Not Acceptable)
  • 415+exception{error_code+message}:请求中的文档格式不支持
  • 422+exception{error_code+message}:不能处理的数据,比如json格式错误、文件内容项错误或会破坏业务规则
  • 429+exception{ error_code+message}:太多请求,流控时使用                    
    500+exception{error_code+message}:服务器内部错误。

统一日志拦截

基于AOP模式拦截所有请求,在请求入站与出站的时候,做统一日志记录以及需要的其他非业务处理(例如鉴权)。

统一的数据返回标准

我们参考Restful数据返回标准,封装我们自己的数据返回格式:code,message,body,error,统一的数据返回格式可以在接口层做统一的拦截处理。实现返回数据的标准化。
  code:返回状态码
  message:返回响应结果的语义解释
  body:响应的具体数据信息,包括metada信息,具体响应数据以及请求连接
  error:代表返回的错误信息
  具体的响应格式如下所示:

{    \u0026quot;code\u0026quot;: 200,    \u0026quot;message\u0026quot;: \u0026quot;获取学生列表成功\u0026quot;,    \u0026quot;body\u0026quot;: {        \u0026quot;links\u0026quot;: [            {                \u0026quot;rel\u0026quot;: \u0026quot;self\u0026quot;,                \u0026quot;href\u0026quot;: \u0026quot;http://localhost:8080/api/cloud/v1/students?name=test\u0026amp;startDate=2019-01-01\u0026amp;endDate=2019-09-01\u0026amp;style=normal\u0026amp;sort=asc\u0026amp;limit=10\u0026amp;offset=0{\u0026amp;fields}\u0026quot;,                \u0026quot;hreflang\u0026quot;: null,                \u0026quot;media\u0026quot;: null,                \u0026quot;title\u0026quot;: null,                \u0026quot;type\u0026quot;: null,                \u0026quot;deprecation\u0026quot;: null            }        ],        \u0026quot;metadata\u0026quot;: []        \u0026quot;content\u0026quot;: [            {                \u0026quot;id\u0026quot;: 1,                \u0026quot;name\u0026quot;: \u0026quot;test3\u0026quot;,                \u0026quot;status\u0026quot;: \u0026quot;running\u0026quot;,                \u0026quot;props\u0026quot;: \u0026quot;test\u0026quot;,                \u0026quot;remark\u0026quot;: \u0026quot;test\u0026quot;,                \u0026quot;ownerId\u0026quot;: 1,                \u0026quot;createrId\u0026quot;: 1,                \u0026quot;menderId\u0026quot;: 1,                \u0026quot;gmtCreate\u0026quot;: \u0026quot;2019-03-11 10:42:15\u0026quot;,                \u0026quot;gmtModify\u0026quot;: null,                \u0026quot;startDate\u0026quot;: null,                \u0026quot;endDate\u0026quot;: null,                \u0026quot;links\u0026quot;: [                    {                        \u0026quot;rel\u0026quot;: \u0026quot;self\u0026quot;,                        \u0026quot;href\u0026quot;: \u0026quot;http://localhost:8080/api/cloud/v1/students/1?style=normal\u0026amp;fields=\u0026quot;,                        \u0026quot;hreflang\u0026quot;: null,                        \u0026quot;media\u0026quot;: null,                        \u0026quot;title\u0026quot;: null,                        \u0026quot;type\u0026quot;: null,                        \u0026quot;deprecation\u0026quot;: null                    }                ]            }        ]    }    \u0026quot;errors\u0026quot;: {}}

服务接口的设计一定是围绕标准化的规则进行的,这样才能在后期减少因为接口变动导致不断出现的前后端联调问题。因为在实践中我们经常遇到格式不统一导致web要写不同的数据解析方式,从而造成大量重复的工作。

遗留问题

当然我们落地过程的选择也不一定尽善尽美,也有很多随着业务处理能力的加强,之前没有考虑到的问题,例如:

  • 各个服务自身并发数据支撑能力;
  • 服务交互的内部代码瓶颈,包括调用链路冗余,响应偏慢等;
  • 数据库的并发支撑与性能优化;
  • 与容器服务集成的参数配置,开发与部署环境的转变;
  • 调用链路可能出现的回环问题,交叉的业务单元调用,导致调用链路混乱;
  • 数据的缓存设计,加快业务响应速率;
  • 这些问题在后续不断深入的理解和探索中,都会找到相应的解决方案。

微服务落地,我们在考虑什么?\n相关推荐

  1. 微服务落地,我们在考虑什么?

    点击蓝色"程序猿DD"关注我哟 加个"星标",不忘签到哦 来源:博云技术社区 导读 微服务已经成为过去几年软件架构设计的"事实标准",大多数 ...

  2. 干货|基于 Spring Cloud 的微服务落地

    转载自 干货|基于 Spring Cloud 的微服务落地 微服务架构模式的核心在于如何识别服务的边界,设计出合理的微服务.但如果要将微服务架构运用到生产项目上,并且能够发挥该架构模式的重要作用,则需 ...

  3. 微服务落地,我们在考虑什么?| 技术头条

    戳蓝字"CSDN云计算"关注我们哦! 技术头条:干货.简洁.多维全面.更多云计算精华知识尽在眼前,get要点.solve难题,统统不在话下! 作者:李宁 转自: 博云技术社区 导读 ...

  4. 微服务落地践行渐进,4个QA一窥金融微服务现状

    2019独角兽企业重金招聘Python工程师标准>>> 1月13日,中国双态运维用户大会在北京举办.来自银行.保险.证券.政府.央企等多个行业的330多位企业用户参加,其中工商银行信 ...

  5. DDD微服务架构设计第四课 微服务落地实践的技术中台

    10 微服务落地的技术实践 如今,做一个优秀的程序员越来越难.激烈的市场竞争.互联网快速的迭代.软件系统规模化发展,无疑都大大增加了软件设计的难度.因此,对于架构师的能力要求也越来越高,就像我的一本书 ...

  6. 【微服务落地】服务间通信方式: gRPC

    多语言:语言中立,支持多种语言. 轻量级.高性能:序列化支持 PB(Protocol Buffer)和 JSON,PB 是一种语言无关的高性能序列化框架. IDL:基于文件定义服务,通过 proto3 ...

  7. 微服务落地实战一创建Swarm集群

    创建Swarm集群 Swarm 是 Docker 官方提供的一款集群管理工具,其主要作用是把若干台 Docker 主机抽象为一个整体, 并且通过一个入口统一管理这些 Docker 主机上的各种 Doc ...

  8. 我是如何把微服务的这个模式落地的:一个服务一个数据库模式(中)

    从我接触微服务以来,迄今也得有五六年了.断断续续要么从零开始,要么中途接手,也经历了 5 套微服务项目了. 从这些项目中的经验以及和同行交流来看,根据业务切分微服务的方法总的来说思路不复杂,但是落地总 ...

  9. DDD微服务架构设计第四课 DDD指导微服拆分和落地实现

    07 在线订餐场景中是如何开事件风暴会议的? 微服务设计最核心的难题是微服务的拆分,不合理的微服务拆分不仅不能提高研发效率,反倒还使得研发效率更低,因此要讲究"小而专"的设计.&q ...

  10. 传统行业转型微服务的挖坑与填坑

    原文:传统行业转型微服务的挖坑与填坑 一.微服务落地是一个复杂问题,牵扯到IT架构,应用架构,组织架构多个方面 在多家传统行业的企业走访和落地了微服务之后,发现落地微服务是一个非常复杂的问题,甚至都不 ...

最新文章

  1. 安装黑屏_含能公司黑屏管理助力智能化改造
  2. c语言退出程序命令_C语言#error命令,阻止程序编译
  3. python脚本创建拓扑_实验 1:Mininet --拓扑的命令脚本生成
  4. C++类模板特化全总结
  5. freemodbus源码/获取地址
  6. JS面向对象编程实现
  7. LeetCode 1203. 项目管理(两次拓扑排序)
  8. linux手动安装unzip_怎样在Linux下搭建接口自动化测试平台?
  9. 对于vue的评价:没事情做可以学
  10. unity三维地图的经纬度如何在二维地图上表示_安全数据分析:数据点—地图—线性回归...
  11. TeamViewer远程控制软件,让你享受远程办公的便利
  12. (产品面试贴)乐动——阿里巴巴2015暑期实习平台型产品经理(技术领域)
  13. Rust语言编程实例100题-036
  14. 音乐系统(译码作曲)
  15. win10无法访问linux共享服务器,Win10无法访问NAS或Linux网络共享的处理方法
  16. 【网络工程】计算机网络专业术语概论全面整理
  17. Java基础篇:八大基本数据类型
  18. 什么是CRM?CRM定义/CRM适用于谁?/CRM系统有什么作用?
  19. 开课吧WEB全栈架构师【6期,9-12期】
  20. 图显系统DRM GEM完全解析

热门文章

  1. ps证件照白底换蓝底_【插件】PS插件证件照V2.0一键裁剪排版磨皮换装换底色软件2020Mac/Win完整版...
  2. BCM wifi分析
  3. win7 修改html文件图标,如何更改文件图标,教您Win7如何更改图标
  4. 计算机配置很不错但是卡,高手告诉你win10电脑明明配置很好却卡顿的详尽处理手法...
  5. 即时聊天通讯软件安卓+ios双端原生源码
  6. PHP微信公众号登录获取openid信息
  7. 糖友控糖是在控什么糖呢
  8. 运行zookeeper提供者报错:org.jboss.netty.util.internal.jzlib.ZStream scanned from multiple locations: jar:
  9. 只读(Readonly)与禁用(Disable)的区别与使用
  10. 阿里巴巴图标库iconfont的使用