微服务架构

如何完成一个产品

微服务架构指得是通过拆分业务来将不同的业务拆分为不同的服务 再通过服务之间的组合/通信来完成一个产品

什么是服务 什么是微服务

那么首先要定义的是什么是服务 一个服务实际上有两部分组成

服务的接口

Q0:该定义什么接口 这里的接口指的是服务提供的能力 即这个服务能做什么 例如一个存储服务的接口可能如下

  1. list() -> Array
  2. get(FilePath) -> File 服务的接口总是由三个部分组成
  3. 必要 接口名 如何从服务提供的众多接口中区分出这个服务 即 list和get的不同之处
  4. 可选 接口参数 当我调用这个接口时我要向其发送什么类型的参数
  5. 可选 接口返回值的类型

    如何调用接口

    Q1:如何调用接口

这里就要戴上具体实现的帽子 因为 如何调用 是和服务的具体实现绑定起来的

假设我们的存储服务是restful派的接口 即http协议 通过url+method 确定接口名 url/body/head 确定接口参数 那么调用的过程是发送http请求

假设我们的存储服务是rpc 那么调用的过程是初始化rpc对象 调用其上的方法

现在我们已经定义好了一个服务 接下来就是 想办法定义清楚如何组合服务

服务组合

服务的组合意味着交互 交互意味着我们谈论的不再是单个服务的理型 而是服务的实现

假设我们的服务/代码是完美的 每个服务都有良好的接口设计 简单易用的调用方式 代码只要写好就在也不会变化 唯一我们要思考的就是 如何让一个服务调用另一个服务 即服务通信

服务通信

Q2:服务之间如何通信 如何从一个实例到另一实例 字母代表服务 其中A是一个主入口服务 -> 表示A要和B交互才能完成A的接口

A->B 
B->C
B->D
D->C

当我们在讨论完成A服务时要考虑到A服务是和B服务组合在一起的 如何能让A服务调用B服务的接口 具体来讲 如何能让A服务的一个实例A1调用B服务的一个实例B1 再具体来讲 A服务 js React 负责处理浏览器请求渲染界面 B服务 js express + sequelize 负责同数据库交互获取数据 当B服务有可能起了多分实例做负载时 A服务项目的代码里如何写B服务的IP地址 端口

服务不可能是完美的 世上唯一不变的就是变化本身 需求变化 需求增加 业界技术升级都会导致代码的变化或者服务接口的变化 这就涉及到服务更新

服务依赖更新

接口的变化会导致其他调用此接口的服务的行为变得未知 也就是说其他服务的接口依赖于此服务的接口 实际上服务的依赖还是抽象的 现实中是

AV1->BV1
BV1->CV1
BV1->DV1
BV1->EV1
EV1->FV1

A的初始版本的接口AV1依赖B的初始版本BV1 当BV1升级成BV2时 必须要保证BV2包含BV1 或者修正A的接口 从AV1升级成AV2 使得 AV2 -> BV2 Q3:当服务升级后如何保证满足所有的服务之间的接口依赖

现实生活

现在服务定义完成 服务之间如何通信 以及如何解决服务之间的依赖也已经理清 我们又要戴上现实的帽子 如何 真的让一个个服务跑起来 Q4: 如何做无状态服务实例的负载均衡/自动容缩 Q5: 如何监控服务的状态 Q6: 当服务状态出现问题时如何通知出去 Q7: 如何管理产品版本 Q8: 产品有灰度版本 如何自动切换 如何为某些用户指定这个特殊的产品版本 Q9: 服务管理的任何一个自动流程出了问题 如何监控 如何手动恢复 Q10: 有状态的服务如何恢复

Q4-10 一个回答(workflow)可能是 A gitlab 管理项目 当 B merge到master 时自动触发 C ci 根据项目里的Docker file 打包成镜像 推到 Docker Repo 然后触发 jkenis 到kubenet管理的集群中更新此服务的Docker

编程时间

上述问题 很多都是带上运维帽子时要考虑的问题 当带上开发帽子时要考虑的实际上只有

Q0:该定义什么接口

如何划分服务 服务的职责是什么 接口名 参数 返回值

Q1:如何调用接口

这里是涉及具体的技术选型 restful/rpc/某种看上去向restful实际上当restful用的东西/某种看上去向restful实际当rpc用的东西 C服务是rpc的还好 如果是restful的B和D是不是要重复手写相同http请求

Q3:当服务升级后如何保证满足所有的服务之间的接口依赖

这里实际上是这篇blog的原因 简单的讲我希望通过某种方法在写代码时声明出服务的接口名 参数类型 返回类型 自动生成出 调用库的包 (rpc-client?) 每次代码commit时同步其他服务调用此库的状态 确定出现在此服务的接口能否满足已有服务对他的接口的要求 其他服务使用时只要调用这个服务的调用库即可 恩 为什么不用rpc呢? rpc是实现 不是服务的接口? 还能同时生成服务的依赖 和服务的文档

Q4: 如何做无状态服务实例的负载均衡/自动容缩
kubenet Q5: 如何监控服务的状态 Q6: 当服务状态出现问题时如何通知出去
kubenet+某种plugin+某种日志收集服务+某种日志分析服务+某些消息通知服务
Q7: 如何管理产品版本
gitlab+某种ci机制 Q8: 产品有灰度版本 如何自动切换 如何为某些用户指定这个特殊的产品版本
kubenet+某种分流服务 Q9: 服务管理的任何一个自动流程出了问题 如何监控 如何手动恢复
强大kubenet实践经验 Q10: 有状态的服务出问题时如何恢复
定时备份+定时备份+定时备份

日志管理