内容大纲:
- 认识微服务
- 分布式服务架构案例
- euraka注册中心
- Ribbon负载均衡原理
- nacos注册中心
1. 认识微服务
1.1 微服务架构演变
- 单体架构:
将业务的所有功能集中在一个项目中开发打包成一个包部署。
- 优点:架构简单、部署成本低k
- 缺点:耦合度高、不利于大型项目开发
- 分布式架构
根据业务功能进行拆分,每个业务模块作为独立项目开发,称为一个服务。
- 降低服务耦合
- 有利于服务升级拓展
微服务
微服务是一种经过良好架构设计及的分布式架构方案。
微服务架构的特征:
- 单一职责:
服务拆分粒度更小,每个服务多对应为为唯一的业务能力,做到每一个服务都队医唯一的业务能力,做到单一职责,避免重复业务开发。- 面向服务:
微服务对外暴漏业务接口- 自治:
团队独立、技术独立、数据独立每个服务都有独立的数据库,部署独立。- 隔离性强:
服务调用做好隔离、容错、降级、避免出现级联问题。微服务结构:
- 服务集群
- 注册中心
- 配置中心
- 服务网关
- 服务网关
微服务技术对比:
- Dubbo:
- 注册中心:zookeeper、Redis
- 服务远程调用:Dobbo协议
- 配置中心:无
- 网关服务:无
- 服务监控和保护:dubbo-admin,功能较弱
- SpringCloud:
- 注册中心:Eureka、Consul
- 服务远程调用:Feign(http协议)
- 配置中心:SpringCloudConfig
- 服务网关:SpringCloudGateway、zuul
- 服务监控和保护:Hystrix
- SpringCloudAlibaba
- 注册中心:Nacos、Eureka
- 服务远程调用:Dubbo、Feign
- 配置中心:SpringCloudConfig、Nacos
- 服务网关:SpringCloudGateway、Zuul
- 服务监控和保护:Sentinel
1.2 Spring Cloud
SpringCloud是目前国内使用最广泛的微服务框架,继承了各种微服功能组件,并基于SpingBoot实现了这些组件的自动装配,提供了开箱即用的体验。
- 服务注册发现:Eureka、Nacos、Consul
- 统一配置管理:SpringCloudConfig、Nacos
- 服务远程调用:OpenFeigin、Dubbo
- 统一网关路由:SpringCloudGateway、Zuul
- 服务链路监控:Zipkin、Sleuth
- 流控、降级、保护:Hystix、Sentinel
SpringCloud与SpringBoot的版本兼容 :
2. 服务拆分与远程调用
服务拆分注意事项:
- 不同微服务不要重复开发相同业务
- 每个微服务数据独立,不要访问其他微服务的数据库
- 微服务可以将自己的业务暴露为接口,供其他微服务调用
2.1 服务拆分案例
- 项目架构:
- 测试拆分效果
- 订单查询:
浏览器地址栏中输入:查询结果:http://localhost:8080/order/103
- 用户查询:
浏览器地址栏中输入:查询结果:http://localhost:8081/user/1
2.2 服务远程调用案例
在查询订单详情时将该订单所属用户的信息一并返回。
- 基于RestTemplete发起的http请求实现远程调用。
- http请求做远程调用是与语言无关的调用,只要知道对方的ip、端口、接口路径、请求参数即可。
- 在订单服务中注入RestTemplate
- 在订单服务的service层注入RestTemplate
- 设置用户服务的查询路径,使用RestTemplate发起HTTP请求,获得用户信息
- 将获取到的用户信息封装到订单服务查询到的信息中并返回即可
案例中存在的问题:
订单服务发起http请求调用用户服务的过程中,采用的时硬编码的形式:
如果后期调试或部署环境发生改变,需要重新修改代码等一系列后续操作,非常麻烦。
而且后续为了应对高并发的访问,服务可能会部署成多实例形成服务集群,此时硬编码就无法处理了
2.3 服务提供者与服务消费者
- 服务提供者:
一次业务中被其他微服务调用的服务- 服务消费者:
一次业务中调用其他微服务的服务。一个服务可以同时是服务提供者和服务消费者。
3. Eureka注册中心
Eureka的作用:
- Eureka-Server:注册中心,记录、管理其他微服务
- Eureka-Client:Eureka客户端,包括服务提供者和服务消费者
Eureka的运行原理:
- 每一个服务启动时都会把自己的信息注册给Eureka,Eureka将这些信息记录下来,包括服务名称、ip、端口等。
- 每个服务每隔30秒都会向服务中心发送一次心跳,向Eureka-Server确认自己的状态。如果Eureka-Server检测到某个服务不再发送心跳就会把它从列表中剔除。
- 当服务消费者需要调用其他服务时,直接去Eureka-Server注册中心拉取服务信息。
- 服务消费者从拉取到的服务信息中通过负载均衡挑取一个服务进行远程调用。
3.1 示例
搭建EurekaServer
- 创建项目,引入spring-cloud-starter-netflix-eureka-server 的依赖 。
<dependency> ><groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> <version>2.2.1.RELEASE</version> <type>pom</type> </dependency>
编写启动类,添加@EnableEurekaServer注解。
添加application.yml文件,编写配置信息
启动EurekaServer服务,在浏览器地址栏中输入 :
http://localhost:10086/
- 进入到EurekaServer页面
注册服务到EurekaServer
- 在服务项目中引入spring-cloud-starter-netflix-eureka-client的依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
- 在服务的application.yml文件中添加配置
eureka: client: service-url: # eureka的地址信息 defaultZone: http://127.0.0.1:10086/eureka
- 服务拉取
修改服务中的代码,修改访问的url路径,用服务名代替ip、端口
在服务的启动类中的RestTemplate上添加负载均衡注解。
4. Ribbon负载均衡
4.1 负载均衡原理
- 负载均衡流程:
首先服务消费者发起一个http请求,然后Ribbon将这个请求拦截下来,接着Ribbon去Eureka-server注册中心拉取服务提供者的信息,然后调取其中一个服务提供者进行远程调用。
4.2 负载均衡策略
- Ribbon的负载均衡规则是由IRule的接口来定义的,每一个子接口都是一种规则。
常见负载均衡规则:
- RoundRobinRule:
简单的轮询服务列表来选择服务器,是Ribbon的默认负载均衡规则。- ZoneAvoidanceRule:
以区域可用的服务器为基础进行服务器的选择,使用Zone对服务器进行分类。Zone可以理解为一个机房或机架等,然后对Zone内的多个服务做轮询。- AvailabilityFilteringRule:
对以下两种服务器进行忽略:
- 在默认情况下,这台服务器如果3次连接失败就会被设置为“短路”状态,“短路”状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级的增加。
- 并发数过高的服务器。
- WeightedResponseTimeRule:
为每一个服务器赋予一个权重值。服务器响应时间越长这个服务器的权重就越小,这个规则会随机选择一个服务器,这个权重值会影响服务器的选择。- BestAvailableRule:
忽略那些短路的服务器,并选择并发数较低的服务器。- RandomRule:
随机选择一个可用的服务器- RetryRule:
重试机制的选择逻辑。- 修改负载均衡规则:
- 修改全局负载均衡规则:
在服务的启动类中定义一个新的IRule:@Bean public IRule randomRule() { retuen new RandomRule(); }
- 修改指定服务负载均衡规则:
在服务消费者的application.yml配置文件中添加新的配置项:userservice: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalance.RandomRule
4.3 懒加载
Ribbon默认采用的是懒加载,第一次访问时才会去创建LoadBalanceClient,请求时间会很长。
饥饿加载则会在项目启动时创建,降低第一次访问的耗时。
- 通过修改服务消费者的application.yml配置文件来指定服务提供者开启饥饿加载:
ribbon: eager-load: enabled: true clients: userservice
5. Nacos注册中心
5.1 认识Nacos
Nacos是阿里巴巴的产品,是SpringCloud中的一个组件,相比Eureka注册中心功能更加丰富。
- Nacos服务搭建
- 下载Nacos安装包并解压到本地(目录中不要包含中文)
- 可执行包在target下:
- 配置文件:conf --> application.properties默认端口为8848。
- 启动脚本:
- 访问Nacos
- 登录Nacos,默认用户名和密码都是nacos
- Nacos服务注册或发现
- 修改maven依赖
在父工程中添加spring-cloud-alibaba的管理依赖:
在微服中添加nacos的客户端依赖:
orderservice:
userservice:
- 修改配置文件
orderservice:
userservice:
- 重启微服务并访问Nacos注册中心的服务列表:
- 测试服务的发现
访问order:
5.2 Nacos的服务分级存储模型
一个服务可以包含多个实例,随着业务规模的不断扩大,实例的数量也会增加,为了规避意外情况造成服务不可用的问题,通常会进行容灾处理,将实例分布在不同地域的机房中,同在一个机房的实例称为一个集群。
5.3 服务跨集群调用问题
访问本地的微服务的速度较快,跨集群调用的延迟会很高。
本地集群不可访问时再去访问其他集群。
5.4 设置服务集群属性
- 修改配置文件,添加如下内容:
orderservice:HZ集群
> userservice:SH 集群
userservice:HZ 集群
- 重启Nacos, 在Nacos控制台可以看到集群变化:
userservice有HZ,SH,两个集群:
orderservice有HZ集群:
5.5 根据集群负载均衡
- NacosRule负载均衡策略:
- 优先选择同集群服务实例列表
- 本地集群找不到提供者才去其他集群寻找,并且会报警告
- 确定了可用实例列表后再采用随机负载均衡挑选实例
- 在order-service中设置负载均的IRule为NacosRule,这个规则会优先寻找与自己同一集群的服务:
- 在浏览器中多次访问orderservice进行测试:
orderservice日志内容:
userservice SH集群日志:
userservice HZ集群日志:
5.6 根据权重负载均衡
Nacos提供了权重配置来控制访问频率,权重越大访问频率越高
- 在Nacos控制台可以设置实例的权重值,首先选中实例后面的编辑按钮
- 修改权重
5.7 环境隔离 - namespace
Nacos 中服务存储和数据存储的最外层是namespace,用来做最外层隔离。
每个namespace都有唯一id,不同namespace下的服务不可见。
- 在Nacos控制台创建namespace,用来隔离不同环境:
- 修改微服务的配置文件,添加namespace:
5.8 nacos注册中心细节
- 服务提供者将自己的信息注册到nacos注册中心
- 服务消费者定时去nacos注册中心拉取(pull)信息并存储到服务缓存列表中
- nacos将服务提供者分为临时实例和非临时实例,默认情况下所有的实例都是临时实例。临时实例采用的是心跳检测,服务提供者每隔一段时间发一个请求到nacos注册中心,当提供者不再发送时nacos注册中心就会将将这实例剔除。非临时实例不会进行心跳检测,而是由nacos主动发请求询问,如果服务提供者无响应,nacos注册中心不会将它剔除,而是等它恢复健康。
- nacos会主动向服务消费者推送(push)变更消息。
- 配置临时实例和非临时实例:修改配置文件
5.9 Nacos 与 eureka
- 共同点:
- 都支持服务注册和服务拉取
- 都支持服务提供者心跳方式做健康检测
- 区别:
- Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式(主动检测会对服务器造成压力)
- 临时实例心跳不正常会被剔除,非临时实例不会被剔除
- Nacos支持服务列表变更的消息推送模式,服务列表更新及时
- Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;Euerka采用AP方式。