赞
踩
目录
配置启动参数 --spring.profiles.active 和 --server.port
- 注册
客户端一次次的反复连接注册中心进行注册,直到注册成功为止
- 拉取
客户端每30秒拉取一次注册表,刷新注册表
- 心跳
客户端每30秒发送一次心跳数据,如果服务器端连续三次收不到一个服务的心跳,会删除它的注册信息
- 自我保护模式
- 由于网络故障,15分钟内,85%服务器出现心跳异常,会自动进入自我保护模式
- 保护所有注册信息不删除
- 等待网络恢复后,可以退出保护模式,恢复正常
- 开发调试期间应该关闭保护模式,避免影响测试
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
- </dependency>
- spring:
- application:
- name: eureka-server
-
- server:
- port: 2001
-
- eureka:
- server:
- enable-self-preservation: false
- instance:
- hostname: eureka1
- client:
- register-with-eureka: false
- fetch-registry: false
-

启动类添加@EnableEurekaServer
注解
C:\Windows\System32\drivers\etc\hosts
添加内容
- 127.0.0.1 eureka1
- 127.0.0.1 eureka2
在pom.xml中添加以下依赖
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
- </dependency>
application.yml 添加 eureka注册配置
- eureka:
- client:
- service-url:
- defaultZone: http://eureka1:2001/eureka
启动类添加@EnableDiscoveryClient注解
application-eureka1.yml
- eureka:
- instance:
- hostname: eureka1
- client:
- register-with-eureka: true #profile的配置会覆盖公用配置
- fetch-registry: true #profile的配置会覆盖公用配置
- service-url:
- defaultZone: http://eureka2:2002/eureka #eureka1启动时向eureka2注册
- server:
- port: 2001
application-eureka2.yml
- eureka:
- instance:
- hostname: eureka2
- client:
- register-with-eureka: true #profile的配置会覆盖公用配置
- fetch-registry: true #profile的配置会覆盖公用配置
- service-url:
- defaultZone: http://eureka1:2001/eureka #eureka2启动时向eureka1注册
- server:
- port: 2002
--spring.profiles.active
和 --server.port
--spring.profiles.active=eureka1 --server.port=2001
如果在命令行运行,可以在命令行中添加参数
java -jar xxx.jar --spring.profiles.active=eureka1 --server.port=2001
- 负载均衡 -- 默认启用了负载均衡
- 重试 -- 默认启用了重试:调用后台服务失败(异常、服务器崩溃、超时),可以自动发起重试调用
重试参数
- ribbon.MaxAutoRetries - 单台服务器的重试次数,默认0
- ribbon.MaxAutoRetriesNextServer - 更换服务器的次数,默认1
- ribbon.ReadTimeout - 接收响应的超时时间,默认1000
- ribbon.ConnectTimeout - 与后台服务器建立连接等待超时时间,默认1000
- ribbon.OkToRetryOnAllOperations - 是否对所有类型请求都进行重试,默认只对 GET 请求重试
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
- </dependency>
spring: application: name: zuul server: port: 3001 eureka: client: service-url: defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka zuul: routes: item-service: /item-service/** user-service: /user-service/** order-service: /order-service/**
启动类添加@EnableZuulProxy
和 @EnableDiscoveryClient
注解
1. 新建过滤器类:AccessFilter,继承 ZuulFilter
2.添加注解:`@Component`
- 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 lombok.extern.slf4j.Slf4j;
- 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
- @Slf4j
- public class AccessFilter extends ZuulFilter {
- //设置过滤器的类型:pre,routing,post,error
- //zuul自动配置的回调方法
- @Override
- public String filterType() {
- //return "pre";
- log.info("Zuul自动配置过滤器类型");
- return FilterConstants.PRE_TYPE;
- }
-
- //过滤器的顺序号
- @Override
- public int filterOrder() {
- /*
- 在默认的第5个过滤器中,向上下文对象放入了serviceId
- 后面过滤器中才能访问这个数据
- */
- log.info("Zuul自动配置过滤器的顺序号");
- return 6;
- }
-
- //针对当前请求进行判断,是否要执行过滤代码
- @Override
- public boolean shouldFilter() {
- //如果客户端调用商品,要判断权限
- //否则调用用户或订单,不判断权限
- //获得当前请求的上下文对象
- RequestContext ctx = RequestContext.getCurrentContext();
- //从上下文对象取出正在访问的serviceId
- String serviceId = (String) ctx.get("serviceId");
- //判断serviceId是否是“item-service”
- return "item-service".equalsIgnoreCase(serviceId);
- }
-
- //过滤代码
- @Override
- public Object run() throws ZuulException {
- //获得上下文对象
- RequestContext ctx = RequestContext.getCurrentContext();
- //从上下文对象取出request对象
- HttpServletRequest request = ctx.getRequest();
- //用request接收token参数
- String token = request.getParameter("token");
- //如果token不存在
- if(StringUtils.isBlank(token)){
- //阻止继续访问
- ctx.setSendZuulResponse(false);
- //直接返回响应:JsonResult{code:500,msg:"xxx",data:null}
- String json = JsonResult.build().code(500).msg("没有登录!").toString();
- ctx.addZuulResponseHeader("Content-Type","application/json;charset=UTF-8");
- ctx.setResponseBody(json);
- }
- return null;//zuul当前版本没有使用这个返回值,返回任何数据都可以,不起任何作用
- }
- }

- 默认已经启动 ribbon 的负载均衡
- 默认不启用 ribbon 的重试
- 在网关重试,可能造成后台服务大面积出现压力翻倍
- 重试功能应该尽量往后放
- 启用重试
1. 添加 spring-retry 依赖
- <dependency>
- <groupId>org.springframework.retry</groupId>
- <artifactId>spring-retry</artifactId>
- </dependency>
2. yml配置启用重试: zuul.retryable=true
- zuul:
- retryable: true
- zuul默认已经启用了Hystrix
- 添加降级
1. 添加降级类,实现 FallbackProvider 接口
2. 添加 `@Component`
- zuul的自动配置会从spring容器自动发现降级类的实例,完成自动配置
- package cn.tedu.sp06.fb;
-
- import cn.tedu.web.util.JsonResult;
- import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
- import org.springframework.http.HttpHeaders;
- import org.springframework.http.HttpStatus;
- import org.springframework.http.client.ClientHttpResponse;
- import org.springframework.stereotype.Component;
-
- import java.io.ByteArrayInputStream;
- import java.io.IOException;
- import java.io.InputStream;
-
- /*
- 当调用后台商品服务失败,执行网关中的这个降级类,向客户端返回降级结果
- */
- @Component
- public class ItemFB implements FallbackProvider {
- /*
- 设置当前降级类,针对哪个后台服务降级
- - item-service:只针对商品降级
- - *:对所有服务都应用当前降级类
- - null:对所有服务都应用当前降级类
- */
- @Override
- public String getRoute() {
- return "item-service";
- }
-
- //发回给客户端的降级响应数据
- @Override
- public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
- return new ClientHttpResponse() {
- @Override
- public HttpStatus getStatusCode() throws IOException {
- return HttpStatus.INTERNAL_SERVER_ERROR;
- }
-
- @Override
- public int getRawStatusCode() throws IOException {
- return HttpStatus.INTERNAL_SERVER_ERROR.value();
- }
-
- @Override
- public String getStatusText() throws IOException {
- return HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase();
- }
-
- @Override
- public void close() {
- //用来关闭下面的输入流
- //ByteArrayInputStream 不占用底层系统资源
- }
-
- @Override
- public InputStream getBody() throws IOException {
- //JsonResult {code:500,msg:调用后台服务失败,data:null}
- String json = JsonResult.build().code(500).msg("调用后台服务失败").toString();
- return new ByteArrayInputStream(json.getBytes("UTF-8"));
-
- }
-
- @Override
- public HttpHeaders getHeaders() {
- HttpHeaders h = new HttpHeaders();
- h.add("Content-Type", "application/json;charset=UTF-8");
- return h;
- }
- };
- }
- }

- 容错 -- 通过降级来容错
- 调用后台服务失败,执行当前模块的一段降级代码,返回降级结果
- 错误提示
- 缓存数据
- 根据具体业务逻辑,返回任何结果都可以
- 限流 -- 通过熔断来限制后台服务的流量
- 流量过大时,后台服务出现大量错误,会自动触发熔断
- 10秒20次请求(必须首先满足)
- 50%出错,执行了降级
- 半开状态
- 断路器打开后一段时间,会进入半开状态
- 会尝试发送一次客户端调用
调用成功,关闭断路器,恢复正常链路
调用失败,继续保持打开状态
Hystrix利用 springboot 的 Actuator 工具来暴露自己的监控数据
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
- </dependency>
- server:
- port: 4001
- hystrix:
- dashboard:
- #允许抓取日志的服务器列表
- proxy-stream-allow-list: localhost
启动类添加注解:@EnableHystrixDashboard
springboot提供的项目监控指标工具,提供了多种监控数据
- 健康状态
- 环境变量、配置参数
- spring mvc 的映射路径
- JVM 虚拟机堆内存镜像
- spring 容器中所有的对象
- .....
1. 添加 actuator 依赖:已经被Zuul集成,添加zuul依赖后无需添加
2. 在网关模块的yml配置暴露的监控数据
- #暴露所有监控数据
- management:
- endpoints:
- web:
- exposure:
- include: "*"
从多台服务器抓取 Hystrix 日志,进行聚合,
Hystrix dashboard从Turbine抓取聚合后的日志数据
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-turbine</artifactId>
- </dependency>
- spring:
- application:
- name: turbine
- server:
- port: 5001
- eureka:
- client:
- service-url:
- defaultZone: http://eureka1:2001/eureka,http://eureka2:2002/eureka
- turbine:
- app-config: zuul
- cluster-name-expression: new String("default")
turbine.app-config 聚合的服务列表:zuul,a,b,c
turbine.cluster-name-expression 对聚合的日志数据命名:new String("default")
启动类注解:@EnableTurbine
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。