文章目录
spring cloud
集成多种工具,解决微服务中的各种问题
-注册和发现
Nacos
Eureka
-远程调用 - OpenFeign
负载均衡
重试
-系统容错和限流 - Sentinel, Hystrix
降级
熔断
-错误监控 - Hystrix Dashboard、Turbine
-配置中心 - Nacos、Config
-链路跟踪 - Sleuth、Zipkin
1.搭建 springcloud 业务模块
新工程的 Maven 配置
File - New project settings - settings for new projects
这里配置配置好,每次新建工程,都应用这个配置
1.新建 Empty project 工程: springcloud1
2.新建 Maven 模块: sp01-commons — 存放业务模块中的通用代码
3.pom.xml 添加依赖(从笔记复制)
4.代码
1)商品、用户、订单实体类
2)三个业务接口
3)三个工具类:cookie工具、json工具、封装响应数据的工具
商品模块
1.新建 spring 模块:sp02-itemservice
2.添加 web 依赖
3.pom.xml
springboot 版本:2.3.2.RELEASE
添加 sp01-commons 依赖
4.yml
5.Service
6.Controller
2.注册中心
微服务系统的核心服务
-所有模块启动,都向注册中心注册
-模块之间互相调用,要从注册中心互相发现
常用的注册中心: nacos、eureka、zookeeper、etcd、consul …
2.1搭建eureka注册中心
1.新建 spring 模块: sp05-eureka
2.添加 eureka server 依赖
3.pom.xml 调整版本:
springboot: 2.3.2.RELEASE
springcloud: Hoxton.SR6
4.yml
禁用自我保护模式
主机名
针对单台服务器,不向自己注册,不从自己拉取
5.启动类的注解: @EnableEurekaServer
通过注解来触发自动配置
2.2eureka客户端
修改 2,3,4
1.添加 eureka client 依赖
2.yml 配置 eureka 服务器连接地址
3.(可选) 启动类添加@EnableDiscoveryClient
2.3eureka四条运行机制
1.注册
客户端会一次一次反复连接服务器进行注册,直到注册成功为止
2.拉取
客户端每30秒拉取一次注册表,来刷新注册表
3.心跳
客户端每30秒发送一次心跳,如果服务器连续三次收不到一个服务的心跳,会删除这个服务
4.自我保护模式
由于网络不稳定,网络中断,15分钟内,85%服务器出现心跳异常,就会进入自我保护模式
-在这种特殊情况下,所有服务都不删除
-网络恢复正常后,可以自动退出保护模式
-开发调试期间,可以禁用保护模式,避免影响测试
2.4item 商品的高可用
启动命令行参数:java -jar item.jar --server.port=8001
右键点商品的启动配置 – edit configuration
在 program arguments 中填 --server.port=8001
右键点商品的启动配置 – copy configuration
端口改成 8002
3.服务间的远程调用
订单服务远程调用商品和用户
添加 Feign,用Feign的声明式客户端接口做远程调用
1.pom.xml 添加 Feign 依赖
2.启动类添加注解: @EnableFeignClients
3.定义两个客户端接口
-ItemClient
-UserClient
4.修改 OrderServiceImpl 完成远程的调用
3.1Feign 集成了 Ribbon,实现负载均衡和重试
-默认已经启用负载均衡和重试
3.2 Ribbon 重试
远程调用后台服务失败时,可以自动重试调用
-失败: 出现异常、一台服务器宕机、阻塞延迟超时
-重试参数:
MaxAutoRetries: 单台服务器重试次数,默认值是 0
MaxAutoRetriesNextServer: 更换服务器的次数, 默认值是 1
ReadTimeout: 等待响应的超时时间,默认值是 1000
OkToRetryOnAllOperations: 是否对所有请求方式都重试,默认只对GET重试
ConnectTimeout: 与后台服务器建立网络连接的超时时间
4.API 网关
Zuul
-统一的调用入口
-统一的权限校验
-集成 Ribbon
-集成 Hystrix
4.1统一的调用入口
1.新建 spring 模块: sp06-zuul
2.添加依赖: zuul、eureka client、sp01
3.yml
#转发规则
#service-id 作为访问子路径是默认配置,zuul会根据注册表完成自动配置
#最好手动配置,防止注册表不全
zuul:
routes:
item-service: /item-service/**
user-service: /user-service/**
order-service: /order-service/**
4.启动类注解: @EnableZuulProxy
4.2统一的权限校验
通过Zuul的过滤器,判断用户权限
-有权限,继续转发调用
-没有权限,从网关直接返回结果
http://localhost:3001/item-service/u56y5g4 没登录,不允许访问
http://localhost:3001/item-service/u56y5g4?token=u6y54t 已登录,可以访问
1.继承ZuulFilter
2.添加 @Component, Zuul的自动配置类,可以从 spring 容器自动发现过滤器实例,完成自动配置
package cn.tedu.sp06.filter;
import cn.tedu.web.util.JsonResult;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Component
public class AccessFilter extends ZuulFilter {
//pre, routing ,post,error
@Override
public String filterType() {
//return "pre";
return FilterConstants.PRE_TYPE;
}
//过滤器的顺序号,
@Override
public int filterOrder() {
//有5个默认的过滤器,我们放在第6位
return 6;
}
//针对当前请求,判断是否要执行过下一个方法的滤代码
//如果调用item-service,检查是否登录
//否则,不检查,直接访问
@Override
public boolean shouldFilter() {
//先获取当前请求的上下文对象
RequestContext ctx = RequestContext.getCurrentContext();
//当前请求,调用的服务ID
String serviceId = (String)ctx.get(FilterConstants.SERVICE_ID_KEY);
//调用的是是否是item-service,是的话返回true
return "item-service".equals(serviceId);
}
//过滤代码,权限认证
@Override
public Object run() throws ZuulException {
//获取上下文对象
RequestContext ctx = RequestContext.getCurrentContext();
//获得re