第3章 服务拆分
微服务拆分的起点
起点?
- 既有架构的形态
终点?
- 好的架构不是设计出来的,而是进化来的
- 一直在演进…
适合微服务吗?
业务形态不适合的:
- 系统包含很多很多强事物场景
- 业务相对稳定,迭代周期长
- 访问压力不大,可用性要求不高(中小企业内部oa系统)
康威定律和微服务
康威定律
微服务和团队结构:

点餐业务服务拆分分析
如何拆分?
- 手机端、PC端?
- 订单、商品、支付?
看实际情况
服务拆分方法论
扩展立方模型
- X轴 水平复制(副本扩展,负载均衡)
- Z轴 数据分区(每个服务器负责一个数据子集,运行的代码一样)
- Y轴 功能解耦(将不同职责的模块分成不同服务)
如何拆“功能”?
- 单一职责、松耦合、高内聚
- 关注点分离
- 按职责(业务)
- 按通用性(基础组件:消息、用户)
- 按粒度级别
服务和数据的关系
- 先考虑业务功能、再考虑数据
- 无状态服务(一个数据需要多个业务共享就是有状态)
点餐业务拆分

- 业务高速发展背景下
- 新增支付渠道(目前只支持微信、以后扩展支付宝等)
- 短信、日志(作为基础服务单独抽离,如用户、redis缓存)
- 积分、优惠券…
接下来实现商品、订单业务
商品服务
知识点:
1 | - API的格式定义 |
API和SQL介绍
api
导入类目/商品表
编码实现
配置一个eureka client,工程名为product
持久层:
pom
dataobject\ProductInfo
repository\ProductInfoRepository
test
dataobject\ProductCategory
repository\ProductCategoryRepository
服务层
ProductInfo:
service\ProductInfoService
service\impl\ProductInfoServiceImpl
enums\ProductStatusEnum
test
ProductCategory:
…
控制层
定义api对应的VO对象 vo\ …
最外层:vo\ResultVO
utils\ResultVOUtils
订单服务
知识点:
1 | - 参数校验 |
api sql
业务逻辑
1 | 创建订单: |
编码
新建一个order项目
持久层
1 | dataobject |
业务层
1 | dto |
controller
1 | converter |
再看“拆数据”
如何拆数据:
- 每个微服务都有单独的数据存储(单独数据库)
- 依据服务特点选择不同结构的数据库类型
- 难点在确定边界
- 针对边界设计API
- 依据边界权衡数据冗余
第4章 应用通信
HTTP vs RPC
应用间通信方式
Dubbo:RPC框架
Spring Cloud:微服务架构下的一站式解决方案,微服务之间使用http restful方式
- http restful:轻量易用,跨平台跨语言
SpringCloud中服务间2种restful调用方式
- RestTemplate
- Feign
RestTemplate
RestTemplate:Http客户端,功能上类似于HttpClient
订单服务 –> 调用 –> 商品服务
1 | 商品:server |
RestTemplate的三种使用方式
1 | package com.mxx.order.controller; |
RestTemplateConfig
1 | package com.mxx.order.config; |
负载均衡器:Ribbon
Eureka:客户端发现
客户端负载均衡器:Ribbon
- RestTemplate
- Feign
- Zuul
@LoadBalanced会自动使用Ribbon基于某种规则(轮训、随机链接)去连接目标服务,从而使用Ribbon实现自定义负载均衡算法
Ribbon实现软负载均衡核心
- 服务发现(发现服务列表)
- 服务选择规则(如何从多个服务中选择有效服务)
- 服务监听(检测失效服务,高效剔除)
Ribbon主要组件
- ServerList
- IRule
- SererListFilter
流程:ServerList获取所有可用服务列表,SererListFilter过滤部分地址,在剩下地址中通过IRule选择一个实例作为结果
追踪源码自定义负载均衡策略
源码追踪
…
自定义负载均衡策略
1 | # 修改负载均衡的策略:由默认的轮寻改为随机 |
Feign
使用
pom
1 | <dependency> |
启动类
1 | @EnableFeignClients |
定义好要调用的接口 client
1 | package com.mxx.order.client; |
使用
1 | ("/getProductMsg") |
Feign
- 声明式REST客户端(伪RPC)
- 感知不到http调用,使用的时候像本地方法一样
- 采用了基于接口的注解
- 内部也使用Ribbon做负载均衡
业务开发:打通下单流程
知识点:
1 | @RequestBody只能用 @PostMapping |
获取商品列表、扣库存(Feign)
1 | product |
整合接口打通下单流程(Feign)
1 | OrderServiceImpl/create |
项目改造成多模块
改进:
1 | // 1、不要暴露全部ProductInfo,重新封装ProductInfoOutput |
多模块:
1 | product-server 业务逻辑(依赖common) |
同步or异步
服务间的通信分为同步 和 异步
异步:消息队列
适合异步的服务:短信服务、邮件服务
订单服务改为异步方式:
 、
消息中间件的选择:
- RabbitMQ
- Kafka
- ActiveMQ
RabbitMQ的安装
1 | # 15762: 管理界面 |
Docker和DevOps
微服务和docker代表的容器技术:天生一对
- 从系统环境开始,自底而上打包应用
- 轻量级、隔离
- 可复用,版本化
Microservice、Docker、Devops紧密相连
DevOps 是一个完整的面向IT运维的工作流,以 IT 自动化以及持续集成(CI)、持续部署(CD)为基础,来优化程式开发、测试、系统运维等所有环节
Development和Operations
软件开发人员和运维人员的沟通合作
一种理念:快速高质量交付





