微服务架构实践总结
微服务架构实践总结
优雅先生 发表于3年前
微服务架构实践总结
  • 发表于 3年前
  • 阅读 7777
  • 收藏 120
  • 点赞 5
  • 评论 17

腾讯云 技术升级10大核心产品年终让利>>>   

摘要: 本文是我结合阅读微服务架构相关资料和工作实践,总结而成。

    微服务架构是由Martin Fowler在他这篇microservices博客中提出来的,与之对立的是monolithic架构。

monolithic架构概念 vs. 微服务架构概念

    monolithic架构指的是应用被以单一单元构建。比如一个小型订餐网站包含菜品展示、下订单、在线支付等业务功能模块,该网站的后端系统应用实现了所有这些业务功能。

    而微服务架构则是由一组微服务组成的架构模式。每个微服务都是一个可独立部署的完整系统。一组微服务组成微服务层(注意这里的服务层不同于monolithic架构中的服务层,那个是单系统中的功能模块分层)。微服务层上面一般是应用层,应用层通过组合使用微服务层的各个微服务而向外提供接口(比如HTTP API接口)。各个微服务可以通过RPC接口供应用层调用,比如利用Thrift、Avro。

微服务拆分方法

    微服务架构中的微服务一般按照业务功能来拆分,将关联性较强的业务拆成一个微服务,比如上面订餐网站可以拆分成用户服务、订单服务、菜品服务、支付服务等。具体来说一般根据业务实体名词如订单、用户或者业务动作如登录、下载等来拆分。

数据集成 vs. 服务集成

    数据集成是一种比较传统的系统集成方式,其中心是数据。比如交易系统会操作订单表和用户表,比如生成订单。而短信通知系统也会访问订单表和用户表,根据订单的状态来发出不同的短信通知给用户:比如给金额较大的订单对应的用户发一些促销活动短信,给一些未完成订单的用户发短信提醒其完成订单。这就是一种数据集成方式,交易系统和短信通知系统依靠订单表和用户表进行集成。这种集成方式的优点在于实现简单,缺点有下面几条:

  • 业务数据库负担较大,因为多个系统都访问同一个数据库的同几张表

  • 安全性,交易系统可以修改订单表中的订单状态是理所当然的事,但由于短信通知系统也可以直接访问订单表,可能导致一些意想不到的问题

  • 扩展性问题:交易系统如果以后想把订单表从RDBMS迁到HBase可能就没那么容易了,因为还有很多其他系统也依赖于订单表,真可谓牵一发而动全身;或者各个系统可能擅自做主给表增减字段,都会带来不好后果

  • DAO代码重复,如果交易系统和短信通知系统由两个不同部门的团队开发,那么每个系统中都会有针对订单表和用户表的DAO代码

    服务集成则打破了数据集成模式,不再以数据为中心集成各系统。微服务架构天然就拥抱服务集成方式。如果用服务集成方式重新设计上面的交易系统和短信通知系统,那么就会提出两个微服务:用户微服务,负责对用户信息进行管理(具体底层是否真的操作关系数据库表,外部已经不关心,即外部不知道用户信息是存在MySQL、Redis还是二者都有,也不需要知道);和订单微服务,负责对订单信息进行管理。交易系统和短信通知系统都被提取到更上一层的应用层,他们分别调用用户微服务和订单微服务完成任务。这样用户数据状态的变化和订单数据状态的变化将不再同时受控于交易系统和短信通知系统,而只由用户微服务和订单微服务控制。

微服务与微服务之间相互调用

    一般避免微服务直接调用另外一个微服务,尤其忌讳两个微服务相互调用,如果存在两个微服务相互调用的场景,那么得慎重衡量下微服务拆分是否合理。

    当然某些情况无法避免微服务之间相互调用,这时候我们一般可以采用两种方式实现:

  • 消息队列

  • 消息总线

monolithic架构与微服务架构各自优缺点

    除了上面提到的一些优缺点外。下面再总结下两种架构的各自优缺点。

    首先看monolithic架构,它的优点是:部署方便,只需要部署一份代码。但它的缺点有很多:

  • 代码庞杂,理解困难,新人上手也困难

  • 维护困难,一般一个monolithic架构应用得由一个团队维护,如果应用越大,则维护的人越多,团队管理成本也越高,团队效率也会越低下(3-5人是最佳团队规模)

  • 启动一般较慢

  • 持续部署困难:每一次小改动都需要重新部署整个应用

  • 技术堆栈固化:尝试新技术的代价太高

  • 扩展困难:应用某些部分偏IO密集型、某些部分却偏CPU密集型,但应用却只部署在一台机器上,很难用单一硬件来满足应用各部分对硬件资源的不同要求

    微服务架构的优点自然与上面的缺点相反,列举三条:

  • 每个微服务功能简单,代码量也不多,新人上手容易

  • 每个微服务可以由不同团队开发,每个微服务一般由1-3人开发维护

  • 系统稳定性增强,单个服务的失效不会影响其他服务,可以一定程度实现服务降级

  • 容易尝试技术创新,甚至每个微服务都可以采用不同的编程语言编写,只要对外提供约定好的接口就行

    但微服务架构也有缺点,按照我个人理解的严重程度由高到低排列如下:

  • 运维成本高:原来一个应用一个进程,现在被拆分成微服务后可能有十几个进程,并且每个微服务都需要独立部署

  • 测试成本高:微服务架构带来的是一个分布式系统,分布式系统的测试比单系统测试更复杂

  • 微服务升级带来的接口不向后兼容问题

  • 每个微服务开发者都需要关注微服务开发、集成、测试、部署、上线完整流程

    为了应对微服务升级带来的接口不向后兼容问题,一般可以对接口升级做一些约定以保证接口向后兼容,假设微服务采用Thrift接口开放给应用层,那么约定如下:

一般接口升级只允许下面几种情况(这种情况能够保证Thrift服务端二进制代码向后兼容客户端,
即Thrift服务端由V1.0.9升级到V1.1.0,客户端依然可以使用V1.0.9 Thrift服务端对应的Stub
代码):
> 增加新接口方法或者新结构体(Struct)
> 在接口方法参数后面增加非必须参数
> 为结构体(Struct)增加非必须参数
> 修改返回值类型为void的接口方法,使其返回值类型为任意其他类型
> 删除接口方法签名中的throw
> 从结构体中删除field
> 重命名结构体
> 修改命名空间

不允许的情况包括:
> 删除或者重命名接口方法
> 修改非void返回值类型接口方法的返回值类型
> 修改接口方法参数类型
> 为非void返回值类型接口方法添加throw
> 通过Thrift接口开放给外部的系统在升级后必须升级pom.xml中的版本号,同时对应的inf接口
  项目的版本号也要跟着升级

    全文完,转载请注明出处http://my.oschina.net/feichexia/blog/344190,谢谢!

标签: 微服务架构
共有 人打赏支持
粉丝 340
博文 34
码字总数 46563
评论 (17)
ice_stream
请教一下,如果服务消费者需要在一个执行单元中保证消费多个服务,怎么保证数据的一致性?在你们的实践中,如何解决或者规避此问题?
优雅先生

引用来自“ice_stream”的评论

请教一下,如果服务消费者需要在一个执行单元中保证消费多个服务,怎么保证数据的一致性?在你们的实践中,如何解决或者规避此问题?
在我们的服务中尽量只保证数据的最终一致性。否则就会用到分布式锁,那个是万不得已的选择。
优雅先生
还有一种规避方案就是合服务。
优雅先生

引用来自“ice_stream”的评论

请教一下,如果服务消费者需要在一个执行单元中保证消费多个服务,怎么保证数据的一致性?在你们的实践中,如何解决或者规避此问题?
请教不敢当,大家相互学习,
ice_stream
最终一致性性的方案,会加大业务开发部门的设计与开发难度.

传统方式下,平台部门能在框架层面保证业务部门的代码不出现一致性问题.
微服务架构下,这种工作需要业务部门自己来负责.这个对业务开发者水平不是很强的组织,推广阻力就会比较大.

这就是我的困境,业务部门认为会带来额外工作量,对此种架构此否认态度.难于在公司范围内推广.
优雅先生

引用来自“ice_stream”的评论

最终一致性性的方案,会加大业务开发部门的设计与开发难度.

传统方式下,平台部门能在框架层面保证业务部门的代码不出现一致性问题.
微服务架构下,这种工作需要业务部门自己来负责.这个对业务开发者水平不是很强的组织,推广阻力就会比较大.

这就是我的困境,业务部门认为会带来额外工作量,对此种架构此否认态度.难于在公司范围内推广.
我做的项目是新项目,人也不多,大家也对新技术持开放心态,所以组内推广这个还是蛮顺利的。但随着实践的深入,踩坑是难以避免的。
老盖
和SOA有什么区别?
翟志军
希望更多的实践方面的文章。好处大家都知道。但是坑在哪?没有多少知道。而且Amazon似乎老早以前就是以服务为中心的设计了。国内现在才开始火起来。。。
厦门王五
微服务的思想是极好的,我们在实际技术实践中也有类似的应用,但是由于数据一致性等一些问题,只在日志等非核心组件尝试使用。
在这么细的层面部署多个jvm,事务跟性能是否有保障,有相对可靠的解决方案么?我们现在采用Best effort 1PC机制。
业务微调带来的影响是否可控,或者说是否对前期的设计有了更高的要求,是否有相对的规范或参考标准?
错觉
请问 我每一个都用嵌入jetty 因此同一主机每个服务都占用一个端口 这些端口的维护量会很大 如果加上负载均衡 多个服务器都必须这样 在负载均衡上是不是要配置很多
优雅先生

引用来自“错觉”的评论

请问 我每一个都用嵌入jetty 因此同一主机每个服务都占用一个端口 这些端口的维护量会很大 如果加上负载均衡 多个服务器都必须这样 在负载均衡上是不是要配置很多
是的,是会带来更多的运维部署开销
优雅先生

引用来自“戏水”的评论

和SOA有什么区别?
和SOA没有本质区别,微服务可以理解为细粒度的SOA。
ice_stream

引用来自“错觉”的评论

请问 我每一个都用嵌入jetty 因此同一主机每个服务都占用一个端口 这些端口的维护量会很大 如果加上负载均衡 多个服务器都必须这样 在负载均衡上是不是要配置很多

引用来自“优雅先生”的评论

是的,是会带来更多的运维部署开销
其实这里有个潜在好处,能够驱动开发测试运维的自动化.
ice_stream

引用来自“戏水”的评论

和SOA有什么区别?

引用来自“优雅先生”的评论

和SOA没有本质区别,微服务可以理解为细粒度的SOA。
SOA是世界观,微服务是方法论
优雅先生

引用来自“错觉”的评论

请问 我每一个都用嵌入jetty 因此同一主机每个服务都占用一个端口 这些端口的维护量会很大 如果加上负载均衡 多个服务器都必须这样 在负载均衡上是不是要配置很多

引用来自“优雅先生”的评论

是的,是会带来更多的运维部署开销

引用来自“ice_stream”的评论

其实这里有个潜在好处,能够驱动开发测试运维的自动化.
非常赞同,我现在也感觉到了运维自动化的必要性。
zhanggt
可以理解为:微服务是SOA的最佳实践。
水贼过河
楼主你好
文章里提到的用消息队列来解决微服务相互调用的实现,能简单说明一下吗。不是很理解用消息队列怎么实现相互调用,另外这种调用方式有什么好处。

“当然某些情况无法避免微服务之间相互调用,这时候我们一般可以采用两种方式实现: 消息队列”
×
优雅先生
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: