初识SpringCloud笔记一

SpringCloud

一、引言

1.1 什么是SpringCloud?

SpringCloud是基于SpringBoot的一整套实现微服务的框架。它提供了微服务开发所需的配置管理、服务发现、断路器、智能路由、微代理、控制总线、全局锁、决策竞选、分布式会话和集群状态管理等组件。最重要的是,跟spring boot框架一起使用的话,会让你开发微服务架构的云服务非常好的方便。

1.2 什么是微服务?

单体架构中,所有的代码集中在同一个项目中。虽然便于管理,但是当项目足够庞大时,所有的业务模块都集中在一个JVM进程中,会面临很多问题:
1、项目过于臃肿,难以维护
2、资源无法隔离,某个资源出现问题,整个系统崩溃
3、拓展性差,通常只能水平拓展,缺乏灵活性

什么是微服务?

简单来说,微服务架构风格是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制(通常用HTTP资源API)。这些服务围绕业务能力构建并且可通过全自动部署机制独立部署。这些服务共用一个最小型的集中式的管理,服务可用不同的语言开发,使用不同的数据存储技术。

微服务的特点:

1、根据业务模块划分服务
2、每个服务可以独立部署并且互相隔离
3、通过轻量的 API 调用服务
4、服务需要保证良好的高可用性

三高(高并发、高性能、高可用)

二、SpringCloud的注册中心 - Eureka

2.1 什么是注册中心?为什么要注册中心?
	服务注册中心是服务实现服务化管理的核心组件,类似于目录服务的作用,主要用来存储服务信息,譬如提供者 url 串、路由信息等。服务注册中心是微服务架构中最基础的设施之一。
	**注册中心可以说是微服务架构中的“通讯录”,它记录了服务和服务地址的映射关系。在分布式架构中,服务会注册到这里,当服务需要调用其它服务时,就到这里找到服务的地址,进行调用。**
	简单理解就是:在没有注册中心时候,服务间调用需要知道被当服务调方的具体地址(写死的 ip:port)。更换部署地址,就不得不修改调用当中指定的地址。而有了注册中心之后,每个服务在调用别人的时候只需要知道服务名称(软编码)就好,地址都会通过注册中心根据服务名称获取到具体的服务地址进行调用。
	了解了什么是注册中心,那么我们继续谈谈,为什么需要注册中心。在分布式系统中,我们不仅仅是需要在注册中心找到服务和服务地址的映射关系这么简单,我们还需要考虑更多更复杂的问题:
  • 服务注册后,如何被及时发现 ;
  • 服务宕机后,如何及时下线;
  • 服务如何有效的水平扩展;
  • 服务发现时,如何进行路由;
  • 服务异常时,如何进行降级;
  • 注册中心如何实现自身的高可用。
    这些问题的解决都依赖于注册中心。简单看,注册中心的功能有点类似于 DNS 服务器或者负载均衡器,而实际上,注册中心作为微服务的基础组件,可能要更加复杂,也需要更多的灵活性和时效性。所以我们还需要学习更多 Spring Cloud 微服务组件协同完成应用开发。
    注册中心解决了以下问题:
  • 服务管理;
  • 服务之间的自动发现;
  • 服务的依赖关系管理。
    常见的注册中心
  • Netflix Eureka
  • Alibaba Nacos
  • HashiCorp Consul
  • Apache ZooKeeper
  • CoreOS Etcd
  • CNCF CoreDNS
    在这里插入图片描述
    原文地址
2.2 Eureka注册中心的搭建

1)创建父工程(继承SpringBoot工程、SpringCloud依赖)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!-- 当前工程继承了SpringBoot父工程 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.jh</groupId>
    <artifactId>springcloud_demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR5</spring-cloud.version>
    </properties>

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

    <!-- 相当于让当前的工程继承了spring-cloud-dependencies工程 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <!--<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>-->

</project>

2)创建Eureka微服务(继承自定义的父工程)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <!-- 继承自定义父工程 -->
        <groupId>com.jh</groupId>
        <artifactId>springcloud_demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <artifactId>microserver_eureka</artifactId>

    <dependencies>
        <!-- 添加Eureka Server依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

3)启用Eureka服务(启动类)

@SpringBootApplication
@EnableEurekaServer
public class MicroserverEurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(MicroserverEurekaApplication.class, args);
    }
}

4)配置application.yml

#配置注册中心的端口
server:
  port: 20000
#配置微服务的名字(重要,千万别写下划线)
spring:
  application:
    name: eureka-server
#配置注册中心的地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:20000/eureka
    #当前微服务是否可以去调用其他微服务,默认为true,如果当前微服务是注册中心的话,则必须设置为false
    fetch-registry: false
    #当前微服务就不会注册到注册中心上(其他的微服务就不能调用当前微服务了,但是当前微服务仍然可以调用其他微服务)
    register-with-eureka: false

5)启动注册中心,查看控制页面
在这里插入图片描述

2.3 服务的注册 - 微服务

1)添加相关依赖

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

2)配置启动类

@SpringBootApplication
@EnableEurekaClient
public class MicroserverStuApplication {

    public static void main(String[] args) {
        SpringApplication.run(MicroserverStuApplication.class, args);
    }

}

3)配置application.yml

server:
  port: 8080
spring:
  application:
    name: micro-stu
eureka:
  client:
    service-url:
      #配置注册中心的地址
      defaultZone: http://localhost:20000/eureka

4)编写微服务提供的接口(controller)

package com.jh.controller;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/stu")
public class StuController {

    @RequestMapping("/query/{sid}")
    public String queryNameById(@PathVariable("sid") Integer sid){
        switch (sid){
            case 1:
                return "小明";
            case 2:
                return "小红";
        }
        return "查无此人";
    }
}

5)启动微服务实现注册
在这里插入图片描述

2.4 Eureka集群的搭建

Eureka集群的工作模式
在这里插入图片描述

注意:Eureka集群最多可以挂掉n-1台机器,仍然可以对外提供服务

集群搭建的步骤:
1)准备3个Eureka服务,错开端口
在这里插入图片描述
2)修改本机的hosts文件,给每个Eureka服务分配一个主机别名(实际的集群中不需要)

127.0.0.1 eureka1
127.0.0.1 eureka2
127.0.0.1 eureka3

hosts文件的路径:
window - C:\Windows\System32\drivers\etc\hosts
linux - /etc/hosts

3)修改eureka服务的注册地址

eureka:
  client:
    service-url:
      defaultZone: http://eureka1:20000/eureka,http://eureka2:20001/eureka,http://eureka3:20002/eureka
2.5 Eureka的自我保护机制
  1. 当我们进行SpringCloud微服务开发的时候,有可能会出现如下的一些红色提示信息。这个是Eureka的自我保护机制。
  2. Eureka的自我保护机制用最通俗的语言说就是:好死不如赖活着。一句话:某时刻某一个微服不可用了,eureka不会立刻清理,依旧会对改微服的信息进行保存。
  3. 默认情况下,如果eureka server在一定时间内没有接收到每个微服务实例的心跳,eureka server将会注销该实例。
  4. 当网络分区故障发生时,微服务与eureka server之间无法正常通信,以上行为可能变得非常危险了,因为微服务本身其实是健康的,此时本不应该注销这个微服务。eureka通过“自我保护模式来解决这个问题”。
  5. 在自我保护模式中,eureka server会保护服务注册表中的信息,不再注销任何服务实例。当它收到的心跳数重新恢复到阀值以上时,该eureka server节点就会自动退出自我保护模式。
    在spring cloud中,可以使用
eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url: 
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  server:
    enable-self-preservation: false

禁用自我保护模式。
原文地址

三、微服务的调用 - Ribbon + RestTemplate

3.1 什么是Ribbon?

Ribbon本质上是一个客户端负载均衡器,在SpringCloud中主要的作用包含两个:
1、去Eureka上发现服务
2、负载均衡调用指定微服务

什么是服务端负载均衡?
在这里插入图片描述
什么是客户端负载均衡?
在这里插入图片描述

注意:客户端负载均衡往往会配合注册中心一起使用

3.2 Ribbon的服务调用

1)创建一个班级服务,注册到注册中心之上,实现学生服务对班级服务的调用

2)调用方添加依赖

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

3)注册RestTemplate对象

   /**
     * 注册RestTemplate对象
     * @return
     */
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }

4)在调用方使用RestTemplate发送请求

@Autowired
private RestTemplate restTemplate;

...
String clsName = restTemplate
		.getForObject("http://micro-cls/cls/queryName/" + sid, String.class);

注意:
1、RestTemplate需要添加**@LoadBalanced才会配合Ribbon进行负载均衡和服务发现
2、RestTemplate请求的地址必须填写
微服务的名称**

3.3 Ribbon负载均衡的策略

Ribbon实现负载均衡策略的核心接口 - IRule
在这里插入图片描述
在这里插入图片描述

设置负载均衡策略

/**
 * 设置负载均衡策略
 * @return
 */
@Bean
public IRule getRule(){
    return new RandomRule();
}

四、微服务的调用 - Feign

Feign其实本质上就是Ribbon + Hystrix,提供了更加面向对象的服务调用方式

4.1 Feign的服务调用

1)创建教师微服务,注册到注册中心上

2)调用方(班级服务)添加依赖

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

3)编写Feign的调用接口

@FeignClient(name = "micro-tea")
public interface TeaFeign {

    @RequestMapping("/tea/queryName/{tid}")
    String queryTeaName(@PathVariable Integer tid);
}

4)启动类添加注解,配置Feign接口的扫描

@EnableFeignClients(basePackages = "com.jh.feign")

5)使用Feign调用微服务

4.2 Feign的超时时间和重试

Feign本身拥有超时和重试的设定,但是默认是关闭的。Feign默认采用的是底层Ribbon的重试和超时的设定,一旦Feign的超时和重试开启,那么就会覆盖Ribbon的设置。

Ribbon的读超时默认是1s,连接超时默认也是1s,跨服务重试的次数默认1次,同服务重试的次数默认1次

feign的超时和重试的设置

ribbon:
  ConnectTimeout: 1000  #毫秒    连接超时时间
  ReadTimeout: 1000    #毫秒      读超时时间
  MaxAutoRetries: 0     # 对当前实例的最大重试次数
  MaxAutoRetriesNextServer: 1     # 切换实例的最大重试次数(如果还失败就切换下

注意:
1、实际开发过程中,可以根据业务适当的调整Read超时的大小
2、实际开发过程中,根据需要可以开启或者关闭重试,但是需要注意,如果开启了重试,就有重复请求的风险,尽可能的需要保证服务的被调用方的接口幂等

如何构造一个幂等的接口?

1、给数据库的某些字段设置唯一性
2、结合缓存服务器Redis实现接口幂等

五、断路器 - Hystrix

什么Hystrix(豪猪)?

Hystrix是微服务架构体系的保险丝

为什么要Hystrix?

在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以相互调用。
为了保证其高可用,单个服务通常会集群部署。由于网络原因或者自身的原因,
服务并不能保证100%可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,
此时若有大量的请求涌入,Servlet容器的线程资源会被消耗完毕,导致服务瘫痪。
服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,
这就是服务故障的“雪崩”效应。

为了解决这个问题,业界提出了断路器模型。

Hystrix是如何保证服务的可用性的

资源的隔离:Hystrix会通过一些方式(线程池隔离、信号量隔离),对Tomcat的线程池资源进行隔离限制,让Tomcat不要将所有的线程资源都用在一个微服务请求上

服务的降级:对于一些超时或者失败的请求,可以自动的去调用一个托底方法,返回一个默认值,这种方式称之为服务降级

请求的熔断:如果对某个微服务的请求失败达到一定的比例,熔断器就会自动的开启,一旦熔断器开启,所有发送给该微服务的请求,会立刻判定失败,调用降级方法。

5.1 在Feign中使用Hystrix

1)开启Feign中Hystrix的功能(默认关闭)

feign:
  hystrix:
    enabled: true

2)编写Feign接口的实现类(Hystrix的降级方法实现类)

@Component
public class TeaFeignHystrix implements TeaFeign {

    /**
     * 重写的方法就是所谓的降级方法(托底方法)
     * @param tid
     * @return
     */
    @Override
    public String queryTeaName(Integer tid) {
        return "服务繁忙,请稍后再试!";
    }
}

3)去设置Feign接口的注解

@FeignClient(name = "micro-tea", fallback = TeaFeignHystrix.class)
5.2 Hystrix的相关配置
hystrix:
  command:
    default:
      execution:
        isolation:
          #资源隔离方法,THREAD:线程池隔离(默认值),SEMAPHORE:信号量隔离
          strategy: THREAD
          thread:
            #调用的超时时间,默认1s
            timeoutInMilliseconds: 5000
        #是否开启Hystrix的超时,默认是开启,如果关闭了,Feign本身的超时仍然起作用
        timeout:
          enabled: true
      #熔断器的配置,默认开启
      circuitBreaker:
        enabled: true
        #单位时间内,使熔断器跳闸的最小异常请求(访问失败或者超时等)次数。如果失败的请求达到该值,则熔断器就会打开,默认值为20
        requestVolumeThreshold: 2
        #多久时间熔断器进入半开状态
        sleepWindowInMilliseconds: 5000
  #设置线程池隔离时,线程池大小,默认是10
  threadpool:
    default:
      coreSize: 10

注意:如果开启了Hystrix,服务调用的超时时间,就取决于Ribbon和Hystrix中最小读取超时时间

5.3 搭建Hystrix的监控仪表盘

Hystrix 仪表盘主要用来监控微服务和微服务之间的调用情况

1)创建Hystrix仪表盘工程

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

2)启动类添加注解

@EnableHystrixDashboard

3)修改端口启动工程

4)访问浏览器地址,查看仪表盘的监控的页面

在这里插入图片描述

5)配置被监控的微服务(案例中,需要配置班级服务)

<!-- 添加依赖 -->
<dependency>
    <groupId>com.netflix.hystrix</groupId>
    <artifactId>hystrix-metrics-event-stream</artifactId>
</dependency>
@Configuration
public class HystrixConfiguration {

    @Bean
    public ServletRegistrationBean<HystrixMetricsStreamServlet> getServlet(){
        HystrixMetricsStreamServlet hystrixMetricsStreamServlet = new HystrixMetricsStreamServlet();

        ServletRegistrationBean<HystrixMetricsStreamServlet> servletRegistrationBean = new ServletRegistrationBean();
        servletRegistrationBean.setServlet(hystrixMetricsStreamServlet);
        servletRegistrationBean.addUrlMappings("/hystrix.stream");
        servletRegistrationBean.setName("HystrixMetricsStreamServlet");
        return servletRegistrationBean;
    }
}

在被监控微服务中
在这里插入图片描述

6)在仪表盘的监控路径中,添加班级服务的监控路径
在这里插入图片描述

在这里插入图片描述

六、路由网关 - Gateway

为什么需要路由网关?

路由网关会作为微服务架构体系的入口组件,所有的外部请求,都必须经过路由网关分发(内部互相访问没有影响),这样可以屏蔽微服务体系结构复杂性,并且可以提供请求路由、负载访问、请求过滤整形等功能。
在这里插入图片描述
在这里插入图片描述

6.1 搭建Gateway

1)创建一个SpringBoot工程(依赖Eureka-Client、Gateway,千万不要依赖web)

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

2)启动类注解

@EnableEurekaClient

3)配置application.yml

server:
  port: 80
spring:
  application:
    name: gateway
eureka:
  client:
    service-url:
      defaultZone: http://eureka1:20000/eureka,http://eureka2:20001/eureka,http://eureka3:20002/eureka

4)配置getaway的路由功能(静态路由)

spring:
  application:
    name: gateway
  cloud:
    gateway:
      #配置静态路由
      routes:
        #----路由规则1---------
        - id: guize1 #当前的路由规则标识,不重复的合法标识即可
          predicates: #配置路由断言,路由的条件
            - Path=/stu/**
          uri: lb://micro-stu
        #----路由规则2---------
        - id: guize2 #当前的路由规则标识,不重复的合法标识即可
          predicates: #配置路由断言,路由的条件
            - Path=/cls/**
            - Query=token
          uri: lb://micro-cls

注意可以不用加上微服务名称

http://localhost/stu/queryName/1

6.2 动态路由 (后面补充)
6.3 过滤器链 (后面补充)

七、链路追踪 - sleuth

什么是链路追踪?

微服务会有很多的服务互相调用,我们的一个业务到底用了多少微服务,每个微服务耗时多少,中间出现了异常,到底是谁出现了异常,所以我需要对请求的链路进行追踪
在这里插入图片描述

7.1 使用Docker搭建链路追踪的监控平台 - zipkin

1)拉取zipkin的镜像

docker pull openzipkin/zipkin

2)配置zipkin的docker-compose模板

version: "3.1"
services:
  zipkin:
    image: openzipkin/zipkin
    restart: always
    volumes:
      - ./zipkin/localtime:/etc/localtime
    ports:
      - 9411:9411
    container_name: zipkin

3)执行命令,创建容器

docker-compose up -d

在这里插入图片描述

4)开放端口,访问zipkin图形化页面

​ 查看哪些端口被打开 netstat -anp,在linux中
在这里插入图片描述

7.2 给所有微服务配置链路追踪

1)微服务添加依赖

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

2)配置application.yml

spring:
  zipkin:
    #配置zipkin服务的地址
    base-url: http://192.168.195.188:9411
  sleuth:
    sampler:
      #链路采样率,默认0.1
      probability: 1
7.3 整合MySQL持久化zipkin链路数据

在这里插入图片描述

1)创建mysql容器

  mysql:
    image: mysql:5.7
    ports:
      - 3306:3306
    container_name: mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
    volumes:
      - ./mysql/conf:/etc/mysql/conf.d
      - ./mysql/logs:/logs
      - ./mysql/data:/var/lib/mysql
    restart: always

2)连接mysql创建zipkin的表结构

create database `zipkin` /*!40100 DEFAULT CHARACTER SET utf8 */;
use zipkin;

create table if not exists zipkin_spans (
  `trace_id_high` bigint not null default 0 comment 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',

  `trace_id` bigint not null,

  `id` bigint not null,

  `name` varchar(255) not null,

  `remote_service_name` varchar(255),

  `parent_id` bigint,

  `debug` bit(1),

  `start_ts` bigint comment 'Span.timestamp(): epoch micros used for endTs query and to implement TTL',

  `duration` bigint comment 'Span.duration(): micros used for minDuration and maxDuration query',

  primary key (`trace_id_high`, `trace_id`, `id`)

) engine=innodb row_format=compressed character set=utf8 collate utf8_general_ci;

 

alter table zipkin_spans add index(`trace_id_high`, `trace_id`) comment 'for getTracesByIds';

alter table zipkin_spans add index(`name`) comment 'for getTraces and getSpanNames';

alter table zipkin_spans add index(`remote_service_name`) comment 'for getTraces and getRemoteServiceNames';

alter table zipkin_spans add index(`start_ts`) comment 'for getTraces ordering and range';

 

create table if not exists zipkin_annotations (

  `trace_id_high` bigint not null default 0 comment 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',

  `trace_id` bigint not null comment 'coincides with zipkin_spans.trace_id',

  `span_id` bigint 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 not null comment 'BinaryAnnotation.type() or -1 if Annotation',

  `a_timestamp` bigint comment 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp',

  `endpoint_ipv4` int comment 'Null when Binary/Annotation.endpoint is null',

  `endpoint_ipv6` binary(16) comment 'Null when Binary/Annotation.endpoint is null, or no IPv6 address',

  `endpoint_port` smallint comment 'Null when Binary/Annotation.endpoint is null',

  `endpoint_service_name` varchar(255) comment 'Null when Binary/Annotation.endpoint is null'

) engine=innodb row_format=compressed character set=utf8 collate utf8_general_ci;

 

alter table zipkin_annotations add unique key(`trace_id_high`, `trace_id`, `span_id`, `a_key`, `a_timestamp`) comment 'Ignore insert on duplicate';

alter table zipkin_annotations add index(`trace_id_high`, `trace_id`, `span_id`) comment 'for joining with zipkin_spans';

alter table zipkin_annotations add index(`trace_id_high`, `trace_id`) comment 'for getTraces/ByIds';

alter table zipkin_annotations add index(`endpoint_service_name`) comment 'for getTraces and getServiceNames';

alter table zipkin_annotations add index(`a_type`) comment 'for getTraces and autocomplete values';

alter table zipkin_annotations add index(`a_key`) comment 'for getTraces and autocomplete values';

alter table zipkin_annotations add index(`trace_id`, `span_id`, `a_key`) comment 'for dependencies job';

 

create table if not exists zipkin_dependencies (
  `day` date not null,
  `parent` varchar(255) not null,
  `child` varchar(255) not null,
  `call_count` bigint,
  `error_count` bigint,
  primary key (`day`, `parent`, `child`)
) engine=innodb row_format=compressed character set=utf8 collate utf8_general_ci;

3)重新创建zipkin的容器,需要连接数据库

zipkin:
    image: openzipkin/zipkin
    restart: always
    volumes:
      - ./zipkin/localtime:/etc/localtime
    ports:
      - 9411:9411
    container_name: zipkin
    environment:
      MYSQL_USER: root
      MYSQL_PASS: root
      MYSQL_HOST: 192.168.195.148
      STORAGE_TYPE: mysql
      MYSQL_DB: zipkin
      MYSQL_TCP_PORT: 3306

4)重新构建zipkin的容器

docker-compose up -d --build zipkin

八、分布式配置管理中心 - SpringCloud Config

什么是分布式配置管理?

在这里插入图片描述

8.1 搭建分布式配置管理服务端 - Config Server(Github)

1)在github上创建仓库管理配置文件

​ 1.1、在github上创建仓库** java20study_config**

​ 1.2、在D:\gitconfig打开
在这里插入图片描述

git init
git add .
git commit -m "first commit"
git remote add origin https://github.com/903658216/java20study_config.git
git push -u origin master

在这里插入图片描述

配置全局的用户名和邮箱
在这里插入图片描述
在这里插入图片描述

2)创建Config Server管理Github上的配置文件
​ 添加依赖

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

​ 启动类配置

@EnableConfigServer

​ 配置application.yml

server:
  port: 40000
spring:
  cloud:
    config:
      server:
        #通过git进行管理
        git:
          #配置git服务的地址
          uri: https://github.com/xxxxxxx/springcloud_config.git
        #通过svn进行管理
        svn:
          uri:
          username:
          password:

3)搭建Config Client配置读取的客户端
​ 添加依赖

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

编写配置文件bootstrap.yml

spring:
  cloud:
    config:
      #配置当前config server的地址
      uri: http://localhost:40000
      #读取的配置文件的名称
#      name: application
      name: gitconfig
      #读取的配置文件的环境
      profile: default
      #配置读取的分支
      label: master

在SpringBoot启动过程中,会先加载bootstrap.yml,再加载application.yml

8.2 微服务不重启更新配置的方式

1)微服务(config client)添加依赖

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

2)开放执行器的所有接口(配置在config client的bootstrap.yml)

#暴露所有节点
management:
  endpoints:
    web:
      exposure:
        include: '*'

3)在需要更新配置的类上,添加注解@RefreshScope

@RestController
@RefreshScope
public class TestGit {

    @Value("${com.name}")
    private String name;

    @RequestMapping("/test")
    public String test(){
        return name;
    }

}

4)查看微服务的执行器的节点

Exposing 15 endpoint(s) beneath base path ‘/actuator’

控制台打印这个表示actuator执行器生效了

访问:http://localhost:8080/actuator
在这里插入图片描述

 "refresh":{
            "href":"http://localhost:8080/actuator/refresh",
            "templated":false
        }

5)修改Config Server的配置信息后,给微服务发送post请求

http://localhost:8080/actuator/refresh

注意:
1、请求类型必须是post请求
2、请求头必须包含Content-Type: application/json

配置自动更新的终极方案结构
在这里插入图片描述
在这里插入图片描述

配置开发环境、测试环境、生产环境

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

maven 占位符

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

启动 服务的时候可能target包没有编译进去,所以可能手动build一下

PS 统一配置中心的一些细节

1、如果配置是放到Git服务器或者SVN服务器上时,Config Server永远都是直接去服务器上读取最新的配置,所以配置发生变化时,Config Server无需重启

2、如果配置是放在Config Server的本地,那么配置发生变化时,需要重启Config Server

3、如果配置发生变化,Config Client默认也是必须重启才能读取到最新配置

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值