Eureka、Zuul、Hystrix、Actuator、Turbine

目录

Eureka

Eureka的四条运行机制

依赖

 application.yml

修改 hosts 文件,添加 eureka 域名映射

微服务注册到Eureka服务器

Eureka 高可用

配置启动参数 --spring.profiles.active 和 --server.port

Feign 集成 Ribbon

Zuul网关

依赖

application.yml

Zuul 统一权限校验

Zuul 集成 Ribbon

Zuul集成Hystrix

Hystrix

 Hystrix数据监控

依赖

application.yml

Actuator

 Turbine

依赖

application.yml


Eureka

Eureka的四条运行机制

- 注册

  客户端一次次的反复连接注册中心进行注册,直到注册成功为止

- 拉取

  客户端每30秒拉取一次注册表,刷新注册表

- 心跳

  客户端每30秒发送一次心跳数据,如果服务器端连续三次收不到一个服务的心跳,会删除它的注册信息

- 自我保护模式

  - 由于网络故障,15分钟内,85%服务器出现心跳异常,会自动进入自我保护模式
  - 保护所有注册信息不删除
  - 等待网络恢复后,可以退出保护模式,恢复正常
  - 开发调试期间应该关闭保护模式,避免影响测试

依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

 application.yml

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
  
  • eureka 集群服务器之间,通过 hostname 来区分
  • eureka.server.enable-self-preservation
  • eureka 的自我保护状态:心跳失败的比例,在15分钟内是否超过85%,如果出现了超过的情况,Eureka Server会将当前的实例注册信息保护起来,同时提示一个警告,一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据。也就是不会注销任何微服务
  • eureka.client.register-with-eureka=false
  • 不向自身注册
  • eureka.client.fetch-registry=false
  • 不从自身拉取注册信息
  • eureka.instance.lease-expiration-duration-in-seconds
  • 最后一次心跳后,间隔多久认定微服务不可用,默认90

启动类添加@EnableEurekaServer注解

修改 hosts 文件,添加 eureka 域名映射

C:\Windows\System32\drivers\etc\hosts

添加内容

127.0.0.1       eureka1
127.0.0.1       eureka2

微服务注册到Eureka服务器

在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
  • eureka.instance.lease-renewal-interval-in-seconds
  • 心跳间隔时间,默认 30 秒
  • defaultZone,默认位置,可以修改为具体地理位置,比如:beiJing, shangHai, shenZhen 等,表示 eureka 服务器的部署位置, 需要云服务器提供
  • eureka.client.registry-fetch-interval-seconds
  • 拉取注册信息间隔时间,默认 30 秒

启动类添加@EnableDiscoveryClient注解

Eureka 高可用

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

Feign 集成 Ribbon

- 负载均衡 -- 默认启用了负载均衡
- 重试 -- 默认启用了重试:调用后台服务失败(异常、服务器崩溃、超时),可以自动发起重试调用

重试参数

- ribbon.MaxAutoRetries - 单台服务器的重试次数,默认0
- ribbon.MaxAutoRetriesNextServer - 更换服务器的次数,默认1
- ribbon.ReadTimeout - 接收响应的超时时间,默认1000
- ribbon.ConnectTimeout - 与后台服务器建立连接等待超时时间,默认1000
- ribbon.OkToRetryOnAllOperations - 是否对所有类型请求都进行重试,默认只对 GET 请求重试

Zuul网关

依赖

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>

application.yml

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 注解

Zuul 统一权限校验

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当前版本没有使用这个返回值,返回任何数据都可以,不起任何作用
    }
}

Zuul 集成 Ribbon

- 默认已经启动 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

- 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;
            }
        };
    }
}

Hystrix

- 容错 -- 通过降级来容错
  - 调用后台服务失败,执行当前模块的一段降级代码,返回降级结果
    - 错误提示
    - 缓存数据
    - 根据具体业务逻辑,返回任何结果都可以
- 限流 -- 通过熔断来限制后台服务的流量
  - 流量过大时,后台服务出现大量错误,会自动触发熔断
  - 10秒20次请求(必须首先满足)
  - 50%出错,执行了降级
  - 半开状态
    - 断路器打开后一段时间,会进入半开状态
    - 会尝试发送一次客户端调用
      调用成功,关闭断路器,恢复正常链路
      调用失败,继续保持打开状态

 Hystrix数据监控

Hystrix利用 springboot 的 Actuator 工具来暴露自己的监控数据

依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

application.yml

server:
  port: 4001
hystrix:
  dashboard:
    #允许抓取日志的服务器列表
    proxy-stream-allow-list: localhost

启动类添加注解:@EnableHystrixDashboard

Actuator

springboot提供的项目监控指标工具,提供了多种监控数据

- 健康状态
- 环境变量、配置参数
-  spring mvc 的映射路径
- JVM 虚拟机堆内存镜像
- spring 容器中所有的对象
- .....

1. 添加 actuator 依赖:已经被Zuul集成,添加zuul依赖后无需添加

2. 在网关模块的yml配置暴露的监控数据

#暴露所有监控数据
management:
  endpoints:
    web:
      exposure:
        include: "*"

 Turbine

从多台服务器抓取 Hystrix 日志,进行聚合,

Hystrix dashboard从Turbine抓取聚合后的日志数据

依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-turbine</artifactId>
</dependency>

application.yml

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值