介绍了本次微服务重构的服务拆分原则和系统整体架构,今天我们来看下微服务系统各个基础组件的技术选型,这也是我们在开始开发前需要调研和规划好的。
在此之前,我们可以先回顾下微服务架构总体设计和基础组件这篇教程中对微服务必备基础组件的介绍,然后以此为纲要进行调研。
服务框架
所谓服务框架指的是后端提供微服务接口的 RPC 框架,由于我们本次重构选择的是 Go-Micro 框架,所以,我们可以使用 Go-Micro 内置的 RPC 框架对外提供服务。
通信编码
经过微服务重构后,客户端应用(这里是基于 PHP 开发的电商系统)与微服务、微服务与微服务之间的服务调用都变成了网络调用,所以势必涉及到通信数据的编码和解码,这里我们仍然使用 Go-Micro 内置的 Codec 组件提供的编解码功能,在 PHP 应用与 Go 微服务之间通过基于 JSON 编码的 REST API 进行通信,微服务与微服务之间的服务调用则通过 Protobuf 进行编码,关于两者之间的区别,前面介绍 Protobuf 的时候已经提及,从性能来说,Protobuf 更优,但是 JSON 格式编码可读性更好,在客户端应用与 Go 微服务之间选择这种编码方便调试和排错。
服务描述
服务描述指的是服务接口的描述,这里我们统一通过 Swagger 对所有微服务接口进行管理和维护。
服务网关
服务网关介于客户端应用与微服务之间,是连接客户端与服务端的桥梁,在 PHP 应用与微服务之间我们通过 HTTP API 网关进行通信,在微服务与微服务之间我们通过 gRPC 网关进行通信,同样,Go-Micro 内置了对这些 API 网关的支持。
消息系统
Go-Micro 通过 Broker 组件内置了对事件驱动的异步消息通信的支持,并且我们可以灵活选择不同的消息系统提供后端驱动,这里我们选择 NATS 作为消息系统,此外,你还可以通过 Go-Micro Plugins 引入其它消息系统驱动,比如 RabbitMQ、Kafka 等。
数据库存储
我们将选用 MySQL 作为数据库存储系统,同时通过 gorm 实现 Go 语言与数据库之间的交互,为了简化系统,这里我们不会做分布式数据库部署,而是将不同微服务对应的数据库存放到一个数据库服务器上,关于分布式数据库的话题将留到后续分布式系列教程中去介绍。
服务发现
拆分出多个微服务后,客户端调用远程服务时会涉及到服务路由与发现的问题,我们在本次重构中选择 Consul 作为服务发现的注册中心,Go-Micro 也内置了对此驱动的原生支持,当某个服务启动时会将服务注册进来,客户端通过订阅注册中心,可以及时感知服务端变化,准确访问到某个服务对应的服务器,另外 Consul 还可以兼具 Key/Value 存储配置中心的功能。
负载均衡
负载均衡是为了提高系统的可用性,可以进一步细分为服务端负载均衡和客户端负载均衡,这里服务端负载均衡我们使用 Go-Micro 内置 Selector 组件的负载均衡机制(Random + Cache),客户端负载均衡指的是将这个负载均衡策略下放到客户端去实现,显然服务端负载均衡更简单一些,不需要我们做额外开发。
服务监控
服务监控我们选择引入第三方组件进行可视化管理,这里选择的方案是结合 Prometheus 和 Grafana 实现,前者用于存储监控样本数据源,后者提供对监控数据的可视化展示。
服务治理
服务治理指的是通过一系列手段来保证在各种意外情况下,微服务调用仍然能够正常进行,这些手段包括熔断、隔离、限流、降级、负载均衡等,这里我们选择引入开源的 hystrix-go 和 go-resiliency 来实现,前者是 Netflix 开源库 hystrix 的 Go 语言版本,集流量控制、熔断、容错等功能于一身,被誉为“雪崩利器”,后者可提供重试功能,是弹性模式的 Go 语言实现。
服务追踪
服务追踪用于对每个请求调用的分布式完整服务链路进行记录,从而方便问题定位和故障分析,这里我们选择引入开源的分布式追踪系统 ZipKin实现服务追踪。
自动化测试
在本次重构中,我们使用 GoConvey 编写行为测试代码,并集成 CircleCI 进行自动化测试。
自动化部署
最后,我们将通过 Docker + Kubernetes 对微服务进行容器化编排和自动化部署。