作者: http://dockone.io/people/hokingyang
原文链接:
微服务实战(一):微服务架构的优势与不足
微服务实战(二):使用API Gateway
微服务实战(三):深入微服务架构的进程间通信
微服务实战(四):服务发现的可行方案以及实践案例
微服务实践(五):微服务的事件驱动数据管理
微服务实践(六):选择微服务部署策略
微服务实践(七):从单体式架构迁移到微服务架构
微服务的优势是解耦,对开发运维效率和系统运行效率都有极大的提升。
微服务相比单体式应用的问题本质上是多进程编程对比单进程编程*的问题。
解决单机多进程的经验,如IPC、消息队列和mmap等在微服务中都能得到实践。
每个服务单独使用一个database,这为数据库CAP带来挑战。
例如,一个用户完成一笔消费,同时影响购物车/推荐系统/评论系统等的数据.在单体式应用容易实现一致性,分布式微服务必须使用RPC或消息队列等通讯机制,开销增大。
从某个角度来看, 我们从代码段落到函数再从面向过程到面向对象为的就是解耦,为了不做重复的工作. 一切都是为了当工程量日益增大时, 多个程序员之间的高效协同开发.
举个例子, 当个人程序员开发的时候,遇到重复代码,可能会先想着把代码块打包成函数, 仅暴露参数与返回值即可. 此时随着函数的体量越来越大,我们可以打包成python中的模块(module)或者java中的包(package),然后在每个工程当中引入模块或包即可.
但此时,随着工程数目的增加,相当于每一份工程代码当中都有大量的重复模块(例如, 可能都在从一个数据库里取一些基本数据并进行格式化),运行时来考虑的话就是每个进程当中都有相当一部分时间在做同样的事情. 并且最大的问题在于模块需要修改的时候,将直接影响到每一个工程.
因此,微服务的要点就是实现一个服务对应一个进程, 以进程来作为模块的隔离边界得到充分的解耦. 当模块需要改动时, 只需要保证调用的接口不变(参数与返回值),直接在单个服务上改动就可以完成升级.
可以说, 微服务的其他特征, 如运维部署和分布式通信方面的特点, 都是由"一个服务对应一个进程"这个特点带来的.
问题1: 客户端的需求量与每个微服务暴露的细粒度API数量的不匹配.
每个服务使用一个URL,一个client的WEB UI或者APP需要发起数十个HTTP请求,网络开销大.
问题2: 后端微服务的重构都需要客户端进行改动,特别是将一个微服务拆分成多个时,前端改动大.
使用一个GATEWAY为客户端统一服务.
GATEWAY还可能有其他功能,如授权、监控、负载均衡、缓存、请求分片和管理、静态响应处理等.
实现: GATEWAY以单个页面的需求进行定制化,选择性地挑选页面需要的服务,对客户端封装调用服务的过程,API GATEWAY是一个粗粒度的REST API.
难点: 保证API GATEWAY的高可用.API GATEWAY作为统一入口,需要负担高性能和可拓展的责任.
对客户端隐藏微服务耦合结构,各服务间需要通信.
解决两个问题:
是: 同步,例如,购物车获取商品信息.
否: 异步,例如,商品加入购物车,推荐系统获得商品信息,给出推荐结果.例如,发布打车请求后回到地图页面,服务端异步地把打车请求分发给附近的司机.
• 发布/ 订阅模式:客户端发布通知消息,被零个或者多个感兴趣的服务消费。
• 发布/异步响应模式:客户端发布请求消息,然后等待从感兴趣服务发回的响应。
上图中的服务通信使用了通知、请求/响应、发布/订阅等方式。例如,乘客通过移动端给『行程管理服务』发送通知,希望申请一次出租服务。『行程管理服务』发送请求/响应消息给『乘客服务』以确认乘客账号是有效的。紧接着创建此次行程,并用发布/订阅交互模式通知其他服务,包括定位可用司机的调度服务。
定义API需要考虑新旧版本同时运行.
实现1: 规定缺省响应值,客户端对于响应默认不处理.
实现2: URL加入版本号使不同版本API共存.
API GATEWAY的失败为线程失败: 会影响整体进程.
解决方案:
异步: 消息队列
同步: RPC/REST/Thrift
问题描述:
在客户端与服务之间加上一层服务注册层管理服务. 在客户端实现负载均衡,查看可用服务,决定请求地址.
服务实例的网络位置是在启动时注册到服务注册表中,并且在服务终止时从注册表中删除。服务实例注册信息一般是使用心跳机制来定期刷新的。
最大的缺点是需要针对不同的编程语言注册不同的服务,在客户端需要为每种语言开发不同的服务发现逻辑。(?未理解)
客户端通过负载均衡器向某个服务提出请求,负载均衡器向服务注册表发出请求,将每个请求转发往可用的服务实例。跟客户端发现一样,服务实例在服务注册表中注册或者注销。
简而言之,将客户端实现的功能搬到负载均衡器实现.
服务实例注册和注销主要有两类方式。
使用DNS绑定<域名,IP地址>实现动态发现服务地址. NGINX Plus支持.
微服务框架中各服务维护各自database,事务操作的ACID如今没法保障.
在多个服务之间找到通讯方式,把事务操作抽象为具体的事件,如创建订单,发起付款和点赞等. 由事件发起,触发相关的服务发布另一个事件,并更新自身数据库.
和虚拟机相比,如Docker这类容器技术拥有很多优势.
容器技术离宿主操作系统更近,各个不同容器之间共享内核态操作系统,只在用户态操作系统有各自的沙盒,安全性会收到一定程度上的考验,但是一般使用都不会有这类问题.
不做大规模迁移,逐步分离直到单体式架构被完全替代或自身成为微服务一部分.
微服务有三种方式访问单体应用数据:
使原有单体式框架逐步架空, 随着抽离程度越高,服务化会越来越容易.