springCloud 和springAlibabaCloud

文章目录

  • springCloud 和springAlibabaCloud
    • 一、分布式架构演进(单机---> 微服务)
    • 二、聚合工程
    • 三、服务之间调用
      • 1.RestTemplate 的方式调用
    • 四、注册中心
    • 五、通过注册中心进行服务之间调用
    • 六、负载均衡
      • 1.Ribbon 负载均衡策略
      • 2.openFeign调用
      • 3.Ribbon 和 openFeign 的区别
    • 七、CAP理论
      • 1.CAP基础理论
      • 2.CAP注册中心的选择
      • 3.CAP权衡结果 Base理论
    • 八、高并发下微服务架构存在的问题和解决方案
      • 1.限流
      • 2.熔断
      • 3.降级
      • 4.隔离
      • 5.解决方案:流量防卫兵-Sentinel
      • 6.Sentinel自定义异常-整合Open-Feign
      • 7.新版Sentinel整合OpenFeign配置实战
    • 九、JDK相关
    • 十、网关 springcloud gateway
      • 1.网关实战:
      • 2.网关自定义全局过滤
    • 十一、albabaCloud下实现链路追踪功能
      • 1.链路追踪系统Sleuth
      • 2.链路追踪系统ZipKin 部署实战
      • 3.链路追踪组件Zipkin+Sleuth整合实战
      • 4.Zipkin持久化配置
    • 十二、配置中心nacos
      • 1.注释原来的 application.yml 文件
      • 2.配置中心下面动态的获取配置属性

一、分布式架构演进(单机—> 微服务)

单机架构:

​ 优点:便于测试,对小项目友好

​ 缺点:开发速度慢,启动时间长,依赖庞大

分布式架构:

​ SOA:面向服务的架构 其中包含多个服务,服务之间通过相互依赖提供一系类功能,一个服务通常以独立的形式存在于操作系统中

​ 微服务:将一个大的【单体项目】拆分成多个子项目和服务,每个拆分出来的服务各自独立打包部署

​ 优点:便于理解、开发、部署

​ 缺点:存在分布式事务、服务治理

Spring Alibaba Cloud

  • 全家桶+阿里生态多个组件组合+SpringCloud支持
  • 官网 https://spring.io/projects/spring-cloud-alibaba
    • 服务注册发现:Nacos
    • 服务限流降级:Sentinel
    • 分布配置中心:Nacos
    • 服务网关:SpringCloud Gateway
    • 服务之间调用:Feign、Ribbon
    • 链路追踪:Sleuth+Zipkin
    • 网关:gateway
    • 通信方式:http restful

二、聚合工程

module子模块

xdclass-common
xdclass-video-service
xdclass-user-service
xdclass-order-service
xdclass-api-gateway
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache/POM/4.0.0"
         xmlns:xsi="http://www.w3/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache/POM/4.0.0 http://maven.apache/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.mesmile</groupId>
    <artifactId>xdclass-cloud</artifactId>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>xdclass-common</module>
        <module>xdclass-video-service</module>
        <module>xdclass-user-service</module>
        <module>xdclass-order-service</module>
        <module>xdclass-api-gateway</module>
    </modules>

    <!-- 一般来说父级项目的packaging都为pom,packaging默认类型jar类型-->
    <packaging>pom</packaging>

    <properties>
        <java.version>1.8</java.version>
        <mavenpiler.source>1.8</mavenpiler.source>
        <mavenpiler.target>1.8</mavenpiler.target>
    </properties>

    <dependencies>
        <!-- https://mvnrepository/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository/artifact/cn.hutool/hutool-all -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.4.0</version>
        </dependency>
    </dependencies>

     <!--  dependencyManagement 中的内容是父级项目 用于给子项目引入  -->

    <dependencyManagement>
        <dependencies>
            <!--https://mvnrepository/artifact/org.springframework.boot/spring-boot-dependencies/2.3.3.RELEASE-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.3.3.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--https://mvnrepository/artifact/org.springframework.cloud/spring-cloud-dependencies/Hoxton.SR8-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR8</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--https://mvnrepository/artifact/com.alibaba.cloud/spring-cloud-alibaba-dependencies/2.2.1.RELEASE-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.1.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.1.2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

        </dependencies>

    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

子项目依赖:

  <!--引入 springboot-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>cn.mesmile</groupId>
            <artifactId>xdclass-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!--服务注册-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!--nacos 配置中心-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

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

        <!--sentinel 限流-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

        <!--sleuth 链路追踪-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>

        <!--zipkin 链路追踪可视化-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>

    </dependencies>

三、服务之间调用

1.RestTemplate 的方式调用

​ 服务之间ip写死了

​ 服务之间服务提供负载均衡

​ 多个服务之间调用复杂

四、注册中心

服务注册 与 服务发现

主流的注册中心:zookeeper、Eureka、consul、etcd、Nacos

这里使用nacos作为注册中心:

nacos官方文档:https://nacos.io/zh-cn/docs/quick-start.html

注意nacos在window中安装的坑:

​ 1.需要修改配置文件中 MySQL 的设置

​ 2.需要修改配置文件中 将 集群模式 改为 单机模式

1.第一个问题

2.第二个问题

nacos注册中心使用:

nacos默认的地址:http://127.0.0.1:8848/nacos

nacos默认的账号和密码:nacos/nacos

五、通过注册中心进行服务之间调用

配置文件:

# application 的名字
spring:
  application:
    name: xdclass-video-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

在启动类加上注解:

@EnableDiscoveryClient
// 可以服务之间调用
private final DiscoveryClient discoveryClient;

// 这里的参数默认为,配置文件中的 application.name = xdclass-video-service
List<ServiceInstance> instances = discoveryClient.getInstances("xdclass-video-service");
ServiceInstance serviceInstance = instances.get(0);
String host = serviceInstance.getHost();
int port = serviceInstance.getPort();

六、负载均衡

Load Balance

常见的负载均衡策略(看组件的支持情况)

  • 节点轮询
    • 简介:每个请求按顺序分配到不同的后端服务器
  • weight 权重配置
    • 简介:weight和访问比率成正比,数字越大,分配得到的流量越高
  • 固定分发
    • 简介:根据请求按访问ip的hash结果分配,这样每个用户就可以固定访问一个后端服务器
  • 随机选择、最短响应时间等等

restTemplate增加 **@LoadBalanced ** 注解

 /**
  *  @LoadBalanced  ribbon 负载均衡  默认是 轮训的策略
  */
@Bean
@LoadBalanced
public RestTemplate getRestTemplate () {
    return new RestTemplate();
}

这样通过 restTemplate 的方式调用的话,就可以实现负载均衡 : 默认策略是【 **节点轮询 **】

1.Ribbon 负载均衡策略

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qHAwo33a-1606960678010)(C:\Users\AOSSCI\AppData\Roaming\Typora\typora-user-images\image-20201026110008372.png)]

配置文件:

# video 服务  IRule 规则; 【改变负载均衡策略】  默认为轮训策略
xdclass-video-service:
  ribbon:
    NFLoadBalancerRuleClassName: comflix.loadbalancer.RandomRule

2.openFeign调用

Feign默认集成了Ribbon

<!-- 导入jar包 --> 
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

启动类配置注解:

@EnableFeignClients

增加一个接口:

@FeignClient(value = "xdclass-video-service", fallback = VideoServiceFallback.class)
public interface VideoService {

    // 这里的方法是 video 视频服务中的方法
    @GetMapping("/api/v1/video/getVideoById")
    Video getVideoById (@RequestParam("videoId")Integer videoId);

}

// value 是application.name    fallback 的参数是指定的一个 托底的类,当这个接口中的方法失效的时候,会进入 回调类中调用托底方法
@FeignClient(value = "xdclass-video-service", fallback = VideoServiceFallback.class)

托底类:

@Service
public class VideoServiceFallback implements VideoService {
    
	// 正常接口调用失败,就会进入托底类中调用此方法
    @Override
    public Video getVideoById(Integer videoId) {
        Video video = new Video();
        video.setTitle("这是一个兜底 fallback 数据");
        video.setId(3);
        video.setCoverImg("images");
        video.setSummary("描述");
        return video;
    }
}

3.Ribbon 和 openFeign 的区别

ribbon和feign两个的区别和选择

选择feign,feign默认集成了ribbon
写起来更加思路清晰和方便,feign面向接口编程
采用注解方式进行配置,配置熔断等方式方便

七、CAP理论

1.CAP基础理论

  • CAP定理: 指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可同时获得

    • 一致性(C):所有节点都可以访问到最新的数据
    • 可用性(A):每个请求都是可以得到响应的,不管请求是成功还是失败
    • 分区容错性(P):除了全部整体网络故障,其他故障都不能导致整个系统不可用
  • CAP理论就是说在分布式存储系统中,最多只能实现上面的两点。而由于当前的网络硬件肯定会出现延迟丢包等问题,所以分区容忍性是我们必须需要实现的。所以我们只能在一致性和可用性之间进行权衡

CA: 如果不要求P(不允许分区),则C(强一致性)和A(可用性)是可以保证的。但放弃P的同时也就意味着放弃了系统的扩展性,也就是分布式节点受限,没办法部署子节点,这是违背分布式系统设计的初衷的

CP: 如果不要求A(可用),每个请求都需要在服务器之间保持强一致,而P(分区)会导致同步时间无限延长(也就是等待数据同步完才能正常访问服务),一旦发生网络故障或者消息丢失等情况,就要牺牲用户的体验,等待所有数据全部一致了之后再让用户访问系统

AP:要高可用并允许分区,则需放弃一致性。一旦分区发生,节点之间可能会失去联系,为了高可用,每个节点只能用本地数据提供服务,而这样会导致全局数据的不一致性。

2.CAP注册中心的选择

  • 常见注册中心:zk、eureka、nacos
  • 那你应该怎么选择
NacosEurekaConsulZookeeper
一致性协议CP+APAPCPCP
健康检查TCP/HTTP/MYSQL/Client Beat心跳TCP/HTTP/gRPC/CmdKeep Alive
雪崩保护
访问协议HTTP/DNSHTTPHTTP/DNSTCP
SpringCloud集成支持支持支持支持
  • Zookeeper:CP设计,保证了一致性,集群搭建的时候,某个节点失效,则会进行选举行的leader,或者半数以上节点不可用,则无法提供服务,因此可用性没法满足

  • Eureka:AP原则,无主从节点,一个节点挂了,自动切换其他节点可以使用,去中心化

  • 结论:

    • 分布式系统中P,肯定要满足,所以只能在CA中二选一
    • 没有最好的选择,最好的选择是根据业务场景来进行架构设计
    • 如果要求一致性,则选择zookeeper/Nacos,如金融行业 CP
    • 如果要求可用性,则Eureka/Nacos,如电商系统 AP
    • CP : 适合支付、交易类,要求数据强一致性,宁可业务不可用,也不能出现脏数据
    • AP: 互联网业务,比如信息流架构,不要求数据强一致,更想要服务可用

3.CAP权衡结果 Base理论

  • 什么是Base理论
CAP 中的一致性和可用性进行一个权衡的结果,核心思想就是:我们无法做到强一致,但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性, 来自 ebay 的架构师提出
  • Basically Available(基本可用)
    • 假设系统,出现了不可预知的故障,但还是能用, 可能会有性能或者功能上的影响
  • Soft state(软状态)
    • 允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个不同节点的数据副本存在数据延时
  • Eventually consistent(最终一致性)
    • 系统能够保证在没有其他新的更新操作的情况下,数据最终一定能够达到一致的状态,因此所有客户端对系统的数据访问最终都能够获取到最新的值

八、高并发下微服务架构存在的问题和解决方案

存在问题: 微服务拆分多个系统,服务之间相互依赖,可能由于 负载过高、流量突发或者网络异常等情况导致服务不可用

解决思路:

  • 不要外界影响
  • 不被请求拖垮
    • 上游服务
    • 下游服务

1.限流

​ 采用漏洞算法

2.熔断

​ 服务之间调用出现异常,熔断停止调用,避免拖垮整个业务

​ 保险丝,熔断服务,为了防止整个系统故障,包含当前和下游服务 下单服务 -》商品服务-》用户服务 -》(出现异常-》熔断风控服务

3.降级

​ 服务之间,空余资源降级给紧张资源使用

抛弃一些非核心对的接口和数据,返回兜底数据

4.隔离

​ 限制服务的调用,将其隔离在外

熔断和降级互相交集

  • 相同点:

    • 从可用性和可靠性触发,为了防止系统崩溃
    • 最终让用户体验到的是某些功能暂时不能用
  • 不同点

    • 服务熔断一般是下游服务故障导致的,而服务降级一般是从整体系统负荷考虑,由调用方控制

5.解决方案:流量防卫兵-Sentinel

官网地址:https://github/alibaba/Sentinel/wiki/%E6%8E%A7%E5%88%B6%E5%8F%B0

下载好jar包后的启动命令:

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.0.jar

导入jar包:

<!--sentinel 限流-->
<dependency>
 <groupId>com.alibaba.cloud</groupId>
 <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

配置文件:

# sentinel 限流   dashboard: 8080 控制台端口
# port: 9998 本地启的端口,随机选个不能被占用的,与dashboard进行数据交互,会在应用对应的机器上启动一个 Http Server,该 Server 会与 Sentinel 控制台做交互, 若被占用,则开始+1一次扫描
spring:
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080
        port: 9998

6.Sentinel自定义异常-整合Open-Feign

自定义 sentinel 异常返回结果:

@Component
public class MySentinelBlockHandler implements BlockExceptionHandler {

    /*
        FlowException  //限流异常
        DegradeException  //降级异常
        ParamFlowException //参数限流异常
        SystemBlockException //系统负载异常
        AuthorityException //授权异常
     */

    /**
     *  V2.1.0 到  V2.2.0后,sentinel 里面依赖进行改动,且不向下兼容
     * @param request
     * @param response
     * @param e
     * @throws Exception
     */
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        System.out.println("request.getRequestURI() = " + request.getRequestURI());
        System.out.println("request.getRemoteUser() = " + request.getRemoteUser());
        System.out.println("request.getContextPath() = " + request.getContextPath());
        System.out.println("request.getMethod() = " + request.getMethod());

        // 降级业务
        Map<String,Object> backMap=new HashMap<>();
        if (e instanceof FlowException){
            backMap.put("code",-1);
            backMap.put("msg","限流-异常啦");
        }else if (e instanceof DegradeException){
            backMap.put("code",-2);
            backMap.put("msg","降级-异常啦");
        }else if (e instanceof ParamFlowException){
            backMap.put("code",-3);
            backMap.put("msg","热点-异常啦");
        }else if (e instanceof SystemBlockException){
            backMap.put("code",-4);
            backMap.put("msg","系统规则-异常啦");
        }else if (e instanceof AuthorityException){
            backMap.put("code",-5);
            backMap.put("msg","认证-异常啦");
        }

        // 设置返回json数据
        response.setStatus(200);
        response.setHeader("content-Type","application/json;charset=UTF-8");
        response.getWriter().write(JSON.toJSONString(backMap));

    }
}

7.新版Sentinel整合OpenFeign配置实战

配置文件:

# 开启 feign 对 Sentinel 的支持
feign:
  sentinel:
    enabled: true

九、JDK相关

简介:讲解JDK⼀些基础知识科普

  • OpenJDK和OracleJDK版本区别
    • OpenJDK是JDK的开放源码版本,以GPL协议的形式发布(General Public License)
    • Oracle JDK采⽤了商业实现
  • LTS 是啥意思?
    • Long Term Support ⻓期⽀持的版本,如JDK8、JDK11都是属于LTS
    • JDK9 和 JDK10 这两个被称为“功能性的版本”不同, 两者均只提供半年的技术⽀持
    • 甲⻣⽂释出Java的政策,每6个⽉会有⼀个版本的释出,⻓期⽀持版本每三年发布⼀次,根据 后续的发布计划,下⼀个⻓期⽀持版 Java 17 将于2021年发布
  • 8u20、11u20是啥意思?
    • 就是Java的补丁,⽐如JDK8的 8u20版本、8u60版本; java11的 11u20、11u40版本

十、网关 springcloud gateway

简介:介绍什么是微服务的网关和应用场景

  • 什么是网关
    • API Gateway,是系统的唯一对外的入口,介于客户端和服务器端之间的中间层,处理非业务功能 提供路由请求、鉴权、监控、缓存、限流等功能
    • 统一接入
      • 智能路由
      • AB测试、灰度测试
      • 负载均衡、容灾处理
      • 日志埋点(类似Nignx日志)
    • 流量监控
      • 限流处理
      • 服务降级
    • 安全防护
      • 鉴权处理
      • 监控
      • 机器网络隔离
  • 主流的网关
    • zuul:是Netflix开源的微服务网关,和Eureka,Ribbon,Hystrix等组件配合使用,依赖组件比较多,性能教差
    • kong: 由Mashape公司开源的,基于Nginx的API gateway
  • nginx+lua:是一个高性能的HTTP和反向代理服务器,lua是脚本语言,让Nginx执行Lua脚本,并且高并发、非阻塞的处理各种请求
  • springcloud gateway: Spring公司专门开发的网关,替代zuul

1.网关实战:

导入 jar 包:

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

配置文件:

# 端口号
server:
  port: 8888
# application 的名字  不能有下划线 _
spring:
  application:
    name: xdclass-api-gateway
  cloud:
# nacos 注册与发现
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
# sentinel 限流   dashboard: 8080 控制台端口
# port: 9999 本地启的端口,随机选个不能被占用的,与dashboard进行数据交互,会在应用对应的机器上启动一个 Http Server,该 Server 会与 Sentinel 控制台做交互, 若被占用,则开始+1一次扫描
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080
        port: 9993
    gateway:
      routes: #数组形式
        - id: order-service  #路由唯一标识
          # uri: http://127.0.0.1:8000  #想要转发到的地址

          uri: lb://xdclass-order-service  # 从nacos 进行转发  lb 是负载均衡的意思
          order: 1 #优先级,数字越小优先级越高
          predicates: #断言过滤器 配置哪个路径才转发   【RoutePredicateFactory】  支持多个predicates请求转发,如果配置多个必须满足多个才能转发
            - Path=/order-server/**
#            - Before=2020-10-30T18:59:00.000+08:00[Asia/Shanghai]
#            - Query=source

          # 这个时间【之前可以访问】2020-10-25T14:10:07.049+08:00[Asia/Shanghai]   ZonedDateTime
          # Query=source 每个接口必须携带一个字段过来 source
          filters: #过滤器,请求在传递过程中通过过滤器修改
            - StripPrefix=1  #去掉第一层前缀
      discovery:
        locator:
          enabled: true # 开启网关拉取 nacos 服务

#访问路径 http://localhost:8888/order-server/api/v1/video_order/list
#转发路径 http://localhost:8000/api/v1/video_order/list
#需要过滤器去掉前面第一层

2.网关自定义全局过滤

自定义全局过滤:

//@Component
public class UserGlobalFilter implements GlobalFilter, Ordered {

    /**
     * 【网关不要加入太多业务逻辑,否则会影响性能】
     */

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 写业务逻辑
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        // 根据业务鉴权
        if (StrUtil.isEmpty(token)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            Mono<Void> voidMono = exchange.getResponse().setComplete();
            return voidMono;
        }
        Mono<Void> filter = chain.filter(exchange);
        return filter;
    }

    // 数字越小,优先级越高
    @Override
    public int getOrder() {
        return 0;
    }


}

十一、albabaCloud下实现链路追踪功能

1.快速排查问题所在

2.快速排查调用慢的情况

1.链路追踪系统Sleuth

简介:讲解什么Sleuth链路追踪系统

  • 什么是Sleuth
    • 一个组件,专门用于记录链路数据的开源组件
    • 文档:https://spring.io/projects/spring-cloud-sleuth
    • 案例
    [order-service,96f95a0dd81fe3ab,852ef4cfcdecabf3,false]
    
    第一个值,spring.application.name的值
    
    第二个值,96f95a0dd81fe3ab ,sleuth生成的一个ID,叫Trace ID,用来标识一条请求链路,一条请求链路中包含一个Trace ID,多个Span ID
    
    第三个值,852ef4cfcdecabf3、spanid 基本的工作单元,获取元数据,如发送一个http
    
    第四个值:false,是否要将该信息输出到zipkin服务中来收集和展示。

导入jar:

 <!--sleuth 链路追踪-->
<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>

2.链路追踪系统ZipKin 部署实战

  • 什么是zipkin

    • 官网
      • https://zipkin.io/
      • https://zipkin.io/pages/quickstart.html
    • 大规模分布式系统的APM工具(Application Performance Management),基于Google Dapper的基础实现,和sleuth结合可以提供可视化web界面分析调用链路耗时情况
  • 同类产品

    • 鹰眼(EagleEye)
    • CAT
    • twitter开源zipkin,结合sleuth
    • Pinpoint,运用JavaAgent字节码增强技术
  • StackDriver Trace (Google)

  • 开始使用

    • 安装包在资料里面,启动服务
    java -jar zipkin-server-2.12.9-exec.jar
    
    • 访问入口:http://127.0.0.1:9411/zipkin/
    • zipkin组成:Collector、Storage、Restful API、Web UI组成

3.链路追踪组件Zipkin+Sleuth整合实战

简介:使用Zipkin+Sleuth业务分析调用链路分析实战

  • sleuth收集跟踪信息通过http请求发送给zipkin server
  • zipkin server进行跟踪信息的存储以及提供Rest API即可
  • Zipkin UI调用其API接口进行数据展示默认存储是内存,可也用mysql 或者elasticsearch等存储
  • 微服务加入依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
  • 配置地址和采样百分比配置
spring:
  application:
    name: api-gateway
  zipkin:
    base-url: http://127.0.0.1:9411/ #zipkin地址
    discovery-client-enabled: false  #不用开启服务发现

  sleuth:
    sampler:
      probability: 1.0 #采样百分比
默认为0.1,即10%,这里配置1,是记录全部的sleuth信息,是为了收集到更多的数据(仅供测试用)。
在分布式系统中,过于频繁的采样会影响系统性能,所以这里配置需要采用一个合适的值。

4.Zipkin持久化配置

持久化的数据库sql脚本:

/*
Navicat MySQL Data Transfer

Source Server         : mydata
Source Server Version : 50726
Source Host           : localhost:3306
Source Database       : zipkin_log

Target Server Type    : MYSQL
Target Server Version : 50726
File Encoding         : 65001

Date: 2020-10-26 17:17:01
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for zipkin_annotations
-- ----------------------------
DROP TABLE IF EXISTS `zipkin_annotations`;
CREATE TABLE `zipkin_annotations` (
  `trace_id_high` bigint(20) NOT NULL DEFAULT '0' COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
  `trace_id` bigint(20) NOT NULL COMMENT 'coincides with zipkin_spans.trace_id',
  `span_id` bigint(20) NOT NULL COMMENT 'coincides with zipkin_spans.id',
  `a_key` varchar(255) NOT NULL COMMENT 'BinaryAnnotation.key or Annotation.value if type == -1',
  `a_value` blob COMMENT 'BinaryAnnotation.value(), which must be smaller than 64KB',
  `a_type` int(11) NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if Annotation',
  `a_timestamp` bigint(20) DEFAULT NULL COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp',
  `endpoint_ipv4` int(11) DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null',
  `endpoint_ipv6` binary(16) DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address',
  `endpoint_port` smallint(6) DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null',
  `endpoint_service_name` varchar(255) DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null',
  UNIQUE KEY `trace_id_high` (`trace_id_high`,`trace_id`,`span_id`,`a_key`,`a_timestamp`) COMMENT 'Ignore insert on duplicate',
  KEY `trace_id_high_2` (`trace_id_high`,`trace_id`,`span_id`) COMMENT 'for joining with zipkin_spans',
  KEY `trace_id_high_3` (`trace_id_high`,`trace_id`) COMMENT 'for getTraces/ByIds',
  KEY `endpoint_service_name` (`endpoint_service_name`) COMMENT 'for getTraces and getServiceNames',
  KEY `a_type` (`a_type`) COMMENT 'for getTraces and autocomplete values',
  KEY `a_key` (`a_key`) COMMENT 'for getTraces and autocomplete values',
  KEY `trace_id` (`trace_id`,`span_id`,`a_key`) COMMENT 'for dependencies job'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED;

-- ----------------------------
-- Table structure for zipkin_dependencies
-- ----------------------------
DROP TABLE IF EXISTS `zipkin_dependencies`;
CREATE TABLE `zipkin_dependencies` (
  `day` date NOT NULL,
  `parent` varchar(255) NOT NULL,
  `child` varchar(255) NOT NULL,
  `call_count` bigint(20) DEFAULT NULL,
  `error_count` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`day`,`parent`,`child`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED;

-- ----------------------------
-- Table structure for zipkin_spans
-- ----------------------------
DROP TABLE IF EXISTS `zipkin_spans`;
CREATE TABLE `zipkin_spans` (
  `trace_id_high` bigint(20) NOT NULL DEFAULT '0' COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
  `trace_id` bigint(20) NOT NULL,
  `id` bigint(20) NOT NULL,
  `name` varchar(255) NOT NULL,
  `remote_service_name` varchar(255) DEFAULT NULL,
  `parent_id` bigint(20) DEFAULT NULL,
  `debug` bit(1) DEFAULT NULL,
  `start_ts` bigint(20) DEFAULT NULL COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL',
  `duration` bigint(20) DEFAULT NULL COMMENT 'Span.duration(): micros used for minDuration and maxDuration query',
  PRIMARY KEY (`trace_id_high`,`trace_id`,`id`),
  KEY `trace_id_high` (`trace_id_high`,`trace_id`) COMMENT 'for getTracesByIds',
  KEY `name` (`name`) COMMENT 'for getTraces and getSpanNames',
  KEY `remote_service_name` (`remote_service_name`) COMMENT 'for getTraces and getRemoteServiceNames',
  KEY `start_ts` (`start_ts`) COMMENT 'for getTraces ordering and range'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED;

运行指令:

java -jar zipkin-server-2.12.9-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=127.0.0.1 --MYSQL_TCP_PORT=3306 --MYSQL_DB=zipkin_log --MYSQL_USER=root --MYSQL_PASS=xdclass

十二、配置中心nacos

1.注释原来的 application.yml 文件

新建一个 bootstrap.yml 文件

spring:
  application:
    name: xdclass-api-gateway
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848 #Nacos配置中心地址
        file-extension: yaml #文件拓展格式
  profiles:
    active: dev

若不可用则重新编译项目:

重新构建下项目 

mvn clean package -U

然后重启IDEA

在nacos中配置:

  • dataId组成,在 Nacos Spring Cloud 中,dataId 的完整格式如下
${prefix}-${spring.profiles.active}.${file-extension}

prefix 默认为 spring.application.name 的值

spring.profiles.active 即为当前环境对应的 profile
当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 ${prefix}.${file-extension}

file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 properties 和 yaml 类型。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DiHWkiOC-1606960678014)(C:\Users\AOSSCI\AppData\Roaming\Typora\typora-user-images\image-20201026172918849.png)]

2.配置中心下面动态的获取配置属性

  • 什么是动态刷新配置
    • 我们修改了配置,程序不能自动更新
    • 动态刷新就可以解决这个问题
  • 配置实战
    • 增加Nacos增加测试配置
    • 编写代码

编写代码动态获取文件:

@RequestMapping("/api/v1/get")
@RestController
@RefreshScope
public class GatewayConfigRefresh {

    @Value("${gateway.title}")
    private String gatewayTitle;

    @GetMapping("/test")
    public Object test(){
        return gatewayTitle;
    }

}

更多推荐

springcloud 和 springalibabaCloud组件详细解析