微服务的基本概念、设计及拆分原则
什么是微服务
单体应用痛点:
①项目庞大,可能使用几十张表,结构关系比较复杂
②容易出现尾大不掉的情况
③代码风格及组件不统一
④技术难以升级
什么是服务化
①拆分:将大而全的程序拆分为小而美的模块
②独立:模块间彼此独立,独立部署,职责分明
③通信:模块间使用API调用,不关心彼此实现
什么是微服务
①以专注于单一职责与功能的小型功能区为基础
②利用模块化方法组合成一个大型复杂系统
③各模块之间使用与语言无关的API集相互通信
微服务优势
①技术不受限,新技术有发展空间
②可用性强,一个模块宕机不会整体宕机
③代码及机器使用率上升
微服务缺点
①运维成本高
②接口可能不匹配
③代码可能重复
④架构复杂度高
微服务的特点
①技术栈自由
②按需弹性扩容
③能力复用率高
④部署和回滚成本低
⑤康威定律:微服务导致组织结构发生变动
微服务与SpringCloud关系
微服务分为两大门派:
- SpringCloud:由Spring众多子项目组成的
- Dubbo:高性能-轻量级的开源框架
Dubbo提供的功能实际上是SpringCloud的子集,Dubbo通信协议采用RPC通信,所以效率比较高,SpringCloud使用的是REST,所以更加灵活。从生态上看,SpringCloud的迭代速度,稳定性,生态稍稍好一点 ,但是Dubbo目前属于Apache,所以也还可以。
那么我们如何选型呢?实际上就考虑团队里针对于技术的熟悉程度。
微服务拆分
微服务拆分的信号:
- 事故频发,且原因是耦合导致的
- 服务启动/部署越来越慢
- 流量增加,需要扩容
不适合拆分的场景
- 为了拆分而拆分
- 系统要求变动和维护成本低
- 团队规模小,人数少于5个
如何拆分
- 按照领域拆分
- 热点拆分(按照压力不同拆开)
- 业务拆分,逐步迭代
- 统筹安排,全局考虑
服务拓展的几种方式
- 单体集群,水平复制
- 微服务:功能解耦
-
数据拆分:分库分表
按需拓展:可能合理利用CPU,内存,网络负载程度,在特定时间拓展服务,这种方式具有最佳使用率,节省成本
微服务常见组件及功能(重点)
- 服务注册与发现
- 微服务之间的调用
- 负载均衡
- 网关
- 熔断与降级
微服务实战
基本介绍
SpringCloud定位
成熟的微服务框架框架,定位为开发工具,以便于快捷构建分布式系统
核心组件
- 服务注册中心:SpringCloud NetFlix Eureka
- 服务调用方式:RestAPI,Feign,ribbon
- 服务网关:Spring Cloud Netflix Zuul
- 断路器:Spring Cloiud Netflix Hystrix
架构介绍
项目整体设计分为业务模块:课程列表,课程价格;微服务相关的包括:网关,注册中心等
接口设计
包括课程列表模块的一个课程查询,价格模块的价格查询以及feign调用列表模块获取课程并查询出对应课程价格的组合接口
分模块构建
分布式架构搭建流程:
- 新建Spring Boot项目
- 删除Src目录
- 新建module,建立maven项目
- 删除src目录
- 分别新建列表模块,价格模块
Course-list模块搭建
- 新建目录
- 建立Application,加上@SpringApplication注解,表示Springboot项目启动
-
引入依赖:
spring-boot-starter-web(SpringBoot需要)
mysql-connector-java(mysql需要)
mybatis-spring-boot-starter(mybatis需要)
maven插件(spring-boot-maven-plugin) - resources引入配置文件application.properties
- 正常开发SpringBoot项目
-
注意点:
开启驼峰配置
@Mapper引入时有爆红,是因为引入mybatis注解版本不对导致
course-price搭建
搭建同course-list
开发实现
详情见
gitee
服务整合、注册与发现
Eureka
当没有Eureka之前,接口的调用一般使用rest接口,此时就有一个问题,访问接口需要配置号ip地址,但是微服务架构时,可能存在多实例部署,且会出现ip变化情况,此时ip写死就比较麻烦。
此时,就不得不举出另一个例子——医院总机,问哦们不需要记住所有部门的电话,所有电话都在医院总机,我们找任何一个部门都只需要找到总机即可。
Eureka架构
服务提供者在注册中心注册上服务,服务调用方从注册中心获取地址,然后实际访问服务提供方。
微服务引入Eureka
-
引入依赖
引入Spring Cloud
引入Eureka(eureka服务端引入 spring-cloud-starter-netflix-eureka-server、client端引入spring-cloud-starter-netflix-eureka-client)
2.配置文件:详情见gitee代码
3.启动注解(eureka端增加注解:@EnableEurekaServer)
4.注意点:SpringBoot与SpringCloud版本保持一致,否则会报错,注册不上
module转为Eureka的client
- 引入eureka-client依赖
- 新加eureka.client.service-url.defaultZone=http://localhost:8000/eureka/,与eureka-server地址保持一致
整合Feign实现服务间调用
SpringCloud中默认使用Http调用(比较复杂),我们引入微服务的目的是为了方便,简洁,而不是使得服务调用越来越复杂,所以在这里引入了Feign调用。
集成Feign
- 引入依赖:Spring-Cloud-starter-openfeign
- 增加配置文件:负载均衡配置
- 启动类增加注解:@EnableFeignClients
- 建立客户端:建包,建立调用类,类头上增加@FeignClient注解
- Controller调用feignClient
利用Ribbon实现负载均衡
负载均衡的策略:(com.netflix.loadbalancer)
- RandomRule:随机策略
- RandomRobinRule:轮询策略
- ResponseTimeWeightedRule:加权,根据每个service的平均响应时间来分配
配置不同的负载均衡策略
application配置文件增加配置:
前面
course-list
是调用的注册到eureka的server-id,
com.netflix.loadbalancer.RoundRobinRule
是策略
course-list.ribbon.NFLoadBanlancerRuleClassName=com.netflix.loadbalancer.RoundRobinRule
服务的熔断与降级,并实操演练
利用Hystrix实现断路器,步骤如下:
- 配置文件增加配置:feign.circuitbreaker.enabled=true
- 引入依赖:spring-cloud-starter-netflix-hystrix(调用方)
- 启动类增加注解@EnableCircuitBreaker
- 编写熔断处理代码,调用异常时有备用返回
网关的集成与开发,并接入服务
网关使用Zuul,主要用作身份验证,安全处理等
集成Zuul
- 把自己注册到注册中心
-
引入依赖
spring-cloud-starter-netflix-eureka-client
spring-cloud-starter-zuul
引入plugin-maven -
增加注解(网关微服务上)
@EnableZuulProxy
@SpringCloudApplication
4.配置对应路由地址
#统一前缀
zuul.prefix=/imooc
#映射地址
zuul.routes.course-list.path=/list/**
#服务id
zuul.routes.course-list.service-id=course-list
zuul.routes.course-price.path=/price/**
zuul.routes.course-price.service-id=price-list
利用网关开发过滤器
过滤器类型:
- pre:请求调用亲自
- route:调用中
- post:请求后
- error:异常时
开发过滤器
1.新建过滤器继承ZuulFilter
2.开发对应业务逻辑