Spring cloud

Spring  Cloud  Eureka(服务治理)

Spring  Cloud  Ribbon(客户端负载均衡)

Spring  Cloud  Hystrix(服务容错保护)   黑丝崔克死 

Spring  Cloud  Feign(声明式服务调用)

Spring Cloud   Zuul(API网关服务)

Spring Cloud   Config(分布式配置中心)

Spring Cloud    Bus(消息总线)

Spring Cloud    Stream(消息驱动微服务)  死罪木

Spring Cloud    Sleuth(分布式服务跟踪)   死路死

一、Eureka 注册中心

以订单模块远程调用用户模块和商品模块。并且向eureka进行注册为背景

1、搭建 Eureka 配置中心

1、新建 spring boot项目模块

2、修改pom.xml    添加 eureka server 依赖

3、修改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

4、启动类注解: @EnableEurekaServer 通过注解来触发 eureka 服务器的自动配置

5、浏览器访问注册表: http://localhost:2001/

2、eureka运行机制

注册:客户端向服务器注册时,会一次次反复注册,直到注册成功为止

拉取:客户端每30秒拉取一次注册表,更新本地的缓存的注册表

心跳:客户端每30秒发送一次心跳数据,服务器连续三次收不到一个服务的心跳, 就会删除该服务

自我保护模式:

        1、在网络中断时,15分钟内,85%服务器出现心跳异常,自动进入自我保 护模式

        2、保护模式下,所有注册信息都不删除

        3、网络恢复后,可以自动退出保护模式

        4、开发调试期间,可以禁用保护模式,避免影响测试

客户端连接 eureka

1、添加 eureka client 依赖

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

2、yml 配置 eureka 地址http://eureka1:2001/eureka

3、修改 hosts,完成映射。添加 eureka1 和 eureka2

  1. win+r,输入 drivers
  2. 进入 etc 目录,找到 hosts 文件

    用管理员运行启动编辑器,修改 hosts 文件

    127.0.0.1 eureka1

    127.0.0.1 eureka2

3、高可用

服务器的高可用就是服务器内部设备应用热备份方式(多台相同服务设备同时接受和记录数据),保证提供的服务不中断

Ⅰ、项目的高可用:

1、修改服务的启动配置,添加 springboot 启动参数:--server.port=8001

2、复制启动配置,修改端口 8002

Ⅱ、eureka高可用

1、添加 eureka1 和 eureka2 的 profile 配置

2、配置启动参数

# eureka1         --spring.profiles.active=eureka1  --server.port=2001

# eureka2         --spring.profiles.active=eureka2  --server.port=2002

3、修改需要向eureka注册的项目,使之可以在两台eureka服务器间切换:

​
  client:
    service-url:
      # 可以从云服务商购买不同地点的eureka服务器
      #这里可以改成云服务商提供的地点
      #自己的eureka服务器只能填写 defaultZone
      defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka

​

4、Feign 远程调用,和 Ribbon 负载均衡和重试

Ⅰ、Feign的远程调用步骤

1、添加 feign 依赖

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

2、启动类添加注解 @EnableFeignClients

3、定义远程调用接口

  

Ⅱ、Feign 集成的 Ribbon

        功能:负载均衡和重试

①Ribbon 负载均衡

Feign 集成 Ribbon,默认启动负载均衡

②Ribbon 重试        

调用后台服务时,如果失败可以自动发起重试调用

重试原因: 出异常;调用超时;服务器宕机

Feign 集成 Ribbon,默认启动了重试

重试参数:

ribbon:
  MaxAutoRetries: 1    # 请求阻塞:单台服务器请求次数  默认0
  MaxAutoRetriesNextServer: 2   # 请求阻塞:更换服务器次数次数   默认1  修改为0表示关闭重试功能
  #ReadTimeout: 1000  #接受响应的超时,默认1000毫秒超时
  #ConnectTimeout:  1000 #与后台服务器建立连接的超时时间,默认1000毫秒
  #OkToRetryOnAllOperations: true  #是否对所有的请求方式都重试,默认只对get请求方式重试

二、Zuul  API网关

  • 统一的入口
  • 统一的权限校验
  • 集成 Ribbon
  • 集成 Hystrix

1、统一的入口

新建网关项目模块

②添加依赖:向eureka进行注册并且添加zuul依赖

<dependency> <!--向eureka进行注册-->

     <groupId>org.springframework.cloud</groupId>

     <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>

</dependency>
<dependency>   <!--添加zuul依赖-->
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>

③配置yml

zuul:
  routes:
    item-service: /item-service/**      # ** 包含深层子路径
    user-service: /user-service/**      # *只包含一层路径
    order-service: /order-service/**    #根据注册表中的注册信息,

    #zuul这些有默认配置               

启动类注解:@EnableZuulProxy

2、统一的权限校验

zuul 的过滤器 ZuulProxy,可以过滤客户端请求,在过滤器中可以检查访问权限

本帖网关的设置的规则:调用商品模块需要判断权限,请求地址必须携带token参数    http://localhost:3001/item-service/35?token=1234

1、新建过滤器类:

        AccessFilter 按照 Zuul 的规则实现,添加注解 @Component

2、继承接口ZuulFilter重写里面的方法

3zuul的自动配置,会在 spring 容器中发现过滤器实例,完成自动配置

        第二步详情:

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.lang3.StringUtils;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

//该网关的规则:掉用商品需要判断权限,请求地址必须携带token参数
//  http://localhost:3001/item-service/35?token=1234

@Component //交给spring容器管理
public class AccessFilter extends ZuulFilter {

    //设置过滤器的类型 pre前置    routing表示路由   post   error
    @Override
    public String filterType() {
        //return "pre"; //方法一
        return FilterConstants.PRE_TYPE;  //方法二
    }

    //设置顺序号(过滤规则执行排序)
    @Override
    public int filterOrder() {
        return 6;   //pre过滤类型默认有5个过滤方法,第五个过滤器里面获取了serviceId(item-service)
                        // 如果自定义过滤器需要获取serviceI这个信息,该自定义过滤器就要放到末尾
    }

    //针对当前请求,是否执行下面的过滤规则代码
    @Override
    public boolean shouldFilter() {
        /*掉用商品需要判断权限
        * 调用用户或订单不检查权限*/

        //第一步:获得一个请求上下文对象
        RequestContext ctx  = RequestContext.getCurrentContext();

        //第二步:从上下文对象获得调用的后台服务的ServerId
        String serviceId = (String) ctx.get(FilterConstants.SERVICE_ID_KEY);

        //第三步:如果调用的item-service,返回true,表示不需要检查权限,false需要检查权限
        return "item-service".equals(serviceId);


    }


    //过滤规则代码
    @Override
    public Object run() throws ZuulException {

        //第一步:获得上下文对象
        RequestContext ctx  = RequestContext.getCurrentContext();

        //第二步:获得request对象
        HttpServletRequest request = ctx.getRequest();

        //第三步:以请求路径种携带token信息为过滤规则,接收token参数。
        String token =  request.getParameter("token");

        //第四步:如果token不存在阻止继续调用
        if (StringUtils.isBlank(token)){

            //阻止继续调用
            ctx.setSendZuulResponse(false);

            //直接返回响应
            String json =  JsonResult.build().code(400).msg("Not Login!").toString(); //转成json格式
            ctx.addZuulResponseHeader("Content-Type","application/json;charset=UTF-8");
            ctx.setResponseBody(json);
        }
        return null; //Zuul在当前版本不起任何作用,以后版本更新扩展使用
    }
}

3、Zuul集成Ribbon

负载均衡默认启用

重试默认禁用

        禁用的原因:在最前面重试,能能造成后台服务器大面积压力倍增,大面积出现故障

启用重试

        添加 spring-retry 依赖

<dependency>   <!--开启访问重试功能,Zuul集成Ribbon默认关闭-->
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>

        yml 配置启用重试: zuul.retryable=true

zuul:
 	    retryable: true

        如果需要可以配置重试参数

ribbon:
  MaxAutoRetries: 1   #单台服务器重试次数,全局生效

  #针对item—service模块进行单独配置
  item-service:
    ribbon:
      MaxAutoRetries: 0

4、Zuul 集成 Hystrix

Hystrix是容错和限流工具

        1、Hystrix容错:降级

        2、Hystrix限流:熔断

Hystrix的使用

  1. 新建降级类 ItemFB,实现 FallbackProvider 接口
  2. 添加注解 @Component交给spring管理
  • Zuul的自动配置,可以自动发现降级类实例,完成自动配置
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;
import java.nio.charset.StandardCharsets;


//可以有多个降级类,针对不同的模块
@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.MULTI_STATUS.getReasonPhrase();
            }

            //用来关闭下面的流,但是本类使用的流不需要关闭,不占用系统资源
            @Override
            public void close() {

            }

            //设置协议头 JsonResult - {code:500, msg:xxx, data:null}
            @Override
            public InputStream getBody() throws IOException {
                String json = JsonResult.build().code(500).msg("后台服务器出错,稍后在试").toString();
                return new ByteArrayInputStream(json.getBytes("UTF-8"));
            }

            //设置协议体
            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers =  new HttpHeaders();
                headers.add("Content-Type","application/json;charset=UTF-8");
                return headers;
            }
        };
    }
}

Zuul 网关使用 Hystrix 进行容错处理,执行降级

Zuul 默认已经启用Hystrix,任何基础配置都不用做

调用后台服务失败,执行前面模块中的降级代码,向客户端返回降级结果

  • 错误提示
  • 缓存数据
  • 据业务逻辑,返回任何结果都可以

        

Zuul 集成 Hystrix 实现限流,熔断

当流量过大,后台服务出现故障,可以断开链路,限制后台故障服务的流量,等待它从故障中恢复

  • 断路器打开条件:
    • 10秒20次请求(必须首先满足)
    • 50%请求出错,执行了降级代码
    • 这些参数都可自定义
  • 断路器打开后,会进入半开状态 在半开状态下,会向后台服务尝试发送一次客户端调用, 调用成功,自动关闭断路器恢复正常, 调用失败,继续保持打开状态

5、Hystrix dashboard

对 Hystrix 降级和熔断的情况进行监控,可以通过监控快速定位故障模块

一、Hystrix 使用 Actuator 暴露自己的监控日志

Actuator是 springboot 提供的项目监控指标工具,可以暴露项目的多种监控指标

                

  • 健康状态
  • spring容器中所有的对象
  • spring mvc 映射的所有路径
  • 环境变量
  • 堆内存镜像
  • .....

二、暴露Actuator监控指标

1、添加actuator 依赖

<dependency>  <!--actuator于此依赖-->
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>

2、配置yml

2、配置yml
# 暴露 actuator 监控指标
management:
  endpoints:
    web:
      exposure:
        include: "*"  
# *表示暴露所有监控指
# health,beans,mappings   表示暴露这3个监控指标
# m.e.w.e.i=hystrix.stream      

3、浏览器访问http://localhost:该项目端口/actuator(子路径)/hystrix.stream

看到如下信息,不停的在ping

三、搭建 Hystrix-dashboard 仪表盘

作用:图形化展示监控指标

使用步骤:

1、新建 spring 模块: sp07-hystrix-dashboard

 2、调整pom.xml,添加 hystrix dashboard 

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

  3、配置yml

hystrix:
  dashboard:
    proxy-stream-allow-list: localhost  #允许抓取服务器列表

4、启动类注解:@EnableHystrixDashboard

5、访问

浏览器访问:http://localhost:4001/hystrix

输入框填入 http://localhost:3001/actuator/hystrix.stream

 出现如下页面

6、压力测试工具--Apache24

 在bin目录下执行cmd,在cmd执行访问命令:

        ab -n 20000 -c 50 http://localhost:3001/item-service/35

        n表示访问次数共计20000  c表示并发50次(一个时间点上50次)

7、TurBine

作用:从多态服务器聚合 Hystrix 监控数据,Hystrix dashboard仪表盘可以从Turbine抓取聚合后的日志数据

使用步骤:

①、新建 spring 模块: sp08-turbine

②、pom.xml 添加 eureka client、turbine

<dependency>  <!--向eureka注册-->
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

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

③、配置yml

turbine:
  app-config: zuul   #从哪台服务器抓取日志,多个可以使用逗号隔开(aaa,bbb,ccc)
  cluster-name-expression: new String("default")  
            #服务的id。default为默认id,访问不需要加参数
            #如果自定义名字,则访问路径为:
                            https://ip:port/turbine.stream?cluster=[clusterName]

④、启动类注解: @EnalbeTurbine

⑤、访问日志数据: http://localhost:5001/turbine.stream

三、Springcloud Config 配置中心

作用:集中管理和维护配置文件,数据可以配置到Git,mysql和本地磁盘

使用步骤

1、在父工程目录下新建一个config包,将需要配置的模块的yml文件复制到该包下,并且修改文件名,例如:

  • item-service-dev.yml
  • user-service-dev.yml
  • order-service-dev.yml

推荐使用   模块服务名-dev.yml的格式

2、创建本地git仓库

将该项目代码传到远程仓库(也可以只传config包代码)

3、创建一个项目模块

添加依赖:eureka client,config server

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>

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

配置yml

server:
  port: 6001

spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri:  https://gitee.com/sunyanhui1111/springcloud1.git  #储存配置信息的git仓库的地址
          search-paths: config   #该仓库下文件夹的名字

eureka:
  client:
    service-url:
      defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka

5、启动类注解 @EnableConfigServe

6、访问验证:

        http://localhost:6001/item-service/dev   测试访问是否能拉取到远程仓库的配置
        http://localhost:6001/user-service/dev   测试访问是否能拉取到远程仓库的配置
        http://localhost:6001/order-service/dev   测试访问是否能拉取到远程仓库的配置
        http://eureka1:2001       注册表地址,查看注册表有没有 config-server

7、修改模块(配置在配置中心的模块)

        ②删除 application.yml (或把代码全部注释掉)

        ②添加依赖: config client

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

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

        ③创建bootstrap.yml(比application优先启动)

eureka:
  client:
    service-url:
      defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka

#配置连接注册表,获得配置中心地址,再从配置中心下载该模块需要的配置文件
spring:
  cloud:
    config:
      discovery:
        enabled: true  #允许使用服务发现,去发现配置中心
        service-id: config-server  #服务ID
      name: item-service     #文件名
      profile: dev           #后缀
      #完整文件名:user-service-dev.yml

四、BUS 配置刷新

BUS配置刷新 刷新指令消息发送到Rabbitmq ,其他模块接收执行,执行刷新操作 使用的交换机为主题模式

//该模块接收到刷新指令,使得@Value在配置中心获取到新的值,必须加@RefreshScope(刷新到新的配置,可以重新注入到对象中)


@RefreshScope //刷新到新的配置,可以重新注入到对象中
@Service
@Slf4j
public class UserServiceImpl implements UserService {
    @Value("${sp.user-service.users}")
    private String userJson;

    @Override
    public User getUser(Integer userId) {
        log.info("获取用户,userId="+userId);
        // userJson --> List<User>
        List<User> users = JsonUtil.from(
                userJson, new TypeReference<List<User>>() {});
        for (User u : users) {
            if (u.getId().equals(userId)) {
                return u;
            }
        }
        return new User(userId,"用户名"+userId,"密码"+userId);
    }

    @Override
    public void addScore(Integer userId, Integer score) {
        log.info("增加用户积分,userId="+userId+",score="+score);
    }
}

使用步骤:

1、在需要被刷新的模块和执行刷新的模块添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-bus</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>

2、在执行刷新的模块添加添加 actuator 依赖。暴露刷新路径

        <!--暴露刷新路径-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

3、修改执行刷新的模块的yml配置

#rabbitmq 连接配置
spring:
    rabbitmq:   #rabbitmq信息配置
      host: 192.168.64.140
      port: 5672
      username: admin
      password: admin
      virtual-host: kongjuian1   #空间名字
#暴露 bus-refresh 刷新路径
management: 
  endpoints:
    web:
      exposure:
        include: bus-refresh

4、修改 需要被刷新模块的 yml 配置,添加 rabbitmq 连接  

#rabbitmq 连接配置
spring:
    rabbitmq:   #rabbitmq信息配置
      host: 192.168.64.140
      port: 5672
      username: admin
      password: admin
      virtual-host: kongjuian1   #空间名字

配置刷新测试:

  1. 向 http://localhost:6001/actuator/bus-refresh 提交一个 POST 请求
  2. 观察 被刷新模块的控制台是否重新连接 6001,刷新配置
  3. 向 http://localhost:6001/actuator/bus-refresh /被刷新模块的服务id   提交一个 POST 请求,测试该被刷新模块是否被刷新

选择正确网卡,注册ip不注册主机名

1、配置bootstrap.yml

#修改ip
spring:
  cloud:
    inetutils:
      ignored-interfaces: # 忽略的网卡
        - VM.*            # VM开头, .是任意字符, *0到多个
      preferred-networks: # 要是用的网卡的网段
        - 192\.168\.0\..+ # \.是普通的.字符, .+任意字符1到多个

   2、修改application :prefer-ip-address: true # 使用ip进行注册

eureka:
  instance: #ip设置
    prefer-ip-address: true

虽然注册了ip,但eureka注册表中看到的 instance id 可能还是主机名
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port} # 界面列表中显示的格式也显示ip

 

五、Sleuth + Zipkin 链路跟踪

sleuth使用Rabbitmq(简单模式)与zipkin进行信息交流

1、Sleuth

作用:产生链路跟踪日志   A --> B --> C

向需要监控的路径添加slenth依赖

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

默认抽取访问总量的10%进行日志跟踪

spring:
  sleuth:
    sampler:
      probability: 0.1

2、Zipkin

作用:根据链路日志产生链路调用图表

下载地址:GitHub - openzipkin/zipkin: Zipkin is a distributed tracing system

向需要监控的路径添加zipkin依赖

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

3、向需要监控的路径添加Rabbitmq依赖

spring:
  rabbitmq: #rabbitmq信息配置
    host: 192.168.64.140
    port: 5672
    username: admin
    password: admin
    virtual-host: kongjuian1   #空间名字

4、zipkin 服务器的启动

在该文件根目录的cmd输入启动命令

java -jar z.jar --zipkin.collector.rabbitmq.uri=amqp://admin:admin@192.168.64.140:5672

java -jar z.jar --zipkin.collector.rabbitmq.uri=amqp://admin:admin@wht6.cn:5672

java -jar z.jar --zipkin.collector.rabbitmq.uri=amqp://admin:admin@wht6.cn:5672/空间名字

启动如下界面

启动

 访问zipkin

zipkin

zipkin

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

S Y H

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值