Eureka注册中心
微服务远程调用
Eureka
-提供者与消费者
-
服务提供者:一次业务中,被其他微服务调用的服务。【提供接口给其他微服务】
-
服务消费者:一次业务中,调用其他微服务的服务。【调用其他微服务提供的接口】
-
提供者与消费者角色其实是相对的
Eureka的作用
在Eureka架构中,微服务角色有两类:
EurekaServer:服务端,注册中心
-
记录服务信息
-
心跳监控
EurekaClient:客户端
1. Provider:服务提供者
-
注册自己的信息到EurekaServer
-
每隔30秒向EurekaServer发送心跳
2. Consumer:服务消费者
-
根据服务名称从EurekaServer拉取服务列表
-
基于服务列表做负载均衡,选中一个微服务后发起远程调用
EurekaServer搭建
注册eureka
在order-service完成服务拉取
服务拉取是基于服务名称获取服务列表,如何在对服务列表做负载均衡
小结
Ribbon负载均衡
负载均衡流程
负载均衡策略
内置负载均衡规则类 | 规则描述 |
---|---|
RoundRobinRule | 简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则 |
AvailabilityFilteringRule | 对以下两种服务器进行忽略:(1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级的增加。(2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvaliabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上线,可以由客户端的<clientName>.<clientConfigNameSpace>.ActiveConnectionsLimit属性 |
weightedResponseTimeRule | 为每个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。 |
ZoneAvoidanceRule | 以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房,一个机架等。而后在对Zone内的多个服务器做轮询 |
BestAvailableRule | 忽略哪些短路的服务器,并选择并发数较低的服务器 |
RandomRule | 随机选择一个可用的服务器 |
RetryRule | 重试机制的选择逻辑 |
通过定义IRule【高版本Cloud已弃用】实现可以修改负载均衡规则,有两种方式:
-
代码方式:定义一个新的IRule
-
配置文件方式:
userservice: ribbon: NFloadBalancerRuleClassName: com.netflix.loadbalancerr.RandomRule #负载均衡规则
饥饿加载
Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长
而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面的配置开启饥饿加载:
ribbon:
eager-load:
enabled: true #开启饥饿加载
clients: userservice #指定对userservice这个服务饥饿加载
Nacos注册中心
认识Nacos
Nacos是阿里巴巴的产品,现在是SpringCloud中的一个组件。相比于Eureka功能更加丰富,在国内受欢迎程度较高
Nacos服务分级存储模型
-
Nacos服务分级存储模型
-
一级是服务,例如userservice
-
二级是集群,例如杭州。上海
-
三级是实例,例如杭州机房的某台部署userservice的服务器
-
如何设置实例的集群属性
修改application.yml文件,添加spring.cloud.nacos.discovery.cluster-name属性即可
Nacos负载均衡策略
NacosRule负载均衡策略
-
优先选择同集群服务实例列表
-
本地集群找不到提供者,才回去其他集群中寻找,并且会报警告
-
确定了可用实例列表之后,再采取随即负载均衡挑选实例
在applicatio.yml设置负载均衡的IRule为NacosRule,这个规则优先会寻找与自己同集群的服务:
userservice #服务名称
ribbon:
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule #负载均衡规则
根据权重负载均衡
-
在Nacos控制台可以设置实例的权重值,首先选中实例后面的编辑按钮
实例的权重控制
-
Nacos控制台可以设置实例的权重值,0~1之间
-
同集群之间的多个实例,权重越高被访问的频率越高
-
权重设置为0则完全不会被访问
环境隔离 -namespace
Nacos中服务存储和数据存储的最外层都是一个名为namespace的东西,用来做最外层隔离
-
namespace用来做环境隔离
-
每个namespace都有唯一id
-
不同namespace下的服务不可见
Nacos和Eureka的对比
-
Nacos与eureka的共同点
-
都支持服务注册和服务拉取
-
都支持服务提供者心跳方式做健康检测
-
-
Nacos和Eureka的区别
-
Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式
-
临时实例心跳不正常会被剔除,非临时实例则不会被剔除
-
Nacos支持服务列表变更的消息推送模式,服务列表更新更及时
-
Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP方式;Eureka采用AP方式
-
Nacos配置管理
统一配置管理
将配置交给Nacos管理的步骤
-
再Nacos中添加配置文件
-
在微服务中引入nacos的config依赖
-
在微服务中添加bootstrap.yml ,配置nacos地址、当前环境、服务名称、文件后缀名。这些决定了程序启动时nacos读取哪个文件
注:如果启动时报错,需要再pom.xml文件中添加如下依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
配置热更新
Nacos中的配置文件变更后,微服务无需重启就可以感知。不过需要通过下面两种配置实现:
方式一:
在@Value注入的变量所在类上添加注解@RefreshScope
方式二:
使用@ConfigurationProperties注解
总结:
多种配置的优先级:
服务名-profile.yaml > 服务名称.yaml > 本地配置
nacos集群搭建:
见nacos集群搭建
HTTP客户端Feign
Feign是一个声明式的http客户端,其作用就是帮助我们优雅的实现http请求的发送。
定义和使用Feign客户端
使用Feign的步骤如下:
-
引入依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
-
在需要的启动类上添加@EnableFeignClients 开启Feign的功能
-
编写Feign客户端
主要是基于SpringMVC的注解来声明远程调用的信息,比如:
-
服务名称:userservice
-
请求方式:GET
-
请求路径:/user/{id}
-
请求参数:Longd id
-
返回值类型: User
自定义Feign的配置
类型 | 作用 | 说明 |
---|---|---|
feign.Logger.Level | 修改日志级别 | 包含四种不同的级别:NONE、BASIC、HEADERS、FULL |
feign.code.Decoder | 响应结果的解析器 | http远程调用的结果做解析例如解析json字符串为Java对象 |
feign.code.Encoder | 请求参数编码 | 将请求参数编码,便于通过http请求发送 |
feign.Contract | 支持的注解格式 | 默认是SpringMVC的注解 |
feign.Retryer | 失败重试机制 | 请求失败的重试机制,默认是没有,不过会使用Ribbon的重试 |
一般我们需要配置的就是日志级别
配置Feign日志有两种方式:
方式一:配置文件方式
方式二:Java代码的方式,需要先声明一个Bean:
Feign的性能调优
Feign底层的客户端实现:
-
URLConnection:默认实现,不支持连接池
-
Apache HttpClient:支持连接池
-
OKHttp:支持连接池
因此优化Feign的性能主要包括:
-
使用连接池代替默认的URLConnection
-
日志级别,最好用basic或者none
Feign的性能优化-连接池配置
Feign添加HttpClient的支持
Feign的最佳实践
-
方式一(继承):给消费者的FeignClient和提供者的controller定义统一的父接口作为标准
-
方式二(抽取):将FeignClient抽取为独立模块,并且把接口有关的POJO、默认的Feign配置都放到这个模块中,提供给所有消费者用
当定义的FeignClient不在SpringBootApplication的扫描包范围时,这些FeignClient无法使用。有两种方式解决:
统一网关Gateway
网关的功能:
-
身份认证和权限校验
-
服务路由、负载均衡
-
请求限流
网关的技术实现
在SpringCloud中网关的实现包括两种:
-
gateway
-
zuul
Zuul是基于Servlet的实现,属于阻塞时编程。而SpringCloudGateway则是基于Spring5中提供的WebFlux,属于响应式编程,具备更好的性能
搭建网关服务
步骤:
-
创建一个新的module,引入SpringCloudGateway的依赖和nacos的服务发现依赖:
-
编写路由配置即nacos地址
3.
搭建网关服务
路由断言工厂Route Predicate Factory
网关路由可以配置的内容包括:
-
路由id:路由的唯一标识
-
uri:路由目的地,支持lb和http两种
-
predicates:路由断言,判断请求是否符合要求,符合则转发到路由目的地
-
filters:路由过滤器,处理请求响应
我们在配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断的条件
Spring提供了11种基本的Predicate工厂:
路由过滤器(GatewayFilter)
GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理:
Spring提供了31种不同的路由过滤器工厂。例如:
全局过滤器 GlobalFilter
全局过滤器的作用是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样。
区别在于GatewayFilter通过配置定义,处理逻辑是固定的。而GlobalFilter的逻辑需要自己写代码实现。
定义方式是实现GlobalFilter接口
小结
-
全局过滤器的作用是什么?
-
对所有路由都生效的过滤器,并且可以自定义处理逻辑
-
实现全局过滤器的步骤?
-
实现GlobalFilter接口
-
添加@Order注解或实现Ordered接口
-
编写处理逻辑
过滤器的执行顺序
请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter
请求路由后,会将当前路由过滤器和DefaultFilter、GlobbalFilter,合并到一个过滤器链【集合】中,排序后依次执行每个过滤器
-
每一个过滤器都必须指定一个int类型的order的值,order值越小,优先级越高,执行顺序越靠前。
-
GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order的值,由我们自己指定。
-
路由过滤器和defaultFilter的order由Spring指定,默认按照声明的顺序从1递增。
-
当过滤器的order的值是一样时,会按照 defaultFilter > 路由过滤器 > GlobalFilter顺序执行。
跨域问题处理
跨域: 域名不一致就是跨域,主要包括:
-
域名相同,端口不同:localhost:8080和localhost8081
跨域问题:浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题
解决方案:CORS
网关处理跨域采用的同样是CORS方案,并且只需要简单配置即可实现: