SpringCloud(10~16장): Hystrix 회로 차단기, zuul 라우팅 게이트웨이, 게이트웨이 차세대 게이트웨이, 구성 분산 구성 센터, 버스 메시지 버스, 스트림 메시지 드라이버, Sleuth 분산 링크 추적

10. 히스트릭스 회로 차단기

  • 비록 Hystrix 서비스 저하 프레임워크 SpringCloud가 공식적으로 업데이트를 중단했지만 서비스 저하, 서비스 회로 차단기, 서비스 전류 제한 등의 디자인 컨셉은 매우 우수하며 일련의 아이디어는 후속 프레임워크에서 배울 수 있는 필수 의학입니다. 그래서 우리는 Hystrix에 대해 더 깊이 살펴볼 필요가 있습니다.
  • 이제 공식 웹사이트에서는 resilience4j 사용을 권장하지만 해외에서는 더 일반적으로 사용됩니다.
  • 중국에서는 주로 Hystrix나 Senienl(Alibaba사)를 사용하고 있습니다.
  • 소비자 측과 서비스 측 모두에서 사용할 수 있으며 일반적으로 소비자 측에서 사용됩니다.

10.1 개요

10.1.1 분산 시스템이 직면한 문제

  • 분산 시스템이 직면한 문제

    • 复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败。
      여기에 이미지 설명을 삽입하세요.
  • 서비스 눈사태

    • 여러 마이크로서비스 간을 호출할 때 마이크로서비스 A가 마이크로서비스 B와 마이크로서비스 C를 호출하고, 마이크로서비스 B와 마이크로서비스 C가 다른 마이크로서비스를 호출한다고 가정해 보겠습니다 “扇出”. 팬아웃 링크에 있는 특정 마이크로서비스의 호출 응답 시간이 너무 길거나 사용할 수 없는 경우 마이크로서비스 A에 대한 호출은 점점 더 많은 시스템 리소스를 차지하게 되어 소위 "눈사태 효과"라고 ​​불리는 시스템 충돌을 일으킵니다.
    • 트래픽이 많은 애플리케이션의 경우 단일 백엔드 종속성으로 인해 모든 서버의 모든 리소스가 몇 초 내에 포화될 수 있습니다. 실패보다 더 나쁜 것은 이러한 애플리케이션으로 인해 서비스 간의 대기 시간이 증가하고 백업 대기열, 스레드 및 기타 시스템 리소스에 부담이 가해져 시스템 전체에 걸쳐 연쇄적인 실패가 더 많이 발생할 수도 있다는 점입니다. 이는 모두 단일 종속성 오류로 인해 전체 애플리케이션이나 시스템이 중단되지 않도록 오류 및 지연을 격리하고 관리해야 함을 나타냅니다. 따라서 일반적으로 모듈 아래의 인스턴스에 장애가 발생하면 해당 모듈은 여전히 ​​트래픽을 수신하고 문제가 있는 모듈은 다른 모듈도 호출하므로 연쇄 장애, 즉 눈사태가 발생하게 됩니다 .
  • 예: 서비스 80은 8001을 호출하고, 8001은 8002를 호출하고, 8002는 8004를 호출하고, 8004는 8006을 호출합니다. 서로 하나씩 호출하면 링크가 점점 길어지고, 둘 중 하나만 잘못되면 모든 서비스에 문제가 발생합니다.

10.1.2이란 무엇입니까?

  • Hystrix는 분산 시스템을 처리하는 데 사용되는 延迟오픈 소스 라이브러리 容错입니다. 분산 시스템에서는 시간 초과, 예외 등과 같은 많은 종속성이 필연적으로 호출에 실패합니다 不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性.
  • "서킷 브레이커" 자체가 스위칭 장치로서, 서비스 유닛에 장애가 발생했을 때 서킷 브레이커의 장애 모니터링(퓨즈 단선과 유사)을 통해 向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常서비스 호출자의 스레드가 불필요하게 장기간 차단되지 않도록 보장합니다. 토지가 점유되어 분산 시스템의 결함 확산과 심지어 눈사태도 방지됩니다.

10.1.3 수행할 수 있는 작업

  • 서비스 다운그레이드
  • 서비스 회로 차단기
  • 거의 실시간 모니터링

10.1.4 공식 홈페이지 정보

  • 공식 홈페이지 정보: https://github.com/Netflix/Hystrix/wiki/How-To-Use
    여기에 이미지 설명을 삽입하세요.

10.1.5 Hystrix 공식 발표, 점검을 위한 업데이트 중단

  • https://github.com/Netflix/Hystrix
    여기에 이미지 설명을 삽입하세요.
  • 수동적으로 버그 수정
  • 병합 요청은 더 이상 허용되지 않습니다.
  • 더 이상 새로운 릴리스가 없습니다

10.2 Hystrix의 중요한 개념

10.2.1 서비스 다운그레이드 폴백

  • 서버가 사용 중입니다. 클라이언트를 기다리지 말고 나중에 다시 시도하고 즉시 친숙한 프롬프트를 반환하십시오.
    • 즉, if-else 구조와 유사하게 상대방의 시스템을 사용할 수 없으므로 명확한 해결 방법을 제시해야 합니다.
  • 어떤 상황에서 다운그레이드가 발생하나요?
    • 프로그램이 비정상적으로 실행됨
    • 타임아웃
    • 서비스 회로 차단기가 서비스 저하를 유발합니다.
    • 스레드 풀/세마포어가 가득 차면 서비스 저하도 발생합니다.

10.2.2 서비스 중단

  • 아날로그 퓨즈가 최대 서비스 액세스에 도달한 후 액세스가 직접 거부되고 전원이 차단된 후 서비스 다운그레이드 방법이 호출되고 친숙한 프롬프트가 반환됩니다.
  • 퓨즈입니다. 서비스 저하 -> 퓨즈 -> 통화 링크 복원
  • 서비스 중단도 일종의 다운그레이드로 간주될 수 있습니다.

10.2.3 서비스 흐름 제한 flowlimit

  • 동시성이 높은 플래시 킬링 등의 작업은 크라우딩을 엄격히 금지하며, 모두가 초당 N회씩 줄을 서서 질서정연하게 진행한다.

10.3 히스트릭스 케이스

  • 여러 서비스를 시작하는 것이 번거로워 테스트를 위해 독립형 버전으로 변경했습니다.
    • 7001이 독립형 버전으로 복원되었습니다.
      여기에 이미지 설명을 삽입하세요.

10.3.1 빌드

1) 새로운 cloud-provider-hystrix-pay8001을 생성합니다.

  • 히스트릭스가 날아간 8001을 만들어보세요
    여기에 이미지 설명을 삽입하세요.

2) 포엠

여기에 이미지 설명을 삽입하세요.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.angenin.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-provider-hystrix-payment8001</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <!--hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!--eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
            <groupId>com.angenin.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

3) YML

여기에 이미지 설명을 삽입하세요.

server:
  port: 8001

spring:
  application:
    name: cloud-provider-hystrix-payment

eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      #集群版
      #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
      #单机版
      defaultZone: http://eureka7001.com:7001/eureka

4) 메인 스타트업

여기에 이미지 설명을 삽입하세요.

package com.angenin.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@EnableEurekaClient
@SpringBootApplication
public class PaymentHystrixMain8001 {
    
    

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

}

5) 업종

  • service : 일반적인 상황에서는 인터페이스와 인터페이스 구현 클래스를 작성해야 하며, 시간을 절약하기 위해 구현 클래스를 직접 작성합니다.
    여기에 이미지 설명을 삽입하세요.
package com.angenin.springcloud.service;

import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class PaymentService {
    
    

    //正常访问方法
    public String paymentInfo_OK(Integer id){
    
    
        //如果正常访问则,返回当前线程池的名字、传入的id、表情包
        return "线程池:  "+Thread.currentThread().getName()+"  paymentInfo_OK,id:  "+id+"\t"+"O(∩_∩)O哈哈~";
    }


    //超时访问方法
    public String paymentInfo_TimeOut(Integer id){
    
    
        //前面学过时会导致服务降级,模拟错误
        int timeNumber = 3;
        try {
    
    
            TimeUnit.SECONDS.sleep(timeNumber);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        //超时返回的提示信息
        return "线程池:" + Thread.currentThread().getName() +
                "paymentInfo_TimeOut,id:" +id+"\t"+"O(∩_∩)O哈哈~"+"  耗时(秒):"+timeNumber;
    }

}

  • 제어 장치
    여기에 이미지 설명을 삽입하세요.
package com.angenin.springcloud.controller;

import com.angenin.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@Slf4j
@RestController
public class PaymentController {
    
    

    @Resource
    PaymentService paymentService;

    @Value("${server.port}")    //spring的@Value注解
    private String ServerPort;

    //正常
    @GetMapping("/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id){
    
    
        String result = paymentService.paymentInfo_OK(id);
        log.info("******result:" + result);
        return result;
    }

    //超时
    @GetMapping("/payment/hystrix/timeout/{id}")
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id){
    
    
        String result = paymentService.paymentInfo_TimeOut(id);
        log.info("******result:" + result);
        return result;
    }

}

6) 일반시험

  • 유레카7001 시작

  • cloud-provider-hystrix-pay8001 시작

  • 액세스: 모든 사람이 결과에 올바르게 액세스하고 결과를 반환할 수 있습니다.

    • 성공방법 : http://localhost:8001/pay/hystrix/ok/4
      여기에 이미지 설명을 삽입하세요.
      여기에 이미지 설명을 삽입하세요.

    • 각 호출에는 3초가 소요됩니다: http://localhost:8001/pay/hystrix/timeout/4
      여기에 이미지 설명을 삽입하세요.
      여기에 이미지 설명을 삽입하세요.

  • 위 모듈은 모두 괜찮습니다. 위 모듈을 기본 플랫폼으로 사용하고 올바른 -> 오류 -> 회로 차단기 다운그레이드 -> 복구로 이동하세요.

10.3.2 높은 동시성 테스트

  • 위의 내용은 동시성이 높지 않은 상황에서는 여전히 요구 사항을 거의 충족할 수 없지만...

1) Jmeter 스트레스 테스트

  • Jmeter를 열면 20,000개의 동시 요청이 8001을 분쇄하고 20,000개의 요청이 모두 PaymentInfo_TimeOut 서비스에 액세스합니다.
    여기에 이미지 설명을 삽입하세요.
    여기에 이미지 설명을 삽입하세요.
    저장:
    여기에 이미지 설명을 삽입하세요.
    여기에 이미지 설명을 삽입하세요.
    http://localhost:8001/pay/hystrix/timeout/4
    여기에 이미지 설명을 삽입하세요.

  • 유레카7001 시작

  • cloud-provider-hystrix-pay8001 시작

  • 2가지 방법에 각각 접속하여 시연 결과 확인(자체 테스트)

    • 성공방법 : http://localhost:8001/pay/hystrix/ok/4
    • 각 호출에는 3초가 소요됩니다: http://localhost:8001/pay/hystrix/timeout/4
  • 결과:

    • 둘 다 혼자서 원을 그리며 돌고 있어요
      • 접속에 성공한 메소드는 즉시 결과를 반환하고, 접속한 메소드는 결과를 반환하는데 3초가 소요되는 것으로 나타났습니다. (스레드 수가 적고 스레드가 2개에 불과합니다.)
      • 이제: 두 방법 모두 원형으로 회전하며 이는 성공적인 방법도 속도가 느려졌음을 나타냅니다(많은 스레드, 20,000 + 2 스레드).
    • 왜 붙어 있습니까?
      • Tomcat의 기본 작업 스레드 수는 가득 찼으며 압력과 프로세스를 분해하기 위한 추가 스레드는 없습니다. (Springboot는 기본적으로 Tomact 컨테이너용 스레드 풀이 있는 Tomact를 통합합니다.)
      • 동일한 마이크로서비스에 접근하는 방법에는 두 가지가 있는데, 마이크로서비스는 동시성이 높은 요청을 처리하기 위해 리소스를 집중하는데, 과도한 압박으로 인해 리소스가 고갈되기 때문에 성공적인 접근 방법 역시 지연 및 지연 효과를 겪게 됩니다.

2) Jmeter 압력 테스트 결론

  • 위 내용은 여전히 ​​서비스인데 提供者8001自己测试, 이때 외부 소비자(80)도 방문하면 기다릴 消费者수 결국 소비자(80)는 불만족을 느끼고 서버(8001)는 직접 죽음에 이르게 된다.

3) 큰일을 폄하하지 않고 재미를 보다가 80명의 신입회원이 합류했습니다.

  • 새로운 cloud-consumer-feign-hystrix-order80 생성
    여기에 이미지 설명을 삽입하세요.

  • 포엠
    여기에 이미지 설명을 삽입하세요.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.angenin.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumer-feign-hystrix-order80</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!--openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!--eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
        <dependency>
            <groupId>com.angenin.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--一般基础通用配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>
  • YML
    여기에 이미지 설명을 삽입하세요.
server:
  port: 80

eureka:
  client:
    register-with-eureka: false
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

  • 메인 부팅
    여기에 이미지 설명을 삽입하세요.
package com.angenin.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients  //激活feifn
public class OrderHystrixMain80
{
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(OrderHystrixMain80.class,args);
    }
}

  • 비즈니스 클래스(PaymentHystrixService, OrderHystirxController)
    여기에 이미지 설명을 삽입하세요.
package com.angenin.springcloud.service;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@Component
//调用的微服务名
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT" )
public interface PaymentHystrixService
{
    
    
    @GetMapping("/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id);

    @GetMapping("/payment/hystrix/timeout/{id}")
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id);
}

-----------------------------------------------------------

package com.angenin.springcloud.controller;


import com.angenin.springcloud.service.PaymentHystrixService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
@Slf4j
public class OrderHystirxController {
    
    
    @Resource
    private PaymentHystrixService paymentHystrixService;

    //调用ok方法
    @GetMapping("/consumer/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id) {
    
    
        String result = paymentHystrixService.paymentInfo_OK(id);
        return result;
    }

    //调用超时方法
    @GetMapping("/consumer/payment/hystrix/timeout/{id}")
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
    
    
        String result = paymentHystrixService.paymentInfo_TimeOut(id);
        return result;
    }
}



  • 일반 테스트

    • 7001, 8001, 80 시작
      여기에 이미지 설명을 삽입하세요.

    • 확인 방문: http://localhost/consumer/pay/hystrix/ok/4 (속도도 매우 빠릅니다)
      여기에 이미지 설명을 삽입하세요.

  • 높은 동시성 테스트

    • 2W 스레드 프레스 8001
    • 그런 다음 소비자 측 80 마이크로서비스는 일반 Ok 마이크로서비스 8001 주소에 액세스합니다.
    • http://localhost/consumer/결제/hystrix/ok/32
    • 효과:
      • 또는 원을 그리며 기다리면 결과가 반환되는 데 시간이 걸립니다.
      • 또는 소비자가 시간 초과 오류를 보고합니다.
        여기에 이미지 설명을 삽입하세요.

10.3.3 고장 현상 및 원인

  • 8001 Tomcat 스레드 풀의 작업 스레드가 이미 사용되었기 때문에 동일한 수준의 다른 인터페이스 서비스가 트랩되었습니다.
  • 80은 이때 8001을 호출하고 클라이언트 액세스 응답이 느리고 원을 그리며 회전합니다.

10.3.4 항소의 결론

  • 우리의 다운그레이드/내결함성/전류 제한 및 기타 기술이 탄생한 것은 바로 위의 실패 또는 성능 저하 때문입니다.

10.3.5 어떻게 해결하나요? 해결된 요구사항

  • 시간 초과로 인해 서버 속도가 느려짐(원 모양으로 회전): 시간 초과 후 더 이상 기다리지 않습니다.
  • 오류(다운타임 또는 프로그램 작동 오류): 오류에 대한 명확한 이해를 확인하십시오.
  • 해결책 :
    • 상대방의 서비스(8001) 시간이 초과되었습니다. 발신자(80)가 계속 대기 상태에 있을 수는 없습니다. 서비스가 다운그레이드되어야 합니다.
    • 상대방 서비스(8001)가 다운되었습니다. 발신자(80)가 영원히 대기할 수는 없습니다. 서비스 다운그레이드가 있어야 합니다.
    • 상대방 서비스(8001)는 정상인데, 발신자(80)가 실패하거나 자체적인 요구사항(자신의 대기시간이 서비스 제공자보다 짧음)이 있어서 스스로 다운그레이드를 처리한다.

10.3.6 서비스 저하

1) 다운그레이드 구성

  • @HystrixCommand
  • 요즘은 코딩 대신 실용적인 구성을 기본으로 사용하고 있습니다.

2) 8001은 먼저 자체 내부의 문제를 찾습니다.

  • Call Timeout의 Peak 값을 직접 설정하여 Peak 값 내에서 정상적인 동작이 가능하며, Peak 값을 초과하는 경우 이를 처리하고 서비스 저하 Fallback을 수행할 수 있는 백업 방법이 필요합니다.

3) 8001폴백

Producer 다운그레이드: 타임아웃 방식의 기본 피크 값은 3초인데, 이제 5초 동안 Sleep 상태이므로 다운그레이드가 필요하고 은폐 방식을 수행하게 됩니다.

  • 비즈니스 클래스 활성화됨
    • @HystrixCommand에서 보고된 예외를 처리하는 방법
    • 서비스 메서드 호출이 실패하고 오류 메시지가 발생하면 @HystrixCommand 표시 fallbackMethod 호출 클래스에 지정된 메서드가 자동으로 호출됩니다.
      여기에 이미지 설명을 삽입하세요.
      여기에 이미지 설명을 삽입하세요.
package com.angenin.springcloud.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class PaymentService {
    
    

    //正常访问方法
    public String paymentInfo_OK(Integer id){
    
    
        //如果正常访问则,返回当前线程池的名字、传入的id、表情包
        return "线程池:  "+Thread.currentThread().getName()+"  paymentInfo_OK,id:  "+id+"\t"+"O(∩_∩)O哈哈~";
    }



    /**
     * @HystrixCommand:启用
     * 超时访问方法
     * fallbackMethod:此方法出现问题了,执行哪个兜底的方法
     * HystrixProperty:此方法线程的超时时间为3秒钟,我们现在睡眠5秒说明超时了,就走兜底的方法
     */
    @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = {
    
    
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="3000")
    })
    public String paymentInfo_TimeOut(Integer id){
    
    
        //前面学过时会导致服务降级,模拟错误
        int timeNumber = 5;
        //int age = 10/0; //程序出现异常,同样会走兜底的方法
        try {
    
    
            TimeUnit.SECONDS.sleep(timeNumber);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        //超时返回的提示信息
        return "线程池:" + Thread.currentThread().getName() +
                "paymentInfo_TimeOut,id:" +id+"\t"+"O(∩_∩)O哈哈~"+"  耗时(秒):"+timeNumber;
    }

    // 兜底方法
    public String paymentInfo_TimeOutHandler(Integer id){
    
     // 回调函数向调用方返回一个符合预期的、可处理的备选响应
        return "线程池:  "+Thread.currentThread().getName()+"  8001系统繁忙或者运行报错,请稍后再试,id:  "+id+"\t"+"o(╥﹏╥)o";
    }


}


  • 메인 스타트업 클래스 활성화
    여기에 이미지 설명을 삽입하세요.
package com.angenin.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@EnableEurekaClient
@SpringBootApplication
@EnableCircuitBreaker //激活
public class PaymentHystrixMain8001 {
    
    

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

}

  • 자체 테스트: 7001, 8001 시작
    여기에 이미지 설명을 삽입하세요.

  • http://localhost:8001/결제/hystrix/timeout/1
    여기에 이미지 설명을 삽입하세요.

4) 80폴백

소비자 다운그레이드: 생산자의 최대 시간 제한은 5초이고 3초 동안 휴면 상태였습니다. 이제 소비자 호출은 1.5초가 필요하고 3초를 기다릴 수 없으므로 서비스 다운그레이드는 은폐 방법을 호출합니다.

  • 80개 주문 마이크로서비스는 스스로를 더 잘 보호할 수 있으며 동일한 예를 따라 클라이언트 다운그레이드를 보호할 수도 있습니다.
  • 여담이지만, 우리가 구성한 핫 배포 방법에는 Java 코드가 명백히 변경되었지만 @HystrixCommand내부 .
  • YML
    여기에 이미지 설명을 삽입하세요.
feign:
  hystrix:
    enabled: true
  • 메인 부팅
    여기에 이미지 설명을 삽입하세요.
package com.angenin.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients  //激活feifn
@EnableHystrix //激活
public class OrderHystrixMain80
{
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(OrderHystrixMain80.class,args);
    }
}

  • 비즈니스 클래스
    여기에 이미지 설명을 삽입하세요.
package com.angenin.springcloud.controller;


import com.angenin.springcloud.service.PaymentHystrixService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
@Slf4j
public class OrderHystirxController {
    
    
    @Resource
    private PaymentHystrixService paymentHystrixService;

    //调用ok方法
    @GetMapping("/consumer/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id) {
    
    
        String result = paymentHystrixService.paymentInfo_OK(id);
        return result;
    }

    //调用超时方法
    @GetMapping("/consumer/payment/hystrix/timeout/{id}")
    @HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod",commandProperties = {
    
    
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1500")
    })
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
    
    
	    int age = 10/0; //测试出现异常同样要执行兜底的方法
        String result = paymentHystrixService.paymentInfo_TimeOut(id);
        return result;
    }

    public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id) {
    
    

        return "我是消费者80,对方支付系统繁忙请10秒钟后再试或者自己运行出错请检查自己,o(╥﹏╥)o";
    }
}


  • Producer 측을 정상으로 수정: Producer 측의 Peak 값이 5초이고 3초간 Sleep 상태인데, 이때 Consumer 측의 Peak 값이 1.5초이고 3초 동안 기다릴 수 없으므로 백업 방법 실행됩니다.
    여기에 이미지 설명을 삽입하세요.

  • 테스트: 7001, 8001, 80 시작
    여기에 이미지 설명을 삽입하세요.

  • http://localhost/consumer/결제/hystrix/timeout/1
    여기에 이미지 설명을 삽입하세요.

5) 현안

  • 문제 1: 각각의 비즈니스 메소드가 은밀한 메소드에 해당하고, 코드가 부풀어 오른다.

  • 문제 2: 비즈니스 로직 방법과 은밀한 방법이 혼합되어 있으며 코드의 결합도가 매우 높습니다.

  • 솔루션: 통합 및 맞춤형 분리

    • 비즈니스 메소드는 100가지가 있는데 그 중 97개의 일반 메소드는 전역 구성을 사용하고, 3개의 특수 메소드만 사용자 정의(3개의 ​​비밀 메소드 작성)되어 대체 서비스 저하 메소드 생성을 줄일 수 있습니다.

6) 문제 해결 시연

문제 1 해결: 각 방법에 대해 하나씩 구성하시겠습니까? ? ? 확장

  • 페이그 인터페이스 시리즈

  • @DefaultProperties(defaultFallback = “”)

    • 1:1 방식별로 서비스 다운그레이드 방식을 구성하는데, 기술적으로는 가능하지만 실제로는 말도 안 되는 일이다.
    • 1:N 배타적인 일부 중요한 핵심 업무를 제외하고, 다른 공통 업무는 @DefaultProperties(defaultFallback = “”)를 통해 통일 처리 결과 페이지로 균일하게 점프할 수 있습니다.
    • 通用的和独享的各自分开,避免了代码膨胀,合理减少了代码量,O(∩_∩)O哈哈~
      여기에 이미지 설명을 삽입하세요.
  • 컨트롤러 구성
    여기에 이미지 설명을 삽입하세요.
    여기에 이미지 설명을 삽입하세요.

package com.angenin.springcloud.controller;


import com.angenin.springcloud.service.PaymentHystrixService;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
@Slf4j
/**
 * 没有配置过定制的@HystrixCommand(fallbackMethod)方法就走这个全局定义的@DefaultProperties(defaultFallback)方法,
 * 如果配置了就走自定义的@HystrixCommand(fallbackMethod)兜底方法。
 */
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
public class OrderHystirxController {
    
    
    @Resource
    private PaymentHystrixService paymentHystrixService;

    //调用ok方法
    @GetMapping("/consumer/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id) {
    
    
        String result = paymentHystrixService.paymentInfo_OK(id);
        return result;
    }

    //调用超时方法
    @GetMapping("/consumer/payment/hystrix/timeout/{id}")
    /*@HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod",commandProperties = {
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1500")
    })*/
    /**
     * 注意:需要注释的是这个@HystrixCommand注解中的属性而不是整个注解
     *   注释掉注解:代表不使用服务降级,正确就正确,错误就错误
     *   使用@HystrixProperty注解:不指定fallbackMethod属性表示使用全局的,指定代表使用定制的。
     */
    @HystrixCommand
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
    
    
        int age = 10/0; //测试出现异常同样要执行兜底的方法
        String result = paymentHystrixService.paymentInfo_TimeOut(id);
        return result;
    }

    public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id) {
    
    

        return "我是消费者80,对方支付系统繁忙请10秒钟后再试或者自己运行出错请检查自己,o(╥﹏╥)o";
    }

    //下面是全局fallback兜底方法
    public String payment_Global_FallbackMethod() {
    
    
        return "Global异常处理信息,请稍后再试,/(ㄒoㄒ)/~~";
    }
}


  • 다시 시작: 7001, 8001, 80 테스트
    여기에 이미지 설명을 삽입하세요.
  • 효과:http://localhost/consumer/payment/hystrix/timeout/1
    여기에 이미지 설명을 삽입하세요.

문제 2 해결: 비즈니스 로직과 혼합하시겠습니까? ? ? 착란

  • 아이디어: 소비자가 Feign을 사용하여 통화하는 한 서비스 인터페이스가 있어야 하며 이 인터페이스의 모든 메소드를 통일된 방식으로 정의하고 예약하여 디커플링 목적을 달성할 수 있습니다.
  • 서비스 저하, 클라이언트가 서버를 호출하고 서버가 다운되거나 종료됨(시간 초과 및 런타임 예외는 이전에 테스트됨)
  • 이 경우의 서비스 저하 처리는 在客户端80实现完成的서버(8001)와는 아무런 관련이 없습니다. Feign 클라이언트가 정의한 인터페이스에 서비스 저하 처리를 위한 구현 클래스를 추가하기만 하면 디커플링이 이루어집니다.
  • 미래에 우리가 직면하게 될 이상 현상
    • 달리다
    • 타임아웃
    • 중단 시간
  • 비즈니스 클래스 PaymentController를 다시 살펴보겠습니다.
    여기에 이미지 설명을 삽입하세요.
  • cloud-consumer-feign-hystrix-order80 수정
  • cloud-consumer-feign-hystrix-order80의 기존 PaymentHystrixService 인터페이스에 따라 새로운 클래스(PaymentFallbackService)를 생성하여 인터페이스를 구현하고, 예외 처리를 위해 인터페이스의 메소드를 통합합니다.
  • PaymentFallbackService 클래스는 PaymentFeignClientService 인터페이스를 구현합니다.
    여기에 이미지 설명을 삽입하세요.
package com.angenin.springcloud.service;


import org.springframework.stereotype.Component;

@Component
public class PaymentFallbackService implements PaymentHystrixService{
    
    
    @Override
    public String paymentInfo_OK(Integer id) {
    
    
        return "-----PaymentFallbackService fall back-paymentInfo_OK ,o(╥﹏╥)o";
    }

    @Override
    public String paymentInfo_TimeOut(Integer id) {
    
    
        return "-----PaymentFallbackService fall back-paymentInfo_TimeOut ,o(╥﹏╥)o";
    }
}

  • YML(이전에 이미 설정됨)
    여기에 이미지 설명을 삽입하세요.
  • PaymentFeignClientService 인터페이스
    여기에 이미지 설명을 삽입하세요.
package com.angenin.springcloud.service;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@Component
/**
 * value:调用的微服务名
 * 过程:fallback:相当于去找CLOUD-PROVIDER-HYSTRIX-PAYMENT这个微服务的名字,去调用下面已有的方法,
 *      假如出事了去调用PaymentFallbackService里面的方法
 */
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT",fallback = PaymentFallbackService.class )
public interface PaymentHystrixService
{
    
    
    @GetMapping("/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id);

    @GetMapping("/payment/hystrix/timeout/{id}")
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id);
}

  • 시험
    • 단일 유레카는 7001부터 시작됩니다.
    • PaymentHystrixMain8001 시작, OrderHystrixMain80
    • 일반 액세스 테스트:http://localhost/consumer/payment/hystrix/ok/31
      여기에 이미지 설명을 삽입하세요.
    • 의도적으로 마이크로서비스를 종료합니다 8001
      여기에 이미지 설명을 삽입하세요.
    • 클라이언트가 프롬프트를 호출합니다. 이때 서버 공급자가 다운되었지만 서버를 사용할 수 없을 때 클라이언트가 서버를 끊지 않고 프롬프트 정보를 얻을 수 있도록 서비스 다운그레이드 처리를 수행했습니다.

10.3.7 서비스 회로 차단기

1) 이론

  • 차단기 : 한마디로 집의 퓨즈입니다.

  • 회로 차단기 메커니즘 개요

    • 회로 차단기 메커니즘은 눈사태 효과를 처리하기 위한 마이크로서비스 링크 보호 메커니즘입니다. 오류로 인해 팬아웃 링크의 마이크로서비스를 사용할 수 없거나 응답 시간이 너무 길면 서비스 성능이
      저하되어 노드의 마이크로서비스 호출이 중단되고 잘못된 응답 정보가 빠르게 반환됩니다.
    • 노드의 마이크로서비스 호출 응답이 정상인 것으로 감지되면 호출 링크가 복원됩니다.
    • Spring Cloud 프레임워크에서 서킷 브레이커 메커니즘은 Hystrix를 통해 구현됩니다. Hystrix는 마이크로서비스 간 호출 상태를 모니터링합니다.
      실패한 호출이 특정 임계값에 도달하면 기본값은 5초 내에 20번의 실패 호출이며 회로 차단기 메커니즘이 활성화됩니다. 회로 차단기 메커니즘의 주석은 여전히 ​​@HystrixCommand입니다.
    • 석사 논문: https://martinfowler.com/bliki/CircuitBreaker.html
      여기에 이미지 설명을 삽입하세요.

2) 실제 운용

修改클라우드 제공자-hystrix-결제8001

  • 결제서비스
    여기에 이미지 설명을 삽입하세요.
    //=========服务熔断

    /**
     * commandProperties中配置的4个注解的含义:
     * true使用断路器,假设在时间窗口期10秒钟内,10次请求有
     * 超过60%都是失败的,那么这个断路器将起作用。
     *
     */
    @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = {
    
    
            @HystrixProperty(name = "circuitBreaker.enabled",value = "true"), // 是否开启断路器
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"), // 请求次数
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), // 时间窗口期
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"), // 失败率达到多少后跳闸
    })
    public String paymentCircuitBreaker(@PathVariable("id") Integer id) {
    
    
       /* 业务逻辑:
        *  如果输入的id大于等于0,则输出流水号,如果输入的id是个负数抛出异常,
        *  那么根据上面注解配置的熔断机制执行降级的兜底方法paymentCircuitBreaker_fallback
        * */
        if(id<0){
    
    
            throw new RuntimeException("******id 不能负数");
        }
        /**
         * IdUtil.simpleUUID()类似于 UUID.randomUUID().toString().replaceAll("-", "")
         * 它来自于之前在父项目中引入的hutool依赖
         * hutool是个功能强大的JAVA工具包(中国人编写的),官网:https://hutool.cn/
         */
        String serialNumber = IdUtil.simpleUUID();
        return Thread.currentThread().getName()+"\t"+"调用成功,流水号: " + serialNumber;
    }

    //降级的兜底方法
    public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id) {
    
    
        return "id 不能负数,请稍后再试,/(ㄒoㄒ)/~~   id: " +id;
    }

  • 이러한 매개변수를 구성하는 이유는 공식 웹사이트를 확인하세요 .https://github.com/Netflix/Hystrix/wiki/How-it-Works#CircuitBreaker
    여기에 이미지 설명을 삽입하세요.
    여기에 이미지 설명을 삽입하세요.
  • 결제 컨트롤러
    여기에 이미지 설명을 삽입하세요.
    //=========服务熔断
    
    @GetMapping("/payment/circuit/{id}")
    public String paymentCircuitBreaker(@PathVariable("id") Integer id) {
    
    
        String result = paymentService.paymentCircuitBreaker(id);
        log.info("****result: "+result);
        return result;
    }

시험:

  • 버전: cloud-eureka-server7001, cloud-provider-hystrix-pay8001

  • 자체 테스트 클라우드 제공자-hystrix-결제8001

  • 원본: http://localhost:8001/pay/circuit/31
    여기에 이미지 설명을 삽입하세요.

  • 링크:http://localhost:8001/pay/circuit/-31
    여기에 이미지 설명을 삽입하세요.

  • 한 번 맞고 한 번 틀리는 시도

  • 주요 테스트: 많은 실수가 있었고 점차 수정되었으며 처음에는 조건이 충족되지 않았으며 올바른 액세스 주소조차 사용할 수 없음을 발견했습니다.

    • 설명: 음수 ID를 여러 번 입력하면 오류 페이지가 반환됩니다.(60%를 초과하면 차단기가 끊어지도록 설정되어 있습니다.) 이때 양수 ID를 입력하더라도 여전히 오류 페이지가 반환됩니다. ID를 여러 번 긍정하면 정확도가 높아지며 천천히 올바른 페이지로 복원됩니다.
    • 부정적인 ID를 여러 번 입력하면 오류 페이지가 표시됩니다.
      여기에 이미지 설명을 삽입하세요.
    • 이때, 양성 ID를 입력하더라도 여전히 오류 페이지가 반환됩니다.
      여기에 이미지 설명을 삽입하세요.
    • 긍정 ID를 여러 번 입력하면 정확도가 높아지고 오류율이 감소하며 올바른 페이지가 천천히 복원됩니다.
      여기에 이미지 설명을 삽입하세요.

3) 원칙(간단한 요약)

  • 하나님의 결론
    여기에 이미지 설명을 삽입하세요.

  • 퓨즈 유형

    • 퓨즈 열림
      • 요청은 더 이상 현재 서비스를 호출하지 않으며, 내부 시계는 일반적으로 MTTR(평균 고장 시간)로 설정되며, 개방 시간이 설정된 시계에 도달하면 반 퓨즈 상태로 들어갑니다.
    • 회로 차단기가 닫혔습니다.
      • 회로 차단기를 꺼도 서비스는 회로 차단되지 않습니다.
    • 퓨즈 반 열림
      • 일부 요청은 규칙에 따라 현재 서비스를 호출하며, 요청이 성공하고 규칙을 준수하면 현재 서비스가 정상으로 돌아온 것으로 간주되어 회로 차단기가 꺼집니다.
  • 공식 웹사이트 서킷 브레이커 흐름도
    여기에 이미지 설명을 삽입하세요.

    • 공식 웹사이트 단계
      여기에 이미지 설명을 삽입하세요.

    • 어떤 상황에서 회로 차단기가 작동하기 시작합니까?
      여기에 이미지 설명을 삽입하세요.
      여기에는 회로 차단기의 세 가지 중요한 매개변수가 포함됩니다 快照时间窗、请求总数阀值、错误百分比阀值.

      • 1): 스냅샷 시간 창: 회로 차단기를 열지 여부를 결정하려면 일부 요청 및 오류 데이터를 계산해야 하며 통계 시간 범위는 스냅샷 시간 창이며 기본값은 최근 10 초입니다 .
      • 2): 총 요청 수 임계값: 스냅샷 기간 내에서 총 요청 수 임계값을 충족해야 회로 차단기가 적용됩니다. 기본값은 20 입니다 . 이는 hystrix 명령이 10초 내에 20회 미만 호출되면 모든 요청이 시간 초과되거나 다른 이유로 실패하더라도 회로 차단기가 열리지 않음을 의미합니다.
      • 3): 오류 백분율 임계값: 총 요청 수가 스냅샷 시간 창 내 임계값을 초과하는 경우, 예를 들어 30개의 호출이 발생하고, 이 30개의 호출 중 15개의 시간 초과 예외가 발생하면, 즉 50%가 넘는 오류 백분율, 50% 임계값의 기본 설정에서 회로 차단기는 이때 열립니다.
    • 차단기를 열거나 닫는 조건

      • 특정 임계값이 충족되는 경우(기본값은 10초 이내에 요청 20개를 초과함)
      • 실패율이 일정 수준에 도달한 경우(기본적으로 10초 이내에 요청의 50% 이상이 실패함)
      • 위의 임계값에 도달하면 회로 차단기가 열립니다.
      • 활성화되면 모든 요청이 전달되지 않습니다.
      • 일정 시간(기본값은 5초)이 지나면 회로 차단기가 반쯤 열려 요청 중 하나가 전달됩니다. 성공하면 회로 차단기가 닫히고, 실패하면 열린 상태로 유지됩니다. 4와 5를 반복하세요.
    • 회로 차단기가 열린 후

      • 다른 요청이 호출되면 기본 로직은 호출되지 않지만 다운그레이드 폴백은 직접 호출됩니다. 서킷브레이커를 통해 자동으로 오류를 발견하고 다운그레이드 로직을 메인 로직으로 전환하여 응답지연을 줄여줍니다.
      • 원래의 메인 로직을 복원하는 방법은 무엇입니까?
        이 문제를 위해 hystrix에서는 자동 복구 기능도 구현했습니다.
        회로 차단기가 열리고 메인 로직이 끊어지면 hystrix는 슬립 시간 창을 시작합니다. 이 시간 창 동안 다운그레이드 로직은 일시적으로 메인 로직이 됩니다. 슬립 시간 창이 만료되면 회로 차단기는 절반의 로직으로 진입합니다. open 상태 원래의 메인 로직에 대한 요청을 해제합니다. 요청이 정상적으로 반환되면 회로 차단기는 계속해서 닫히고 메인 로직은 복원됩니다. 이 요청에 여전히 문제가 있으면 회로 차단기는 계속해서 닫힙니다. 열린 상태로 들어가면 수면 시간 창이 다시 설정됩니다.
    • 모든 구성: 다음과 같이

//========================All
@HystrixCommand(fallbackMethod = "str_fallbackMethod",
        groupKey = "strGroupCommand",
        commandKey = "strCommand",
        threadPoolKey = "strThreadPool",

        commandProperties = {
    
    
// 设置隔离策略,THREAD 表示线程池 SEMAPHORE:信号池隔离
@HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
// 当隔离策略选择信号池隔离的时候,用来设置信号池的大小(最大并发数)
@HystrixProperty(name = "execution.isolation.semaphore.maxConcurrentRequests", value = "10"),
// 配置命令执行的超时时间
@HystrixProperty(name = "execution.isolation.thread.timeoutinMilliseconds", value = "10"),
// 是否启用超时时间
@HystrixProperty(name = "execution.timeout.enabled", value = "true"),
// 执行超时的时候是否中断
@HystrixProperty(name = "execution.isolation.thread.interruptOnTimeout", value = "true"),
// 执行被取消的时候是否中断
@HystrixProperty(name = "execution.isolation.thread.interruptOnCancel", value = "true"),
// 允许回调方法执行的最大并发数
@HystrixProperty(name = "fallback.isolation.semaphore.maxConcurrentRequests", value = "10"),
// 服务降级是否启用,是否执行回调函数
@HystrixProperty(name = "fallback.enabled", value = "true"),
// 是否启用断路器
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
// 该属性用来设置在滚动时间窗中,断路器熔断的最小请求数。例如,默认该值为 20 的时候,
// 如果滚动时间窗(默认10秒)内仅收到了19个请求, 即使这19个请求都失败了,断路器也不会打开。
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20"),
// 该属性用来设置在滚动时间窗中,表示在滚动时间窗中,在请求数量超过
// circuitBreaker.requestVolumeThreshold 的情况下,如果错误请求数的百分比超过50,
                // 就把断路器设置为 "打开" 状态,否则就设置为 "关闭" 状态。
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
// 该属性用来设置当断路器打开之后的休眠时间窗。 休眠时间窗结束之后,
// 会将断路器置为 "半开" 状态,尝试熔断的请求命令,如果依然失败就将断路器继续设置为 "打开" 状态,
// 如果成功就设置为 "关闭" 状态。
@HystrixProperty(name = "circuitBreaker.sleepWindowinMilliseconds", value = "5000"),
// 断路器强制打开
@HystrixProperty(name = "circuitBreaker.forceOpen", value = "false"),
// 断路器强制关闭
@HystrixProperty(name = "circuitBreaker.forceClosed", value = "false"),
// 滚动时间窗设置,该时间用于断路器判断健康度时需要收集信息的持续时间
@HystrixProperty(name = "metrics.rollingStats.timeinMilliseconds", value = "10000"),
// 该属性用来设置滚动时间窗统计指标信息时划分"桶"的数量,断路器在收集指标信息的时候会根据
// 设置的时间窗长度拆分成多个 "桶" 来累计各度量值,每个"桶"记录了一段时间内的采集指标。
// 比如 10 秒内拆分成 10 个"桶"收集这样,所以 timeinMilliseconds 必须能被 numBuckets 整除。否则会抛异常
@HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "10"),
// 该属性用来设置对命令执行的延迟是否使用百分位数来跟踪和计算。如果设置为 false, 那么所有的概要统计都将返回 -1。
@HystrixProperty(name = "metrics.rollingPercentile.enabled", value = "false"),
// 该属性用来设置百分位统计的滚动窗口的持续时间,单位为毫秒。
@HystrixProperty(name = "metrics.rollingPercentile.timeInMilliseconds", value = "60000"),
// 该属性用来设置百分位统计滚动窗口中使用 “ 桶 ”的数量。
@HystrixProperty(name = "metrics.rollingPercentile.numBuckets", value = "60000"),
// 该属性用来设置在执行过程中每个 “桶” 中保留的最大执行次数。如果在滚动时间窗内发生超过该设定值的执行次数,
// 就从最初的位置开始重写。例如,将该值设置为100, 滚动窗口为10秒,若在10秒内一个 “桶 ”中发生了500次执行,
// 那么该 “桶” 中只保留 最后的100次执行的统计。另外,增加该值的大小将会增加内存量的消耗,并增加排序百分位数所需的计算时间。
@HystrixProperty(name = "metrics.rollingPercentile.bucketSize", value = "100"),
// 该属性用来设置采集影响断路器状态的健康快照(请求的成功、 错误百分比)的间隔等待时间。
@HystrixProperty(name = "metrics.healthSnapshot.intervalinMilliseconds", value = "500"),
// 是否开启请求缓存
@HystrixProperty(name = "requestCache.enabled", value = "true"),
// HystrixCommand的执行和事件是否打印日志到 HystrixRequestLog 中
@HystrixProperty(name = "requestLog.enabled", value = "true"),
        },
        threadPoolProperties = {
    
    
// 该参数用来设置执行命令线程池的核心线程数,该值也就是命令执行的最大并发量
@HystrixProperty(name = "coreSize", value = "10"),
// 该参数用来设置线程池的最大队列大小。当设置为 -1 时,线程池将使用 SynchronousQueue 实现的队列,
// 否则将使用 LinkedBlockingQueue 实现的队列。
@HystrixProperty(name = "maxQueueSize", value = "-1"),
// 该参数用来为队列设置拒绝阈值。 通过该参数, 即使队列没有达到最大值也能拒绝请求。
// 该参数主要是对 LinkedBlockingQueue 队列的补充,因为 LinkedBlockingQueue
                // 队列不能动态修改它的对象大小,而通过该属性就可以调整拒绝请求的队列大小了。
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "5"),
        }
)
public String strConsumer() {
    
    
return "hello 2020";
}
public String str_fallbackMethod()
{
    
    
return "*****fall back str_fallbackMethod";
}

10.3.8 서비스 전류 제한

  • 아래 고급 장에서는 Alibaba의 Sentinel 지침을 설명합니다.

10.4 히스트릭스 작업흐름

  • https://github.com/Netflix/Hystrix/wiki/How-it-Works
    여기에 이미지 설명을 삽입하세요.

  • Hystrix 작업 흐름

    • 공식 홈페이지 범례
      여기에 이미지 설명을 삽입하세요.

    • 단계 지침

      • 1) HystrixCommand(종속 서비스가 단일 연산 결과를 반환하는 경우 사용) 또는 HystrixObserableCommand(종속 서비스가 여러 연산 결과를 반환하는 경우 사용) 객체를 생성합니다.

      • 2) 명령 실행. 그 중 HystrixComand는 아래 처음 두 가지 실행 메소드를 구현하고, HystrixObservableCommand는 후자 두 가지 실행 메소드인 Execute()를 구현합니다: 동기 실행, 종속 서비스에서 단일 결과 객체를 반환하거나 오류 발생 시 예외를 발생시킵니다. queue(): 비동기 실행은 서비스 실행이 종료될 때 반환될 단일 결과 객체를 포함하는 Future 객체를 직접 반환합니다. observable(): 작업의 여러 결과를 나타내는 Observable 객체를 반환합니다.이것은 Hot Observable입니다("이벤트 소스"에 "구독자"가 있는지 여부에 관계없이 이벤트는 생성 후 게시되므로 각 Hot Observable A에 대해) "구독자"는 "이벤트 소스"의 중간에서 시작할 수 있으며 전체 작업의 일부만 볼 수 있습니다. toObservable(): 또한 작업의 여러 결과를 나타내는 Observable 개체를 반환하지만 Cold Observable을 반환합니다("구독자"가 없으면 이벤트를 게시하지 않지만 "구독자"가 있을 때까지 기다립니다." 이벤트는" 이후에만 게시되므로 Cold Observable 구독자에게는 전체 작업의 전체 프로세스를 처음부터 볼 수 있음을 보장할 수 있습니다.

      • 3) 현재 명령의 요청 캐싱 기능이 활성화되어 있고 명령 캐시에 적중되면 캐시된 결과가 Observable 객체 형태로 즉시 반환됩니다.

      • 4) 차단기가 열려 있는지 확인하세요. 회로 차단기가 열려 있으면 Hystrix는 명령을 실행하지 않고 대신 대체 처리 로직으로 전환합니다(8단계). 회로 차단기가 닫혀 있으면 명령을 실행할 수 있는 리소스가 있는지 확인합니다(5단계).

      • 5) 스레드 풀/요청 큐/세마포어가 가득 찼는지 여부. 명령이 서비스의 전용 스레드 풀과 요청 큐에 의존하거나 세마포어(스레드 풀이 사용되지 않는 경우)가 이미 가득 차면 Hystrix는 명령을 실행하지 않고 대체 처리 로직으로 전환합니다(단계 8) .

      • 6) Hystrix는 우리가 작성한 메소드를 기반으로 종속 서비스를 요청하는 방법을 결정합니다. HystrixCommand.run(): 단일 결과를 반환하거나 예외를 발생시킵니다. HystrixObservableCommand.construct(): Observable 객체를 반환하여 여러 결과를 내보내거나 onError를 통해 오류 알림을 보냅니다.

      • 7) Hystrix는 "성공", "실패", "거부", "시간 초과" 및 기타 정보를 회로 차단기에 보고하며 회로 차단기는 이러한 데이터를 계산하기 위해 일련의 카운터를 유지 관리합니다. 회로 차단기는 이러한 통계를 사용하여 종속 서비스에 대한 "단락/단락" 요청을 위해 회로 차단기를 열지 여부를 결정합니다.

      • 8) 명령 실행이 실패하면 Hystrix는 fallback에 들어가 프로세스 롤백을 시도하는데, 우리는 보통 이 작업을 "서비스 다운그레이드"라고 부릅니다. 다음 상황은 서비스 저하를 일으킬 수 있습니다. 4단계: 전류 명령이 "퓨즈/단락" 상태이고 회로 차단기가 열려 있습니다. 5단계: 현재 명령의 스레드 풀, 요청 큐 또는 세마포어가 가득 찬 경우. 6단계: HystrixObservableCommand.construct() 또는 HystrixCommand.run()이 예외를 발생시키는 경우.

      • 9) Hystrix 명령이 성공적으로 실행되면 처리 결과를 직접 반환하거나 Observable 형태로 반환합니다.

      • 팁: 명령에 대한 성능 저하 논리를 구현하지 않거나 성능 저하 처리 논리에서 예외가 발생하는 경우 Hystrix는 여전히 Observable 객체를 반환하지만 결과 데이터를 내보내지 않고 대신 명령에 즉시 중단하도록 알립니다. onError 메소드를 통해 요청하고, 명령 실패를 발생시킨 예외는 onError() 메소드를 통해 호출자에게 전달됩니다.

10.5 서비스 모니터링 hystrixDashboard

10.5.1 개요

  • 종속 서비스에 대한 호출을 격리하는 것 외에도 Hystrix는 准实时的调用监控(Hystrix Dashboard)Hystrix가 Hystrix를 통해 시작된 모든 요청의 실행 정보를 지속적으로 기록하고 이를 초당 실행되는 요청 수, 실행 방법 등을 포함하여 통계 보고서 및 그래픽 형식으로 사용자에게 표시할 것을 제공합니다. 성공 횟수, 실패 횟수 등 Netflix는 hystrix-metrics-event-stream 프로젝트를 통해 위 지표에 대한 모니터링을 구현합니다. Spring Cloud는 또한 Hystrix Dashboard와의 통합을 제공하여 모니터링 콘텐츠를 시각적 인터페이스로 변환합니다.
    • 즉, hystrix 대시보드 모니터링 인터페이스의 그래픽 표시입니다.

10.5.2 대시보드 9001

1) 새로운 cloud-consumer-hystrix-dashboard9001을 생성합니다.

여기에 이미지 설명을 삽입하세요.

2) 포엠

여기에 이미지 설명을 삽입하세요.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.angenin.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumer-hystrix-dashboard9001</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>


</project>

3) YML

여기에 이미지 설명을 삽입하세요.

server:
  port: 9001

4) 주요 창업강좌

여기에 이미지 설명을 삽입하세요.

package com.angenin.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

@SpringBootApplication
@EnableHystrixDashboard //启用Hystrix仪表盘
public class HystrixDashboardMain9001
{
    
    
    public static void main(String[] args)
    {
    
    
        SpringApplication.run(HystrixDashboardMain9001.class,args);
    }
}

5) 모든 생산자 pom 파일 보기

  • 모든 공급자 마이크로서비스 클래스(8001/8002/8003)는 종속성 구성을 모니터링해야 합니다.
    여기에 이미지 설명을 삽입하세요.

6) 테스트

  • cloud-consumer-hystrix-dashboard9001을 시작합니다. 이 마이크로서비스는 이후에 마이크로서비스 8001을 모니터링합니다.
  • http://localhost:9001/hystrix 이 인터페이스의 모양은 hystrixDashboard 모니터링 플랫폼이 구축되었음을 나타냅니다.
    여기에 이미지 설명을 삽입하세요.

10.5.3 회로 차단기 시연(서비스 모니터링 hystrixDashboard)

  • 데모: 8001 서비스 회로 차단기의 이전 사례를 예로 들어 9001이 8001을 모니터링하면 어떤 아이콘이 생성되는지 확인합니다.

  • 9001 모니터링 및 테스트 플랫폼을 직접 구축해야 하는데, Hystrix를 국내 Alibaba의 sentienl로 교체한 후 웹 사이트에 직접 로그인하여 모니터링할 수 있습니다.

1) cloud-provider-hystrix-pay8001 수정

지침:

  1. 모니터링되는 생산자 서비스는 일반적으로 그래픽 모니터링이 적용되도록 두 가지 종속성을 추가해야 합니다.
    여기에 이미지 설명을 삽입하세요.
  2. 새로운 버전의 Hystrix는 기본 시작 클래스 MainAppHystrix8001에서 모니터링 경로를 지정해야 합니다. 그렇지 않으면 Unable to connect to Command Metric Stream 404가 보고됩니다.
    여기에 이미지 설명을 삽입하세요.
package com.angenin.springcloud;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;

@EnableEurekaClient
@SpringBootApplication
@EnableCircuitBreaker //激活
public class PaymentHystrixMain8001 {
    
    

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

    /**
     *此配置是为了服务监控而配置,与服务容错本身无关,springcloud升级后的坑
     *ServletRegistrationBean因为springboot的默认路径不是"/hystrix.stream",
     *只要在自己的项目里配置上下面的servlet就可以了
     */
    @Bean
    public ServletRegistrationBean getServlet() {
    
    
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }

}

2) 모니터링 테스트

1개의 유레카 또는 3개의 유레카 클러스터를 시작할 수 있습니다.

  • 启动cloud-eureka-server7001,cloud-provider-hystrix-pay8001,cloud-consumer-hystrix-dashboard9001

모니터링 창 관찰

  • 9001 모니터링 8001

    • 모니터링 주소를 입력하세요: http://localhost:8001/hystrix.stream
      여기에 이미지 설명을 삽입하세요.
  • 테스트 주소(위의 8001 테스트 서비스 회로 차단기의 두 주소, 10.3.7 디렉터리)

    • http://localhost:8001/pay/circuit/31(올바른 페이지로 돌아가려면 양수 ID를 입력하세요.)
      여기에 이미지 설명을 삽입하세요.

    • http://localhost:8001/pay/circuit/-31 음수 ID를 입력하고 오류 페이지로 돌아갑니다.)
      여기에 이미지 설명을 삽입하세요.

    • 위의 테스트를 통과했습니다.

    • 좋아요

    • 먼저 올바른 주소를 방문하고, 그 다음 잘못된 주소를 방문하고, 그 다음 올바른 주소를 방문하면 사진의 차단기가 천천히 해제되는 것을 볼 수 있습니다.

      • 모니터링 결과, 성공
        여기에 이미지 설명을 삽입하세요.

      • 모니터링 결과, 실패
        여기에 이미지 설명을 삽입하세요.

  • 어떻게 볼 수 있나요?

    • 7색
      여기에 이미지 설명을 삽입하세요.

    • 1랩

      • 채워진 원: 두 가지 의미가 있습니다. 색상 변경을 통해 인스턴스의 상태를 나타내며, 상태는 녹색에서 녹색으로 변경되며, 색상 변경과 더불어 인스턴스의 요청 트래픽에 따라 크기도 변경됩니다. 단단한 원이 될 것입니다. . 따라서 실선 원의 표시를 통해 수많은 사례에서 빠르게 찾아보실 수 있습니다 故障实例和高压力实例.
        여기에 이미지 설명을 삽입하세요.
    • 1줄

      • 곡선: 2분 이내에 유량의 상대적 변화를 기록하는 데 사용되며 이를 통해 유량의 상승 및 하강 추세를 관찰할 수 있습니다.
        여기에 이미지 설명을 삽입하세요.
    • 전체 그림 설명
      여기에 이미지 설명을 삽입하세요.

    • 전체 사진 설명 2
      여기에 이미지 설명을 삽입하세요.

  • 하나를 이해해야만 복잡한 것도 이해할 수 있다
    여기에 이미지 설명을 삽입하세요.

11. zuul 라우팅 게이트웨이

  • Zuul은 구식이라 여기서는 설명하지 않겠습니다. 차세대 게이트웨이 Gateway로 직접 가보겠습니다. 회사의 오래된 프로젝트가 zuul 기술을 사용한다면 메모하고 두뇌 지도를 확인하세요.
    여기에 이미지 설명을 삽입하세요.

12. 게이트웨이 차세대 게이트웨이

12.1 개요 소개

  • 게이트웨이가 왜 필요한가요?
    여기에 이미지 설명을 삽입하세요.

  • 게이트웨이의 기술적 구현
    여기에 이미지 설명을 삽입하세요.

  • 공식 웹 사이트

    • 이전 세대 zuul 1.X: https://github.com/Netflix/zuul/wiki
      여기에 이미지 설명을 삽입하세요.

    • 当前gateway: https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/
      여기에 이미지 설명을 삽입하세요.

  • 무엇인가요
    여기에 이미지 설명을 삽입하세요.

    • 개요
      여기에 이미지 설명을 삽입하세요.

    • 한 문장으로:

      • SpringCloud Gateway에서 사용하는 Webflux의 Reactor-Netty 반응형 프로그래밍 구성요소는 하단의 Netty 통신 프레임워크를 사용합니다.
      • 소스 코드 아키텍처
        여기에 이미지 설명을 삽입하세요.
  • 당신은 무엇을 할 수 있나요

    • 역방향 프록시
    • 입증
    • 흐름 제어
    • 퓨즈
    • 로그 모니터링
  • 마이크로서비스 아키텍처에서 게이트웨이는 어디에 있나요?
    여기에 이미지 설명을 삽입하세요.

  • Zuul이 있었을 때 왜 관문이 다시 나왔습니까?

    • 게이트웨이를 선택한 이유는 무엇입니까?

      • neflix는 신뢰할 수 없으며 zuul2.0이 지연되어 출시되지 않았습니다.
        여기에 이미지 설명을 삽입하세요.

      • SpringCloud 게이트웨이에는 다음과 같은 기능이 있습니다.
        여기에 이미지 설명을 삽입하세요.

      • SpringCloud Gateway와 Zuul의 차이점
        여기에 이미지 설명을 삽입하세요.

    • Zuul1.x 모델
      여기에 이미지 설명을 삽입하세요.

    • GateWay 모델

      • WebFlux 란 무엇입니까?
        여기에 이미지 설명을 삽입하세요.

      • https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-new-framework
        여기에 이미지 설명을 삽입하세요.

      • 참고: struts2, springmvc 등과 같은 기존 웹 프레임워크는 모두 Servlet API 및 Servlet 컨테이너를 기반으로 실행됩니다. 하지만 在Servlet3.1之后有了异步非阻塞的支持. WebFlux는 대표적인 Non-Blocking 비동기 프레임워크로, 그 핵심은 Reactor 관련 API를 기반으로 구현되어 있습니다. 기존 웹 프레임워크와 비교하여 Netty, Undertow 및 Servlet3.1과 같은 컨테이너에서 실행될 수 있습니다. Non-Blocking + Functional 프로그래밍 (Spring5에서는 java8을 사용할 수 있어야 함) Spring WebFlux는 Spring 5.0에서 도입된 새로운 반응형 프레임워크로 Spring MVC와 달리 Servlet API에 의존할 필요가 없으며 완전히 비동기식이며 Non-Blocking입니다. , 리액티브 스트리밍 사양을 구현하기 위해 Reactor를 기반으로 합니다.

12.2 세 가지 핵심 개념

  • 노선

    • 라우팅은 게이트웨이 구축을 위한 기본 모듈로, ID, 대상 URI, 일련의 Assertion 및 필터로 구성되며, Assertion이 true이면 해당 경로가 일치됩니다.
  • Predicate(단언)

    • 참조는 Java8의 java.util.function입니다.Predicate
      개발자는 HTTP 요청(예: 요청 헤더 또는 요청 매개변수)의 모든 항목을 일치시킬 수 있습니다.如果请求与断言相匹配则进行路由
  • 필터

    • Spring 프레임워크의 GatewayFilter 인스턴스를 의미하며, 필터를 사용하여 요청이 라우팅되기 전이나 후에 요청을 수정할 수 있습니다.
  • 전반적인:
    여기에 이미지 설명을 삽입하세요.

    • 웹 요청은 일부 일치 조건을 통해 실제 서비스 노드를 찾습니다. 그리고 이 전달 프로세스 전후에 몇 가지 개선된 제어를 수행합니다.
      술어는 일치 조건입니다.
    • 그리고 필터는 전능한 인터셉터로 이해될 수 있습니다. 이 두 요소와 대상 URI를 사용하면 특정 경로를 구현할 수 있습니다.

12.3 게이트웨이 워크플로우

  • 공식 홈페이지 요약
    여기에 이미지 설명을 삽입하세요.

  • 핵심 논리:路由转发+执行过滤器链

12.4 시작하기 구성

12.4.1 Gateway9527 설정

1) 새 모듈 생성

  • 클라우드 게이트웨이-gateway9527
    여기에 이미지 설명을 삽입하세요.

2) 포엠

여기에 이미지 설명을 삽입하세요.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.angenin.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-gateway-gateway9527</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!--gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
        <dependency>
            <groupId>com.angenin.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--一般基础配置类-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

3) YML

  • 마이크로서비스로서 Gateway 게이트웨이도 서비스센터에 등록이 필요합니다. zk와 같은 모든 등록 센터를 사용할 수 있습니다.
    여기에 이미지 설명을 삽입하세요.
server:
  port: 9527

spring:
  application:
    name: cloud-gateway

eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka  #以单机版为例,不然集群启动太慢

4) 업종 없음

  • 관문에는 비즈니스 클래스가 없으며 앞에서 문을 감시하는 사람입니다.

5) 주요 창업강좌

여기에 이미지 설명을 삽입하세요.

package com.angenin.springcloud;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

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

6) 9527 게이트웨이는 어떻게 라우팅 매핑을 합니까? ? ?

  • cloud-provider-pay8001을 예로 들어 보겠습니다.

  • cloud-provider-pay8001컨트롤러의 액세스 주소를 확인하세요

    • get 메소드: 쿼리 함수 테스트
      여기에 이미지 설명을 삽입하세요.

    • lib: 사용자 정의 로드 밸런싱 규칙 테스트
      여기에 이미지 설명을 삽입하세요.

  • 우리는 현재 포트 8001을 노출시키고 싶지 않고 8001 외부에 9527 레이어를 넣기를 희망합니다. 이는 더 안전하고 다른 사람이 8001을 직접 공격하는 것을 방지합니다. 이를 차단하는 게이트웨이 레이어가 있습니다.

7) YML의 새로운 게이트웨이 구성

여기에 이미지 설명을 삽입하세요.

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  #网关配置:
  cloud:
    gateway:
      routes:  #routes表示可以路由多个,可以为某个controller里面的所有rest接口都可以做路由
        #第一个路由
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001          #匹配后提供服务的路由地址    写死的
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

        #第二个路由
        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001          #匹配后提供服务的路由地址    写死的
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由


eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka  #以单机版为例,不然集群启动太慢

8) 테스트

  • 启动cloud-eureka-server7001,cloud-provider-pay8001,cloud-gateway-gateway9527

  • jar 패키지 도입 시 작은 버그입니다. 게이트웨이 게이트웨이는 웹 관련 종속성을 도입할 필요가 없습니다. 시작 시 도입되면 오류가 보고됩니다.
    여기에 이미지 설명을 삽입하세요.

  • 액세스 지침
    여기에 이미지 설명을 삽입하세요.

    • 게이트웨이를 추가하기 전: http://localhost:8001/pay/get/4
      여기에 이미지 설명을 삽입하세요.

    • 게이트웨이(http://localhost:9527/결제/get/4)를 추가하면 올바르게 액세스할 수도 있습니다.
      여기에 이미지 설명을 삽입하세요.

9) 게이트웨이에서 라우팅을 구성하는 두 가지 방법'

방법 1: 구성 파일 yml에서 구성, 이전 단계 참조

방법 2: 코드에 RouteLocator Bean 삽입

  • 공식 웹사이트 사례: https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#spring-cloud-circuitbreaker-filter-factory
    여기에 이미지 설명을 삽입하세요.

여기에 이미지 설명을 삽입하세요.

  • Baidu의 국내 뉴스 웹사이트에는 외부 네트워크가 필요합니다: http://news.baidu.com/guonei (이 웹사이트는 더 이상 존재하지 않는 것 같습니다)
    여기에 이미지 설명을 삽입하세요.

  • 직접 써보세요

    • 바이두 뉴스

    • 비즈니스 요구 사항: 9527 게이트웨이를 통해 외부 네트워크에서 Baidu News 웹 사이트에 액세스

    • 코딩

      • 클라우드 게이트웨이-gateway9527
      • 비즈니스 구현, 구성 및 구성 클래스 내용은 아래에 자세히 설명되어 있습니다.
        여기에 이미지 설명을 삽입하세요.
    • 시험:

      • 프로젝트 9527 다시 시작
      • http://localhost:9527/guonei, 동일한 뉴스 페이지를 반환합니다.
        여기에 이미지 설명을 삽입하세요.

구성 내용:

package com.angenin.springcloud.config;


import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class GateWayConfig {
    
    
    /**
     * 配置了一个id为route-name的路由规则,
     * 当访问地址 http://localhost:9527/guonei时会自动转发到地址:http://news.baidu.com/guonei
     * @param
     * @return
     */
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder)
    {
    
    
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();

        routes.route("path_route_atguigu",
                r -> r.path("/guonei")
                        .uri("http://news.baidu.com/guonei")).build();

        return routes.build();
    }
}

12.5 마이크로서비스 이름을 통한 동적 라우팅 구현

  • 현재 문제점: 주소가 하드코딩되어 있고, 서비스 제공자가 여러 개 있을 수 있어 로드 밸런싱이 필요합니다.
    여기에 이미지 설명을 삽입하세요.

  • 건축학
    여기에 이미지 설명을 삽입하세요.

  • 기본적으로 게이트웨이는 등록 센터에 등록된 서비스 목록과 등록 센터의 마이크로서비스 이름 경로를 기반으로 생성됩니다.动态路由进行转发,从而实现动态路由的功能

  • 시작: eureka7001 1개(cloud-eureka-server7001) + 서비스 제공업체 8001/8002 2개(cloud-provider-pay8001, cloud-provider-pay8002)

  • POM: 이 종속성은 이전에 추가되었으며 서비스가 등록 센터에 등록되었습니다.
    여기에 이미지 설명을 삽입하세요.

  • YML

    • uri의 프로토콜은 lb이며 이는 게이트웨이의 로드 밸런싱 기능이 활성화되었음을 의미합니다.
    • lb://serviceName은 마이크로서비스의 Spring Cloud Gateway가 자동으로 생성한 로드 밸런싱 URI입니다.
      여기에 이미지 설명을 삽입하세요.
server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  #网关配置:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:  #routes表示可以路由多个,可以为某个controller里面的所有rest接口都可以做路由
        #第一个路由
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址    写死的
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址(8001 8002集群组成的微服务名称)    替换为动态的
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

        #第二个路由
        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址    写死的
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址    替换为动态的
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由


eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka  #以单机版为例,不然集群启动太慢

  • 시험
    • 시작 시 9527
    • http://localhost:9527/결제/lb
    • 8001/8002 2포트 스위칭
      여기에 이미지 설명을 삽입하세요.
      여기에 이미지 설명을 삽입하세요.

12.6 술어의 사용

12.6.1이란 무엇입니까?

  • Gateway9527을 시작하세요
    여기에 이미지 설명을 삽입하세요.
  • 즉, 조건자 아래에 여러 일치 규칙이 있습니다.
    여기에 이미지 설명을 삽입하세요.

12.6.2 경로 예측 팩토리란 무엇입니까?

  • https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gateway-request-predicates-factories
    여기에 이미지 설명을 삽입하세요.

  • Spring Cloud Gateway는 Spring WebFlux HandlerMapping 인프라의 일부로 경로 일치를 구현합니다. Spring Cloud Gateway에는 다수의 내장 Route Predicate 팩토리가 포함되어 있습니다. 이러한 모든 조건자는 HTTP 요청의 다양한 속성과 일치합니다. 여러 Route Predicate 팩토리를 결합할 수 있습니다.

  • Spring Cloud Gateway는 Route 객체를 생성할 때 RoutePredicateFactory를 사용하여 Predicate 객체를 생성하고, Predicate 객체를 Route에 할당할 수 있다. Spring Cloud Gateway에는 내장된 Route Predicate Factory가 많이 포함되어 있습니다.

  • 이러한 모든 조건자는 HTTP 요청의 다양한 속성과 일치합니다. 다양한 조건자 팩토리를 결합하고 논리적 and를 통해 전달할 수 있습니다.

12.6.3 일반적으로 사용되는 경로 술어

여기에 이미지 설명을 삽입하세요.

  1. 경로 술어 이후
  2. 경로 술어 이전
  3. 경로 술어 사이
  4. 쿠키 경로 술어
  5. 헤더 경로 술어
  6. 호스트 경로 조건자
  7. 메소드 경로 술어
  8. 경로 경로 술어
  9. 쿼리 경로 조건자

12.6.4 일반적으로 사용되는 Route Predicate 시연

1) 경로 술어 후

공식 웹사이트 사례:
여기에 이미지 설명을 삽입하세요.

spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - After=2017-01-20T17:42:47.789-07:00[America/Denver]

질문: 이 구성 줄을 직접 복사할 수 있지만 원하는 시간 형식과 해당 시간대를 어떻게 작성합니까? ? ?

직접 테스트해보세요:

  • 테스트 클래스 : After 뒤에 쓰여진 날짜 및 시간 형식과 시간대를 얻는 것이 목적입니다.
    여기에 이미지 설명을 삽입하세요.

import java.time.ZonedDateTime;

public class T2 {
    
    
    public static void main(String[] args) {
    
    

        //获取默认时区的当前时间
        ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区
        //2023-08-27T19:32:02.975+08:00[Asia/Shanghai]
        System.out.println(zbj);

        // 用指定时区获取当前时间(美国/纽约)
        //ZonedDateTime zny = ZonedDateTime.now(ZoneId.of("America/New_York"));
        //System.out.println(zny);
    }
}



  • yml: 그런 다음 이 시간 형식을 yml 구성 파일에 복사합니다. 즉, lb 주소는 지정된 시간까지 적용되지 않습니다. 두 조건이 조합되어 사용됩니다.
    여기에 이미지 설명을 삽입하세요.
server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  #网关配置:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:  #routes表示可以路由多个,可以为某个controller里面的所有rest接口都可以做路由
        #第一个路由
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址    写死的
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址(8001 8002集群组成的微服务名称)    替换为动态的
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

        #第二个路由
        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址    写死的
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址    替换为动态的
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由
            - After=2023-08-27T19:32:02.975+08:00[Asia/Shanghai] #这个匹配的请求要在指定的时间之后,路由地址lb才生效(亚洲/上海)


eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka  #以单机版为例,不然集群启动太慢


  • 시험:
    • 현재 시간이 설정되어 있다면 테스트 중 현재 시간이 지나야 적용되므로 9527을 재시작하고 성공적으로 접속하면 8001/8002 두 포트가 전환됩니다.
      여기에 이미지 설명을 삽입하세요.
      http://localhost:9527/결제/lb
      여기에 이미지 설명을 삽입하세요.
      여기에 이미지 설명을 삽입하세요.
    • 이 시간을 아직 도착하지 않은 시간으로 수정합니다. 예를 들어 현재 시간은 2023.8 27.19:52이고 2023.8 27.20:52로 변경하면 이 시간에는 시간이 아직 도착하지 않았으므로 적용되지 않으며 액세스할 수 있습니다. 오류 http://localhost:9527/결제/
      여기에 이미지 설명을 삽입하세요.
      lb
      여기에 이미지 설명을 삽입하세요.

2) 경로 술어 전

  • 사용법은 1) Route Predicate 이후와 동일합니다.
  • 술어 아래에 2개의 항목이 적혀 있는데, 이는 지정된 시간까지 lb 주소가 적용되지 않고 조합되어 사용된다는 의미입니다.
    여기에 이미지 설명을 삽입하세요.
# 在指定的时间之前生效
- Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,路径相匹配的进行路由

3) 경로 술어 간

  • 사용법은 1) Route Predicate 이후와 동일합니다.
  • 2개 항목을 함께 사용함
    여기에 이미지 설명을 삽입하세요.
# 在指定的2个时间内生效
- Between=2020-02-02T17:45:06.206+08:00[Asia/Shanghai],2020-03-25T18:59:06.206+08:00[Asia/Shanghai]

4) 쿠키 경로 술어

  • 공식 웹사이트 사례:
    여기에 이미지 설명을 삽입하세요.
    쿠키 경로 조건자에는 두 개의 매개변수가 필요합니다. 하나는 쿠키 이름이고 다른 하나는 정규식입니다.
    해당 쿠키 이름 값과 정규 표현식을 얻어 라우팅 규칙을 매칭하고, 일치하는 경우 라우팅을 실행하고, 일치하지 않는 경우 라우팅을 실행하지 않습니다.
spring:
  cloud:
    gateway:
      routes:
      - id: cookie_route
        uri: https://example.org
        predicates:
        - Cookie=chocolate, ch.p

직접 테스트해보세요:

  • 요청을 받고 게시하는 방법을 시뮬레이션하시겠습니까? ? ?
    • jmeter 도구
    • 우편 배달부 도구(그래픽 도구)
    • 컬 명령(기본 그래픽 도구에서 사용되는 명령)
  • 이 경우 컬 명령은 마이크로서비스를 디버깅하는 데 사용됩니다.
  • yml 파일: 지정된 시간 이후에 쿠키 형식이 충족되는 경우에만 lb 경로가 적용될 수 있음을 나타냅니다.
    여기에 이미지 설명을 삽입하세요.
        #第二个路由
        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址    写死的
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址    替换为动态的
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由
            - After=2023-08-27T19:32:02.975+08:00[Asia/Shanghai] #这个匹配的请求要在指定的时间之后,路由地址lb才生效(亚洲/上海)
            #- Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]   #在指定时间之前生效
            #- Between=2020-02-02T17:45:06.206+08:00[Asia/Shanghai],2020-03-25T18:59:06.206+08:00[Asia/Shanghai] #在指定的2个时间之内生效
            - Cookie=username,zzyy #满足cookie名和正则表达式格式

  • 쿠키 없이 액세스하려면 get 요청을 보내세요.curl http://localhost:9527/payment/lb

    • 현재로서는 쿠키가 만족되지 않아 적용되지 않습니다.
      여기에 이미지 설명을 삽입하세요.
  • 쿠키로 방문:curl http://localhost:9527/payment/lb --cookie "username=zzyy"

    • 지정된 시간이 지나면 쿠키 형식이 충족되므로 lb 경로가 적용되고 효과 8001과 8002가 교대로 나타납니다.
      여기에 이미지 설명을 삽입하세요.
    • 컬을 추가하면 중국어 문자가 깨져서 반환되는 경우 이 주소의 블로그에서 해결 방법을 확인하세요.
      https://blog.csdn.net/leedee/article/details/82685636
      여기에 이미지 설명을 삽입하세요.

5) 헤더 경로 술어

  • 공식 홈페이지 사례
    여기에 이미지 설명을 삽입하세요.
    두 개의 매개변수: 하나는 속성 이름과 정규 표현식이며, 속성 값이 정규 표현식과 일치하면 실행됩니다.
spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: https://example.org
        predicates:
        - Header=X-Request-Id, \d+

직접 테스트해보세요

  • yml 파일: lb는 요청 헤더의 일치 규칙이 충족되는 경우에만 적용됩니다(주석 처리된 항목과 주석 처리되지 않은 항목을 명확하게 확인하세요).
    여기에 이미지 설명을 삽입하세요.
        #第二个路由
        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址    写死的
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址    替换为动态的
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由
            #- After=2023-08-27T19:32:02.975+08:00[Asia/Shanghai] #这个匹配的请求要在指定的时间之后,路由地址lb才生效(亚洲/上海)
            #- Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]   #在指定时间之前生效
            #- Between=2020-02-02T17:45:06.206+08:00[Asia/Shanghai],2020-03-25T18:59:06.206+08:00[Asia/Shanghai] #在指定的2个时间之内生效
            #- Cookie=username,zzyy  #满足cookie名和正则表达式格式
            - Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数的正则表达式

  • 컬 테스트:curl http://localhost:9527/payment/lb -H "X-Request-Id:123"
    여기에 이미지 설명을 삽입하세요.

6) 호스트 경로 조건자

  • 공식 웹사이트 문서인
    여기에 이미지 설명을 삽입하세요.
    Host Route Predicate는 일련의 매개변수와 일치하는 도메인 이름 목록을 받습니다. 이 템플릿은 구분 기호로 .를 사용하는 개미로 구분된 템플릿입니다.
    매개변수의 호스트 주소를 일치 규칙으로 사용합니다.

시험

  • yml
    여기에 이미지 설명을 삽입하세요.
- Host=**.atguigu.com #根据主机地址进行匹配

  • 명령을 입력하다
    • 正确:curl http://localhost:9527/pay/lb -H “호스트: www.atguigu.com”
    • 错误:curl http://localhost:9527/pay/lb -H “호스트: java.atguigu.net”

여기에 이미지 설명을 삽입하세요.

7) 메소드 경로 술어

  • 공식 문서
    여기에 이미지 설명을 삽입하세요.

직접 테스트해보세요:

  • yml
    여기에 이미지 설명을 삽입하세요.
- Method=GET   #根据请求方式进行匹配
  • 주소 입력: 아무것도 쓰지 않고 요청만 받으세요
    여기에 이미지 설명을 삽입하세요.

8) 경로 경로 술어

  • 공식 문서
    여기에 이미지 설명을 삽입하세요.

시험

  • 이전 경로 매칭이며, 자세한 내용은 12.4 시작하기 구성----7), 8)을 참조하세요.
    여기에 이미지 설명을 삽입하세요.

9) 쿼리 경로 술어

  • 공식 문서
    여기에 이미지 설명을 삽입하세요.

직접 테스트해보세요

  • yml
    여기에 이미지 설명을 삽입하세요.
- Query=username, \d+  # 要有参数名username并且值还要是整数才能路由
  • 원본:http://localhost:9527/pay/lb?username=31
  • 错误:http://localhost:9527/pay/lb?username=-31

10) 요약

  • 총 yml
    여기에 이미지 설명을 삽입하세요.
server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  #网关配置:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:  #routes表示可以路由多个,可以为某个controller里面的所有rest接口都可以做路由
        #第一个路由
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址    写死的
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址(8001 8002集群组成的微服务名称)    替换为动态的
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

        #第二个路由
        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址    写死的
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址    替换为动态的
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由
            #- After=2023-08-27T19:32:02.975+08:00[Asia/Shanghai] #这个匹配的请求要在指定的时间之后,路由地址lb才生效(亚洲/上海)
            #- Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]   #在指定时间之前生效
            #- Between=2020-02-02T17:45:06.206+08:00[Asia/Shanghai],2020-03-25T18:59:06.206+08:00[Asia/Shanghai] #在指定的2个时间之内生效
            #- Cookie=username,zzyy  #满足cookie名和正则表达式格式
            #- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数的正则表达式
            #- Host=**.atguigu.com
            #- Method=GET   #根据请求方式进行匹配
            - Query=username, \d+  # 要有参数名username并且值还要是整数才能路由



eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka  #以单机版为例,不然集群启动太慢

  • 직설적으로 말하면 Predicate는 요청이 처리할 해당 경로를 찾을 수 있도록 일련의 일치 규칙을 구현하는 것입니다.

12.7 필터의 사용

  • GatewayFilter는 게이트웨이에 제공되는 필터로, 게이트웨이에 들어오는 요청과 마이크로서비스에서 반환된 응답을 처리할 수 있습니다.
    여기에 이미지 설명을 삽입하세요.

12.7.1이란 무엇입니까?

여기에 이미지 설명을 삽입하세요.

라우팅 필터는 들어오는 HTTP 요청과 반환된 HTTP 응답을 수정하는 데 사용할 수 있습니다. 라우팅 필터는 사용할 경로만 지정할 수 있습니다.

Spring Cloud Gateway에는 다양한 내장 라우팅 필터가 있으며, 이는 모두 GatewayFilter의 팩토리 클래스에 의해 생성됩니다.

12.7.2 Spring Cloud Gateway의 필터

수명주기, 단 2개

  • pre: 비즈니스 로직 이전
  • 게시물: 비즈니스 로직 이후

유형, 단 2개:

  • GatewayFilter: 단일
    여기에 이미지 설명을 삽입하세요.

  • 글로벌필터: 글로벌
    여기에 이미지 설명을 삽입하세요.

  • 자세한 내용은 공식 웹사이트를 확인하세요: https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gatewayfilter-factories
    여기에 이미지 설명을 삽입하세요.

12.7.3 일반적으로 사용되는 GatewayFilter(단일 필터)

  • YML
    여기에 이미지 설명을 삽입하세요.
          filters:
            - AddRequestParameter=X-Request-Id,1024 #过滤器工厂会在匹配的请求头加上一对请求头,名称为X-Request-Id值为1024
  • 나머지 내용은 공식 홈페이지에서 확인하세요

12.7.4 전역 GlobalFilter 사용자 정의(전역 필터)

1) 두 가지 주요 인터페이스 소개

  • implements GlobalFilter,Ordered

2) 당신은 무엇을 할 수 있나요?

  • 글로벌 로깅
  • 통합 게이트웨이 인증

3) 케이스 코드

여기에 이미지 설명을 삽입하세요.

package com.angenin.springcloud.filter;


import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Date;

@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
    
    

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
    
        log.info("**************come in MyLogGateWayFilter:" + new Date());
        //获取request中的uname参数
        String uname = exchange.getRequest().getQueryParams().getFirst("uname");

        if(uname == null){
    
    
            log.info("*******用户名为null,非法用户!!");
            //设置 response 状态码   因为在请求之前过滤的,so就算是返回NOT_FOUND 也不会返回错误页面
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            //完成请求调用
            return exchange.getResponse().setComplete();
        }

        //过滤链放行
        return chain.filter(exchange);

    }

    @Override
    public int getOrder() {
    
    
        //返回值是过滤器的优先级,越小优先级越高(最小-2147483648,最大2147483648)
        return 0;
    }
}


4) 테스트

  • 시작하다
    여기에 이미지 설명을 삽입하세요.

  • 정확함: http://localhost:9527/pay/lb?uname=z3 (8001 8002가 앞뒤로 전환됨)
    여기에 이미지 설명을 삽입하세요.

  • 실수

    • 매개변수 uname이 없습니다: http://localhost:9527/pay/lb, 전달은 정상적으로 사용할 수 없습니다.
      여기에 이미지 설명을 삽입하세요.
  • 9527 콘솔 로그
    여기에 이미지 설명을 삽입하세요.

13 SpringCloud Config 분산 구성 센터

13.1 개요

13.1.1 분산 시스템이 직면한 구성 문제

  • 마이크로서비스는 단일 애플리케이션의 비즈니스를 하위 서비스로 분할하는 것을 의미하며, 각 서비스의 세분성은 상대적으로 작기 때문에 시스템에 많은 수의 서비스가 있게 됩니다. 각 서비스를 실행하려면 필수 구성 정보가 필요하므로 중앙 집중식 동적 구성 관리 기능이 필수적입니다.

  • SpringCloud는 이 문제를 해결하기 위해 ConfigServer를 제공합니다.각 마이크로서비스에는 수백 개의 구성 파일을 관리하기 위한 자체 application.yml이 있습니다... / (
    ㄒoㄒ)/~~

13.1.2이란 무엇입니까?

  • 무엇인가요

    • SpringCloud Config는 마이크로서비스 아키텍처의 마이크로서비스에 대한 중앙 집중식 외부 구성 지원을 제공하며, 各个不同微服务应用모든 환경에 구성 서버가 제공 됩니다 中心化的外部配置.
  • 게임 방법

    • SpringCloud Config는 服务端和客户端两部分.
    • 分布式配置中心,它是一个独立的微服务应用서버 는 구성 서버에 연결하고 클라이언트가 구성 정보, 암호화/해독 정보 등을 얻을 수 있도록 액세스 인터페이스를 제공하는 데 사용되는 서버라고도 합니다.
    • 클라이언트는 지정된 컨피규레이션 센터를 통해 애플리케이션 리소스 및 비즈니스 관련 컨피규레이션 콘텐츠를 관리하고, 구동 시 컨피규레이션 센터로부터 컨피규레이션 정보를 얻어 로드하며, 컨피규레이션 서버는 기본적으로 git을 이용하여 컨피그레이션 정보를 저장하므로 환경 컨피규레이션의 버전 관리에 도움이 된다. , 구성 콘텐츠는 git 클라이언트 도구를 통해 쉽게 관리하고 액세스할 수 있습니다.
  • 예:

    • 문제: 세 개의 마이크로서비스 프로젝트의 yml 파일이 모두 동일한 데이터베이스에 연결되어 있으므로, 이때 포트 번호를 수정해야 한다면 세 개의 yml 파일을 모두 수정해야 합니다.
    • 해결 방법: 공개 구성을 구성 센터로 추출하고 자체 yml 파일에 비공개 구성을 작성하면 관리가 더 쉬워집니다.
    • 아래와 같이 운영 및 유지 관리 엔지니어가 GitHub에서 구성을 수정한 다음 로컬에서 동기화하고 공유 구성 센터에 로컬로 동기화한 다음 ABC가 함께 다운로드하도록 하여 운영 및 유지 관리 엔지니어가 구성을 수정할 수 있도록 합니다. 한 번만 게시하면 어디서나 게시할 수 있습니다.
      여기에 이미지 설명을 삽입하세요.

13.1.3 수행할 수 있는 작업

  • 구성 파일을 중앙에서 관리
  • 다양한 환경에 대한 다양한 구성, 동적 구성 업데이트, dev/test/prod/beta/release와 같은 환경별 배포
  • 운영 중에 구성을 동적으로 조정합니다. 각 서비스가 배포되는 시스템에 구성 파일을 작성할 필요가 없습니다. 서비스는 구성 센터에서 자체 구성 정보를 균일하게 가져옵니다.
  • 구성이 변경되면 구성 변경 사항을 감지하고 새 구성을 적용하기 위해 서비스를 다시 시작할 필요가 없습니다.
  • REST 인터페이스 형식으로 구성 정보를 노출합니다. 게시 및 컬 액세스와 새로 고침을 사용할 수 있습니다.

13.1.4 GitHub와 구성 통합

  • SpringCloud Config는 기본적으로 Git을 사용하여 구성 파일을 저장하므로(SVN 및 로컬 파일 지원 등 다른 방법도 있음) 가장 권장되는 방법은 Git이며 http/https 액세스를 사용합니다.

13.1.5 공식 홈페이지

  • https://cloud.spring.io/spring-cloud-static/spring-cloud-config/2.2.1.RELEASE/reference/html/
    여기에 이미지 설명을 삽입하세요.

13.2 구성 서버 구성 및 테스트

13.2.1 GitHub 환경 설정

  • 자신의 계정을 사용하여 GitHub에 springcloud-config라는 새 리포지토리 원격 웨어하우스를 만듭니다.
    여기에 이미지 설명을 삽입하세요.

  • 이전 단계에서 새로 생성된 Git 주소를 가져옵니다.https://github.com/123shuai-aa/springcloud-config.git
    여기에 이미지 설명을 삽입하세요.

  • 로컬 하드 디스크 디렉터리에 새로운 git 로컬 웨어하우스를 생성하고 원격 웨어하우스를 로컬로 복제합니다.

    • 로컬 창고 위치: E:\Git-bendiku\SpringCloud2020

    • 명령줄 터미널 열기
      여기에 이미지 설명을 삽입하세요.

    • 명령줄 터미널에 복제 명령을 입력합니다.git clone https://github.com/123shuai-aa/springcloud-config.git

      • 새로 생성된 원격 라이브러리에 콘텐츠가 없기 때문에 경고가 보고됩니다.
        여기에 이미지 설명을 삽입하세요.
    • 효과:
      여기에 이미지 설명을 삽입하세요.
      여기에 이미지 설명을 삽입하세요.

  • springcloud-config 디렉터리에 3개의 yml 구성 파일을 만듭니다. 저장 형식은 UTF-8이어야 합니다(기본값은 UTF-8입니다).

    • 개발 환경: config-dev.yml

    • 프로덕션 환경: config-pro.yml

    • 테스트 환경: config-test.yml
      여기에 이미지 설명을 삽입하세요.

  • 구성-dev.yml:

config:
  info: "master branch,springcloud-config/config-dev.yml version=1"
  • config-pro.yml:
config:
  info: "master branch,springcloud-config/config-prod.yml version=1"
  • 구성-테스트.yml:
config:
  info: "master branch,springcloud-config/config-test.yml version=1" 

  • 명령을 사용하여 다음 3개 파일을 원격 창고에 푸시합니다. (명령줄 터미널을 입력한 경우)
    • 로컬 라이브러리 상태 확인: git status, 3개의 yml 파일을 볼 수 있습니다.
      여기에 이미지 설명을 삽입하세요.

    • 준비 영역에 추가: git add 파일 이름

      • 자식 추가 config-dev.yml
      • 자식 추가 config-pro.yml
      • 자식 추가 config-test.yml
        여기에 이미지 설명을 삽입하세요.
    • 로컬 라이브러리 제출: git commit -m "Log information" 파일 이름(영어 기호 참고)

      • git commit -m "init yml" config-dev.yml
      • git commit -m "init yml" config-pro.yml
      • git commit -m "init yml" config-test.yml
      • 상태를 다시 확인해 보세요. 제출 후 제출할 파일이 없다고 나옵니다.
        여기에 이미지 설명을 삽입하세요.
    • 원격도서관 링크 주소가 너무 길어서 기억하기 어려워서 앞으로 코드를 push하고 pull하기 쉽도록 링크에 별칭을 주었습니다( 语法:git remote add 别名 远程库链接地址)

      • 현재 원격 주소 별칭을 모두 확인합니다: git remote -v
      • 기본 별칭은 Origin이므로 다른 별칭을 만들 필요가 없습니다.
        여기에 이미지 설명을 삽입하세요.
    • 로컬 라이브러리 분기를 원격 창고로 푸시합니다.

      • 구문: git push alias Branch (기본 브랜치 이름은 메인 브랜치: main)

      • git push 원본 메인
        여기에 이미지 설명을 삽입하세요.

      • 창이 나타나면 를 선택하세요 浏览器账号登录.
        여기에 이미지 설명을 삽입하세요.

      • GitHub 계정 비밀번호를 입력하세요
        여기에 이미지 설명을 삽입하세요.

      • 자격 증명 관리자에 추가
        여기에 이미지 설명을 삽입하세요.

      • 명령줄 효과:
        여기에 이미지 설명을 삽입하세요.

    • 브라우저의 git 페이지를 새로 고치고 기본 브랜치의 콘텐츠가 GitHub에서 생성된 원격 저장소로 푸시되었는지 확인하세요.
      여기에 이미지 설명을 삽입하세요.

13.2.2 구성 센터 모듈 Congig Server 생성


  • Cloud의 구성 센터 모듈 cloudConfig Center인 새 모듈 모듈 cloud-config-center-3344를 만듭니다 .
    여기에 이미지 설명을 삽입하세요.

1) 모듈 이름: cloud-config-center-3344

여기에 이미지 설명을 삽입하세요.

2) 포엠

여기에 이미지 설명을 삽입하세요.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.angenin.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-config-center-3344</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <!--config server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
        <!--eureka client(通过微服务名实现动态路由)-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>


</project>

3) YML

  • git, GitHub 환경의 비밀번호 계정 명령어와 아이디어와의 통합이 이루어졌다는 것을 전제로 합니다.
    여기에 이미지 설명을 삽입하세요.
server:
  port: 3344


spring:
  application:
    name: cloud-config-center #注册进Eureka服务器的微服务名
  cloud:
    config:
      server:
        git:
          uri: https://github.com/123shuai-aa/springcloud-config.git  #git的仓库地址
          search-paths:   #搜索目录
            - springcloud-config
      label: main   #读取的分支


eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka   #服务注册到的eureka地址


  • 해당 구성
    여기에 이미지 설명을 삽입하세요.

4) 주요 창업강좌

여기에 이미지 설명을 삽입하세요.

package com.angenin.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

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

5) windows: 호스트 파일 수정

  • Windows에서 호스트 파일을 수정하고 매핑을 추가합니다.
  • 127.0.0.1 구성-3344.com
    여기에 이미지 설명을 삽입하세요.

6) 테스트

  • Config 마이크로서비스를 통해 GitHub에서 구성 콘텐츠를 얻을 수 있는지 테스트합니다.
    • 마이크로서비스 7001, 3344 시작
    • http://config-3344.com:3344/main/config-dev.yml (GitHub의 구성 파일에 액세스할 수 있으며 SpringCloud Config를 사용하여 GitHub를 통해 구성 정보를 성공적으로 얻었습니다 )
      여기에 이미지 설명을 삽입하세요.
  • 이제 이 부분이 완료되었습니다.
    여기에 이미지 설명을 삽입하세요.

13.2.3 읽기 규칙 구성

공식 웹 사이트:https://cloud.spring.io/spring-cloud-static/spring-cloud-config/2.2.1.RELEASE/reference/html/#_quick_start

  • 즉, GitHub 웨어하우스의 구성 파일을 읽기 위해 브라우저에 입력할 수 있는 주소 형식은 무엇입니까? (5종)
    여기에 이미지 설명을 삽입하세요.

그 중 3가지를 설명하세요.

  • 첫 번째: /{label}/{application}-{profile}.yml (분기 이름 + 파일 이름, 파일 이름 사이에 공백 포함, 권장, 위에서 테스트한 작성 방법 사용)
    • 마스터 브랜치
      • http://config-3344.com:3344/main/config-dev.yml
      • http://config-3344.com:3344/main/config-test.yml
      • http://config-3344.com:3344/main/config-pro.yml
    • 개발 브랜치
      • http://config-3344.com:3344/dev/config-dev.yml
      • http://config-3344.com:3344/dev/config-test.yml
      • http://config-3344.com:3344/dev/config-pro.yml
  • 두 번째 유형: /{application}-{profile}.yml (파일 이름만 작성하고 파일 이름 사이에 공백이 있음)
    • http://config-3344.com:3344/config-dev.yml
    • http://config-3344.com:3344/config-test.yml
    • http://config-3344.com:3344/config-pro.yml
    • http://config-3344.com:3344/config-xxxx.yml (존재하지 않는 구성) 결과는 다음과 같습니다.{}
  • 세 번째 유형: /{application}/{profile}[/{label}] (첫 번째 유형의 반대 작업, 결과는 json 형식)
    • http://config-3344.com:3344/config/dev/main
      여기에 이미지 설명을 삽입하세요.

    • http://config-3344.com:3344/config/test/main

    • http://config-3344.com:3344/config/test/dev

용어 사전:

  • /{이름}-{프로필}.yml
  • /{라벨}-{이름}-{프로필}.yml
  • 라벨: 지점
  • 이름: 서비스 이름
  • 프로필: 환경(dev/test/prod)

13.3 구성 클라이언트 구성 및 테스트

13.3.1 새로운 cloud-config-client-3355 생성

여기에 이미지 설명을 삽입하세요.

13.3.2 POM

여기에 이미지 설명을 삽입하세요.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.angenin.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-config-client-3355</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <!--config server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <!--eureka client(通过微服务名实现动态路由)-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>


</project>

13.3.3 bootstrap.yml

  • 무엇인가요:

    • applicaiton.yml은 사용자 수준 리소스 구성 항목입니다.
    • bootstrap.yml은 시스템 수준입니다.优先级更加高
    • Application ContextSpring Cloud는 Spring 애플리케이션 의 상위 컨텍스트 로 "Bootstrap Context"를 생성합니다 . 초기화하는 동안 외부 소스Bootstrap Context 에서 구성 속성을 로드하고 구성을 구문 분석하는 일을 담당합니다 . 두 컨텍스트는 외부에서 얻은 컨텍스트를 공유합니다 .Environment
    • Bootstrap속성은 우선순위가 높으며 기본적으로 로컬 구성에 의해 재정의되지 않습니다. Bootstrap context규칙이 다르기 때문에 구성 과의 분리를 보장하기 위해 Application Contextbootstrap.yml파일이 추가되었습니다 .Bootstrap ContextApplication Context
    • bootstrap.yml이 application.yml보다 먼저 로드되기 때문에 클라이언트 모듈 아래의 application.yml 파일을 bootstrap.yml로 변경하는 것이 중요합니다. bootstrap.yml은 application.yml보다 우선순위가 높습니다.
    • 요약 : 클라이언트 A 서비스는 2개의 구성 파일을 가지고 있는데, 하나는 구성 센터 3344와의 통신을 위한 bootstrap.yml이고 다른 하나는 자체 사용을 위한 application.yml이라는 것을 알 수 있습니다. 이런 식으로 공개 파일을 읽습니다. 먼저 3344 구성 센터에서 자신만의 bootstrap.yml로 구성한 다음 자신만의 application.yml을 로드하면 가장 완벽한 클라이언트 파일이 됩니다.
      여기에 이미지 설명을 삽입하세요.
  • 콘텐츠:
    여기에 이미지 설명을 삽입하세요.

server:
  port: 3355

spring:
  application:
    name: config-client
  cloud:
    #Config客户端配置
    config:
      label: main #分支名称
      name: config #配置文件名称
      profile: dev #读取后缀名称   上述3个综合:master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/main/config-dev.yml
      uri: http://localhost:3344 #配置中心地址
      #过程:表示3355通过3344间接读取到配置的主分支下面的config-dev配置文件。

#服务注册到eureka地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka
  • 설명하다:
    여기에 이미지 설명을 삽입하세요.

13.3.4 메인 스타트업

여기에 이미지 설명을 삽입하세요.

package com.angenin.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

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

13.3.5 비즈니스 클래스

13.1.3에서 앞서 언급했듯이 수행할 수 있는 작업은 다음과 같습니다.

  • 분산 구성 센터는 REST 인터페이스 형식으로 구성 정보를 노출할 수 있습니다. 게시, 컬 액세스 및 새로 고침이 가능합니다.
  • 설명: 구성 정보가 노출되므로 3355는 REST 스타일을 통해 3344 구성 센터의 메시지 및 컨텐츠 구성을 읽을 수 있습니다.
    여기에 이미지 설명을 삽입하세요.
package com.angenin.springcloud.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ConfigClientController {
    
    

    @Value("${config.info}")
    private String configInfo;

    @GetMapping("/configInfo")
    public String getConfigInfo() {
    
    
        return configInfo;
    }
}
  • @Value("${config.info}")읽은 내용은 GitHub 구성 파일의 접두사입니다.
    여기에 이미지 설명을 삽입하세요.

13.3.6 테스트

  • 7001 서비스등록센터 시작

  • Config 구성 센터 3344 마이크로서비스 시작 및 자체 테스트

    • http://config-3344.com:3344/main/config-pro.yml
      여기에 이미지 설명을 삽입하세요.

    • http://config-3344.com:3344/main/config-dev.yml
      여기에 이미지 설명을 삽입하세요.

  • 액세스를 준비하려면 클라이언트로 3355를 시작하세요.

    • http://localhost:3355/configInfo
      여기에 이미지 설명을 삽입하세요.
  • 결론: GitHub를 통해 구성 정보를 얻기 위해 SpringCloud Config3344에 대한 클라이언트 3355 액세스를 성공적으로 구현했습니다.

13.3.7 문제는 언제든지 발생합니다. 분산 구성의 동적 새로 고침 문제

  • Linux 운영 및 유지 관리는 GitHub의 구성 파일 내용을 수정하여 조정합니다.

    • config-dev.yml 구성을 수정하고 변수 연령 또는 버전 번호를 추가하는 등 GitHub에 제출합니다.
      여기에 이미지 설명을 삽입하세요.
  • 3344 브라우저 페이지를 새로 고치고 ConfigServer 구성 센터가 즉시 응답했는지 확인하세요.
    여기에 이미지 설명을 삽입하세요.

  • 3355를 새로 고쳤는데 ConfigClient 클라이언트가 응답하지 않는 것으로 나타났습니다.
    여기에 이미지 설명을 삽입하세요.

  • 3355 다시 시작하거나 다시 로드하지 않으면 변경 사항이 없습니다.
    여기에 이미지 설명을 삽입하세요.

  • 운영 및 유지 관리가 구성 파일을 수정할 때마다 클라이언트를 다시 시작해야 할 정도로 어려운가요? ? 악몽

13.4 Config 클라이언트의 동적 새로 고침(수동)

  • 목적: 구성이 업데이트될 때마다 클라이언트 마이크로서비스를 다시 시작하지 마세요. 3355

13.4.1 동적 새로 고침-수정 3355 모듈

1) POM에 액추에이터 모니터링 도입

  • 위에 그래픽 모니터링 종속성이 추가되었으며, 의미 자체가 변경된 후 다른 사람이 모니터링할 수 있습니다.
    여기에 이미지 설명을 삽입하세요.
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

2) 모니터링 포트를 노출하도록 YML을 수정합니다.

여기에 이미지 설명을 삽입하세요.

server:
  port: 3355

spring:
  application:
    name: config-client
  cloud:
    #Config客户端配置
    config:
      label: main #分支名称
      name: config #配置文件名称
      profile: dev #读取后缀名称   上述3个综合:master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/main/config-dev.yml
      uri: http://localhost:3344 #配置中心地址
      #过程:表示3355通过3344间接读取到配置的主分支下面的config-dev配置文件。

#服务注册到eureka地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka


# 暴露监控端点
management:
  endpoints:
    web:
      exposure:
        include: "*"

3) @RefreshScope 비즈니스 클래스 컨트롤러 수정

여기에 이미지 설명을 삽입하세요.

package com.angenin.springcloud.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RefreshScope //实现刷新功能
public class ConfigClientController {
    
    

    @Value("${config.info}")
    private String configInfo;

    @GetMapping("/configInfo")
    public String getConfigInfo() {
    
    
        return configInfo;
    }
}

4) 테스트: 3355가 적용되지 않습니다.

  • 적용하려면 3355 구성을 다시 시작하세요.
  • GitHub 콘텐츠 버전을 3으로 다시 수정합니다.
    여기에 이미지 설명을 삽입하세요.
  • 자체 테스트 액세스 3344에서 내용이 변경되었음을 발견했습니다.---유효
    • http://config-3344.com:3344/main/config-dev.yml
      여기에 이미지 설명을 삽입하세요.
  • 3355를 방문하세요----구성이 수정되었지만 여전히 적용되지 않습니다.
    여기에 이미지 설명을 삽입하세요.

5) 문제 해결: 3355가 적용되지 않습니다.

  • 운영 및 유지 관리 담당자는 3355를 새로 고치려면 Post 요청을 보내야 합니다.

    • POST 요청이어야 합니다.
    • curl -X POST "http://localhost:3355/actuator/refresh"(명령줄 창)
      여기에 이미지 설명을 삽입하세요.
  • 3355를 다시 방문하세요. 현재 3355가 다시 시작되지 않았지만 버전 번호가 변경되어 구성이 적용되었음을 나타냅니다.

    • 이점: 서비스 재시작 방지
    • http://localhost:3355/configInfo
      여기에 이미지 설명을 삽입하세요.

13.4.2 다른 질문이 있으신가요?

  • 여러 개의 마이크로서비스 클라이언트(3355/3366/3377)가 있는 경우 각 마이크로서비스는 사후 요청을 수행하고 수동으로 새로 고쳐야 합니까?

    • 해결책: for 루프에 대해 배치 스크립트를 작성하십시오.
  • 알림을 한 번 방송하고 모든 곳에 적용할 수 있나요? 대규모 자동 새로고침을 하고 싶은데 방법을 찾아주세요

    • 질문 1: 100개의 머신의 경우 알림을 한 번만 브로드캐스팅하면 모두 적용되며 100개의 게시물 요청을 할 필요가 없습니다.
    • 질문 2: 100개의 머신이 있는데 그 중 98개는 적용해야 하고 나머지 2개는 적용하고 원래 버전을 유지할 필요가 없습니다. 이런 종류의 정확한 알림과 정확한 삭제입니다.
  • 솔루션: 위 일련의 문제에 대해 SpringCloud Bus 메시지 버스를 사용하면 일괄 알림 및 정확한 알림을 해결할 수 있습니다.

14 SpringCloud 버스 메시지 버스

14.1 개요

  • 이전 설명의 심화와 확장을 한 단어로

    • 분산 자동 새로 고침 구성 기능
    • Spring Cloud Bus는 Spring Cloud Config와 함께 사용하여 구성을 동적으로 새로 고칠 수 있습니다.
  • 무엇인가요

    • Spring Cloud Bus는 분산 시스템 노드를 경량 메시징 시스템과 연결하는 데 사용되는 프레임워크입니다.它整合了Java的事件处理机制和消息中间件的功能。
    • Spring Clud Bus는 두 개의 메시지 브로커(RabbitMQ 및 Kafka)를 지원합니다.
      여기에 이미지 설명을 삽입하세요.
  • 당신은 무엇을 할 수 있나요

    • Spring Cloud Bus는 상태 변경, 이벤트 푸시 등을 브로드캐스트하는 데 사용할 수 있는 분산 실행기와 마찬가지로 분산 시스템 간에 메시지를 관리하고 전파할 수 있으며 마이크로서비스 간의 통신 채널로도 사용할 수 있습니다.
      여기에 이미지 설명을 삽입하세요.
  • 왜 버스라고 부르나요?

    • 버스가 뭐예요?
      • 마이크로서비스 아키텍처가 있는 시스템에서는 일반적으로 轻量级的消息代理하나를 구축 共用的消息主题하고 시스템의 모든 마이크로서비스 인스턴스를 연결하는 데 사용됩니다. 왜냐하면 该主题中产生的消息会被所有实例监听和消费,所以称它为消息总线. 버스의 각 인스턴스는 주제에 연결된 다른 인스턴스에 알려야 하는 일부 메시지를 쉽게 브로드캐스트할 수 있습니다.
    • 근본적인
      • ConfigClient 인스턴스는 모두 MQ에서 동일한 주제를 수신합니다(기본값은 springCloudBus). 서비스가 데이터를 새로 고치면 동일한 주제를 수신하는 다른 서비스에 알림을 제공하고 자체 구성을 업데이트할 수 있도록 이 정보를 주제에 넣습니다.
    • 테마 등 명사의 의미를 이해하지 못하는 경우 다음을 확인하세요.
      • 杨哥B站ActiveMQ课程:https://www.bilibili.com/video/av55976700?from=search&seid=15010075915728605208

14.2 RabbitMQ 환경 구성

  • 본 강좌에서는 RabbitMQ를 Windows 환경에 설치하는데, 여기서는 Linux 환경에 RabbitMQ를 설치하는 경우를 예로 들어보겠습니다.
  • 설치 단계 보기: https://blog.csdn.net/aa35434/article/details/126634371
  • RabbitMQ 백엔드 관리 인터페이스에 로그인합니다.http://192.168.10.140:15672/
    • 사용자 이름: 관리자
    • 비밀번호: 123456
      여기에 이미지 설명을 삽입하세요.
  • 효과:
    여기에 이미지 설명을 삽입하세요.

14.3 SpringCloud Bus는 글로벌 브로드캐스트를 동적으로 새로 고칩니다.

  • 먼저 좋은 RabbitMQ 환경이 있어야 합니다.

14.3.1 3355를 템플릿으로 사용하여 또 다른 3366 만들기

  • 방송 효과를 시연하고 복잡성을 높인 다음 3355를 템플릿으로 사용하여 3366을 만듭니다.

1) 새로운 cloud-config-client-3366을 생성합니다.

여기에 이미지 설명을 삽입하세요.

1) 포엠

여기에 이미지 설명을 삽입하세요.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.angenin.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-config-client-3366</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <!--config server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <!--eureka client(通过微服务名实现动态路由)-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

2) YML

여기에 이미지 설명을 삽입하세요.

server:
  port: 3366

spring:
  application:
    name: config-client
  cloud:
    #Config客户端配置
    config:
      label: main #分支名称
      name: config #配置文件名称
      profile: dev #读取后缀名称   上述3个综合:master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/main/config-dev.yml
      uri: http://localhost:3344 #配置中心地址
      #过程:表示3366通过3344间接读取到配置的主分支下面的config-dev配置文件。

#服务注册到eureka地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka


# 暴露监控端点
management:
  endpoints:
    web:
      exposure:
        include: "*"

3) 메인 스타트업

여기에 이미지 설명을 삽입하세요.

package com.angenin.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

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

4) 컨트롤러

여기에 이미지 설명을 삽입하세요.

package com.angenin.springcloud.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RefreshScope
public class ConfigClientController {
    
    
    
    @Value("${server.port}")
    private String serverPort;

    @Value("${config.info}")
    private String configInfo;

    @GetMapping("/configInfo")
    public String configInfo() {
    
    
        
        return "serverPort: "+serverPort+"\t\n\n configInfo: "+configInfo;
    }

}

14.3.2 디자인적 사고와 기술 선택

  • 메시지 버스를 사용하여 클라이언트/버스/새로 고침을 트리거하고 모든 클라이언트의 구성을 새로 고칩니다.

    • 즉, 클라이언트 3355 중 하나를 트리거하고 3355가 3366에 알림을 브로드캐스트합니다.
      여기에 이미지 설명을 삽입하세요.
  • 메시지 버스를 사용하여 서버 ConfigServer의 /bus/refresh 엔드포인트를 트리거하고 모든 클라이언트의 구성을 새로 고칩니다.

    • 즉, 구성 센터 3344로 트리거하고 3344는 3355 및 3366으로 알림을 브로드캐스트합니다.
      여기에 이미지 설명을 삽입하세요.
  • 그림 2의 아키텍처가 분명히 더 적합합니다. 그림 1이 적합하지 않은 이유는 다음과 같습니다.

    • 마이크로서비스 자체는 비즈니스 모듈이고 구성 새로 고침을 담당해서는 안 되므로 마이크로서비스의 단일 책임을 위반합니다.
    • 마이크로서비스 각 노드의 패리티를 삭제합니다.
    • 특정 제한 사항이 있습니다. 예를 들어 마이크로서비스를 마이그레이션할 때 네트워크 주소가 자주 변경되는데, 이때 자동으로 새로 고치려면 추가 수정 사항을 추가하게 됩니다.

14.3.3 cloud-config-center-3344 수정

cloud-config-center-3344 구성 센터에 服务端메시지 버스 지원을 추가합니다 .

  • 포엠
    여기에 이미지 설명을 삽입하세요.
        <!-- 添加rabbitMQ的消息总线支持包 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
        <!--凡事要暴露监控刷新的操作,3344的pom文件一定要引入actuator依赖,之前已经添加过了-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
  • YML

여기에 이미지 설명을 삽입하세요.

server:
  port: 3344

spring:
  application:
    name: cloud-config-center #注册进Eureka服务器的微服务名
  cloud:
    config:
      server:
        git:
          uri: https://github.com/123shuai-aa/springcloud-config.git  #git的仓库地址
          search-paths:   #搜索目录
            - springcloud-config
      label: main   #读取的分支
  #rabbitmq相关配置
  rabbitmq:
    host: 192.168.10.140  #linux上的主机ip
    port: 5672       #15672是图形管理界面的端口,5672是client访问端口
    username: admin
    password: 123456

eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka   #服务注册到的eureka地址


#rabbitmq相关配置,暴露bus刷新配置的端点
#凡事要暴露监控刷新的操作,3344的pom文件一定要引入actuator依赖
management:
  endpoints: #暴露bus刷新配置的端点
    web:
      exposure:
        include: 'bus-refresh'

14.3.4 cloud-config-client-3355 수정

cloud-config-client-3355에 客户端메시지 버스 지원 추가

  • 포엠
    여기에 이미지 설명을 삽입하세요.
        <!-- 添加rabbitMQ的消息总线支持包 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
        <!--凡事要暴露监控刷新的操作,3344的pom文件一定要引入actuator依赖,之前已经添加过了-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
  • YML
    여기에 이미지 설명을 삽입하세요.
server:
  port: 3355

spring:
  application:
    name: config-client
  cloud:
    #Config客户端配置
    config:
      label: main #分支名称
      name: config #配置文件名称
      profile: dev #读取后缀名称   上述3个综合:master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/main/config-dev.yml
      uri: http://localhost:3344 #配置中心地址
      #过程:表示3355通过3344间接读取到配置的主分支下面的config-dev配置文件。
  #rabbitmq相关配置
  rabbitmq:
    host: 192.168.10.140  #linux上的主机ip
    port: 5672       #15672是图形管理界面的端口,5672是client访问端口
    username: admin
    password: 123456


#服务注册到eureka地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka


# 暴露监控端点
management:
  endpoints:
    web:
      exposure:
        include: "*"

14.3.5 cloud-config-client-3366 수정

cloud-config-client-3366에 客户端메시지 버스 지원 추가

  • 포엠
    여기에 이미지 설명을 삽입하세요.
        <!-- 添加rabbitMQ的消息总线支持包 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
        <!--凡事要暴露监控刷新的操作,3344的pom文件一定要引入actuator依赖,之前已经添加过了-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
  • YML
    여기에 이미지 설명을 삽입하세요.
server:
  port: 3366

spring:
  application:
    name: config-client
  cloud:
    #Config客户端配置
    config:
      label: main #分支名称
      name: config #配置文件名称
      profile: dev #读取后缀名称   上述3个综合:master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/main/config-dev.yml
      uri: http://localhost:3344 #配置中心地址
      #过程:表示3366通过3344间接读取到配置的主分支下面的config-dev配置文件。
  #rabbitmq相关配置
  rabbitmq:
    host: 192.168.10.140  #linux上的主机ip
    port: 5672       #15672是图形管理界面的端口,5672是client访问端口
    username: admin
    password: 123456

#服务注册到eureka地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka

# 暴露监控端点
management:
  endpoints:
    web:
      exposure:
        include: "*"

14.3.6 테스트

  • 시작 7001, 3344, 3355, 3366
    여기에 이미지 설명을 삽입하세요.

  • 운영 및 유지보수 엔지니어

    • 버전 번호를 높이려면 Github의 구성 파일을 수정하세요.
      여기에 이미지 설명을 삽입하세요.

    • POST 요청 보내기( 刷新的是3344配置中心)

      • 컬 -X POST “http://localhost:3344/actuator/bus-refresh”
        여기에 이미지 설명을 삽입하세요.

      • 한 번만 보내면 어디서나 효과적입니다.

  • 구성 센터

    • http://config-3344.com:3344/main/config-dev.yml
      여기에 이미지 설명을 삽입하세요.
  • 고객

    • http://localhost:3355/configInfo
      여기에 이미지 설명을 삽입하세요.

    • http://localhost:3366/configInfo
      여기에 이미지 설명을 삽입하세요.

    • 서비스를 다시 시작하지 않고 구성 정보를 다시 가져왔더니 새로 고쳐진 것을 확인했습니다.

  • 한 번 수정하면 알림이 전송되고 모든 곳에 적용됩니다.

  • RabbitMQ 백엔드 관리 인터페이스에 로그인합니다.

    • 이전에 논의된 개념:
      여기에 이미지 설명을 삽입하세요.
      여기에 이미지 설명을 삽입하세요.

14.4 SpringCloud Bus는 고정 소수점 알림을 동적으로 새로 고칩니다.

14.1 비즈니스 요구사항

  • 모든 사람에게 알리고 싶지 않고 특정 사항만 알리고 싶습니다.
    • 3355에게만 알림
    • 알림 없음 3366
  • 간단한 문장
    • 전체 인스턴스 대신 적용할 특정 인스턴스를 지정하세요.
    • 공식:http://localhost:配置中心的端口号/actuator/bus-refresh/{destination}
    • /bus/refresh 요청은 더 이상 특정 서비스 인스턴스로 전송되지 않고 구성 서버로 전송되며 대상 매개변수 클래스를 통해 구성을 업데이트해야 하는 서비스 또는 인스턴스를 지정합니다.

14.2 테스트 케이스

사례

  • 여기서는 포트 3355에서 실행되는 config-client를 예로 들어 보겠습니다.

    • 3355에게만 알림
    • 알림 없음 3366
  • GitHub 구성 파일 수정
    여기에 이미지 설명을 삽입하세요.

  • 새로 고치다:

    • curl -X POST "http://localhost:3344/actuator/bus-refresh/config-client:3355"
      여기에 이미지 설명을 삽입하세요.
      • 즉, 새로 고침 3344를 사용하여 지정된 서비스 3355에 알립니다.

      • 버스 새로 고침
        여기에 이미지 설명을 삽입하세요.

      • 구성 클라이언트:3355:
        여기에 이미지 설명을 삽입하세요.

  • 효과: 3344, 3355 새로고침됨, 3366 새로고침되지 않음. (다시 시작하지 않음)
    http://config-3344.com:3344/main/config-dev.yml
    여기에 이미지 설명을 삽입하세요.
    http://localhost:3355/configInfo
    여기에 이미지 설명을 삽입하세요.
    http://localhost:3366/configInfo
    여기에 이미지 설명을 삽입하세요.

14.3 요약

  • 알림 요약전체
    여기에 이미지 설명을 삽입하세요.

15 SpringCloud 스트림 메시지 드라이버

15.1 메시지 기반 개요

15.1.1 스트림이 도입된 이유

  • 장면:

    • 현재 시스템은 프런트 엔드----"java 백엔드----"빅 데이터 플랫폼의 세 부분으로 나눌 수 있습니다. 이제 Java 백엔드는 RabbitMQ를 사용하고 빅 데이터 플랫폼은 Kafka를 사용합니다. 이러한 방식으로 전환, 유지 관리 개발이 이루어지니 일어나기가 더 귀찮습니다.
      여기에 이미지 설명을 삽입하세요.
  • 목적:

    • 특정 MQ의 세부 사항에 더 이상 주의를 기울이지 않아도 되는 새로운 기술이 탄생했을까요? 다양한 MQ 간에 자동으로 전환하려면 적응 바인딩 방법만 사용하면 됩니다.---SpringCloudStream
  • 일반적으로 사용되는 메시지 미들웨어:

    • 액티브MQ
    • RabbitMQ
    • 로켓MQ
    • Kafka(빅데이터에 일반적으로 사용됨)

15.1.1이란 무엇입니까?

  • SpringCloudStream이란 무엇입니까?

    • Spring Cloud Stream의 공식 정의는 메시지 기반 마이크로서비스를 구축하기 위한 프레임워크입니다.
    • 애플리케이션은 입력 또는 출력을 통해 Spring Cloud Stream의 바인더 객체와 상호 작용합니다.
    • 바인딩은 구성을 통해 수행되며 Spring Cloud Stream의 바인더 개체는 메시지 미들웨어와 상호 작용합니다.
    • 따라서 메시지 기반 접근 방식을 편리하게 사용하려면 Spring Cloud Stream과 상호 작용하는 방법만 알아내면 됩니다.
    • Spring Integration을 사용하여 메시지 브로커 미들웨어를 연결하여 메시지 이벤트 구동을 달성합니다.
    • Spring Cloud Stream은 게시-구독, 소비자 그룹 및 파티션의 세 가지 핵심 개념을 참조하여 일부 공급업체의 메시지 미들웨어 제품에 대한 개인화되고 자동화된 구성 구현을 제공합니다.
  • 目前仅支持RabbitMQ、Kafka。

  • 한 문장으로 말하면 기본 메시지 미들웨어의 차이점을 보호하고, 전환 비용을 줄이고, 메시지 프로그래밍 모델을 통합하는 것입니다.

  • 공식 웹 사이트:

    • https://spring.io/projects/spring-cloud-stream#개요
      여기에 이미지 설명을 삽입하세요.

      • Spring Cloud Stream은 공유 메시징 시스템에 연결된 확장성이 뛰어난 이벤트 기반 마이크로서비스를 구축하기 위한 프레임워크입니다. 이 프레임워크는 게시/공유의 세 가지 핵심 개념을 포함하여 이미 확립되고 친숙한 Spring 관용구 및 모범 사례를 기반으로 구축된 유연한 프로그래밍 모델을 제공합니다. 지속성을 지원하는 구독, 소비자 그룹 및 메시지 파티셔닝
    • 공식 문서: https://cloud.spring.io/spring-cloud-static/spring-cloud-stream/3.0.1.RELEASE/reference/html/
      여기에 이미지 설명을 삽입하세요.

    • Spring Cloud Stream 중국어 사용 설명서

      • https://m.wang1314.com/doc/webapp/topic/20971999.html
        여기에 이미지 설명을 삽입하세요.

15.1.2 디자인적 사고

  • 표준 MQ
    여기에 이미지 설명을 삽입하세요.

    • 메시지: 정보 내용은 미디어를 통해 생산자/소비자 간에 消息전달됩니다.
    • 메시지 채널 MessageChannel: 메시지는 특정 경로를 거쳐야 합니다.通道
    • 메시지 채널의 메시지는 어떻게 소비되며, 전송 및 수신 처리는 누가 담당합니까?
      • MessageHandler 메시지 프로세서가 구독하는 메시지 채널 MessageChannel의 하위 인터페이스 SubscribableChannel
  • 클라우드 스트림을 사용하는 이유

    • 예를 들어 RabbitMQ와 Kafka를 사용하는데 이 두 메시지 미들웨어의 아키텍처 차이로 인해 RabbitMQ는 exchange가 있고 Kafka는 Topic과 Partitions 파티션이 있는데 이러한 미들웨어의 차이로 인해 실제 프로젝트 개발에 일정한 문제가 발생하곤 했습니다. 우리는 두 개의 메시지 큐 중 하나를 사용하고 후속 비즈니스 요구를 위해 다른 메시지 큐로 마이그레이션하려고 합니다. 이는 우리 시스템과 결합되어 있기 때문에 의심할 여지 없이 재앙이 될 것입니다. 이때 springcloud Stream은 분리 방법을 제공합니다 一大堆东西都要重新推倒重新做.
      여기에 이미지 설명을 삽입하세요.
    • 스트림이 근본적인 차이점을 통합할 수 있는 이유는 무엇입니까?
      • 바인더 개념이 없을 경우 SpringBoot 애플리케이션이 메시지 미들웨어와 직접 상호 작용할 때 각 메시지 미들웨어의 원래 의도가 다르기 때문에 구현 세부 사항이 상당히 다를 것입니다 应用程序与消息中间件细节之间的隔离。. 채널 채널이 애플리케이션에 노출되므로 애플리케이션은 더 이상 다양한 메시지 미들웨어 구현을 고려할 필요가 없습니다.
      • 通过定义绑定器Binder作为中间层,实现了应用程序与消息中间件细节之间的隔离。
        여기에 이미지 설명을 삽입하세요.
    • Binder
      • 바인더 개념이 없으면 SpringBoot 애플리케이션이 메시지 미들웨어와 직접 상호 작용해야 할 때 각 메시지 미들웨어의 원래 의도가 다르기 때문에 구현 세부 사항이 상당히 다를 것입니다.바인더를 중간 계층으로 정의함으로써, 완벽하게 구현되었습니다 应用程序与消息中间件细节之间的隔离. Stream의 메시지 미들웨어 추가 캡슐화는 코드 계층이 미들웨어를 인식하지 못하게 할 수 있으며 미들웨어를 동적으로 전환(rabbitmq에서 kafka로 전환)하여 마이크로서비스 개발을 고도로 분리시키고 서비스가 자체적으로 더 많은 주의를 기울일 수 있게 합니다.

      • 通过定义绑定器Binder作为中间层,实现了应用程序与消息中间件细节之间的隔离。

      • 바인더는 메시지 컨테이너의 생산자와 소비자를 바인딩하는 데 사용되는 바인딩을 생성할 수 있으며 INPUT과 OUTPUT의 두 가지 유형이 있으며 INPUT은 소비자에 해당하고 OUTPUT은 생산자에 해당합니다.여기에 이미지 설명을 삽입하세요.

      • INPUT은 소비자에 해당합니다.

      • OUTPUT은 생산자에 해당합니다.

  • Stream의 메시지 통신 방식은 게시-구독 모델을 따릅니다.

    • 주제 주제 방송
      • RabbitMQ는 Exchange 스위치입니다.
      • Kakfa에서는 주제입니다

15.1.3 Spring Cloud Stream 표준 프로세스 루틴

여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.

  • 접합재
    • 매우 편리한 연결 미들웨어, 차이점 차폐
  • 채널
    • 채널(Channel)은 큐(Queue)를 추상화한 것으로 메시지 통신 시스템에서 저장과 전달을 위한 매체이며 큐는 채널을 통해 구성된다.
  • 소스 및 싱크
    • 참조 객체는 Spring Cloud Stream 자체이고, Stream에서 메시지를 게시하는 것은 출력(생산자)이고, 메시지를 받는 것은 입력(소비자)이라고 간단히 이해하면 됩니다.

15.1.4 코딩 API 및 공통 주석

여기에 이미지 설명을 삽입하세요.

구성 설명하다
미들웨어 미들웨어는 현재 FRabbitMQ 및 Kafka만 지원합니다.
접합재 바인더는 애플리케이션과 메시지 미들웨어를 캡슐화한 것으로 현재 KafKa와 RabbitMQ의 바인더가 구현되어 있으며, 바인더를 통해 미들웨어를 쉽게 연결하고 메시지 유형을 동적으로 변경할 수 있다(Kafka의 주제와 RabbitMQ 교환) 이것들은 모두 구성 파일을 통해 달성할 수 있습니다.
@입력 주석은 수신된 메시지가 애플리케이션에 들어가는 입력 채널을 식별합니다.
@산출 주석은 게시된 메시지가 애플리케이션을 떠나는 출력 채널을 식별합니다.
@StreamListener 소비자 큐에서 메시지를 수신하는 데 사용되는 청취 큐
@EnableBinding 함께 바인딩되는 채널 채널과 교환을 나타냅니다.

15.2 사례 설명

  • RabbitMQ 환경은 괜찮습니다
  • 프로젝트에 세 개의 새로운 하위 모듈을 만듭니다.
    • cloud-stream-rabbitmq-provider8801, 생산자로 메시지를 보내기 위한 모듈
    • cloud-stream-rabbitmq-consumer8802(메시지 수신 모듈)
    • 메시지 수신 모듈인 cloud-stream-rabbitmq-consumer8803

15.3 메시지 기반 생산자

15.3.1 새 모듈: cloud-stream-rabbitmq-provider8801

여기에 이미지 설명을 삽입하세요.

15.3.2 POM

여기에 이미지 설명을 삽입하세요.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.angenin.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-stream-rabbitmq-provider8801</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <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-stream-rabbit</artifactId>
        </dependency>
        <!--基础配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

15.3.3 YML

  • 폭발적인 인기는 사용에 영향을 미치지 않습니다
    여기에 이미지 설명을 삽입하세요.
server:
  port: 8801

spring:
  application:
    name: cloud-stream-provider
  cloud:
    stream:
      binders: # 在此处配置要绑定的rabbitmq的服务信息;
        defaultRabbit: # 表示定义的名称,用于于binding整合
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
                host: 192.168.10.140
                port: 5672
                username: admin
                password: 123456
      bindings: # 服务的整合处理
        output: # 这个名字是一个通道的名称 生产者使用output,消费者使用input
          destination: studyExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为json,文本则设置“text/plain”
          binder: defaultRabbit # 设置要绑定的消息服务的具体设置

eureka:
  client: # 客户端进行Eureka注册的配置
    service-url:
      defaultZone: http://localhost:7001/eureka
  instance:
    lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
    lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
    instance-id: send-8801.com  # 在信息列表时显示主机名称
    prefer-ip-address: true     # 访问的路径变为IP地址

15.3.4 메인 시작 클래스 StreamMQMain8801

여기에 이미지 설명을 삽입하세요.

package com.angenin.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

15.3.5 비즈니스 클래스

1) 메시지 인터페이스 보내기

여기에 이미지 설명을 삽입하세요.

package com.angenin.springcloud.service;


public interface IMessageProvider {
    
    
     String send() ;
}

2) 메시지 인터페이스 구현 클래스 보내기

여기에 이미지 설명을 삽입하세요.

package com.angenin.springcloud.service.impl;

import com.angenin.springcloud.service.IMessageProvider;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.MessageChannel;

import javax.annotation.Resource;
import java.util.UUID;

/**
 * 不再是以前crud操作数据库了:业务类上使用@service了,类里面注入dao层对象
 * 现在操作的是消息中间件Rabbitmq:使用的是 SpringCloud Stream消息驱动中的注解
 */
@EnableBinding(Source.class) // 可以理解为定义消息的推送管道
public class MessageProviderImpl implements IMessageProvider {
    
    

    @Resource
    private MessageChannel output; // 消息的发送管道

    @Override
    public String send() {
    
    

        //定义发送的消息
        String serial = UUID.randomUUID().toString();
        //使用绑定器将消息绑定起来
        output.send(MessageBuilder.withPayload(serial).build());
        System.out.println("***serial: "+serial);

        return null;
    }
}

3) 컨트롤러

여기에 이미지 설명을 삽입하세요.

package com.angenin.springcloud.controller;

import com.angenin.springcloud.service.IMessageProvider;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class SendMessageController {
    
    
    @Resource
    private IMessageProvider messageProvider;

    //业务:每调用一次就发送一次流水号到Rabbitmq
    @GetMapping(value = "/sendMessage")
    public String sendMessage() {
    
    
        return messageProvider.send();
    }

}

15.3.6 테스트

  • 7001유레카 시작
  • RabbitMQ 시작
  • 8801을 시작하세요
    • Rabbitmq 관리 인터페이스를 방문하세요: http://192.168.10.140:15672
      여기에 이미지 설명을 삽입하세요.
    • 해당 구성:
      여기에 이미지 설명을 삽입하세요.
  • 입장
    • http://localhost:8801/sendMessage
    • 요청이 여러 번 발생했습니다.
      여기에 이미지 설명을 삽입하세요.
    • System.out... 백그라운드 로그의 출력 정보:
      여기에 이미지 설명을 삽입하세요.
    • Rabbitmq 관리 인터페이스에서 전송된 메시지의 최고 값을 볼 수 있으며 이는 위의 통합 구성이 성공했음을 나타냅니다.
      여기에 이미지 설명을 삽입하세요.

15.4 메시지 기반 소비자

15.4.1 새 모듈: cloud-stream-rabbitmq-consumer8802

여기에 이미지 설명을 삽입하세요.

15.4.2 POM

여기에 이미지 설명을 삽입하세요.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.angenin.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-stream-rabbitmq-consumer8802</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <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>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--基础配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

15.4.3 YML

  • 생산자 8801과의 유일한 차이점은 생산자 8801이 출력을 사용하고 소비자 8802가 입력을 사용한다는 것입니다. 물론 이름은 다릅니다.
    여기에 이미지 설명을 삽입하세요.
server:
  port: 8802

spring:
  application:
    name: cloud-stream-consumer
  cloud:
    stream:
      binders: # 在此处配置要绑定的rabbitmq的服务信息;
        defaultRabbit: # 表示定义的名称,用于于binding整合
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
                host: 192.168.10.140
                port: 5672
                username: admin
                password: 123456
      bindings: # 服务的整合处理
        input: # 这个名字是一个通道的名称     生产者使用output,消费者使用input
          destination: studyExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
          binder: defaultRabbit # 设置要绑定的消息服务的具体设置

eureka:
  client: # 客户端进行Eureka注册的配置
    service-url:
      defaultZone: http://localhost:7001/eureka
  instance:
    lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
    lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
    instance-id: receive-8802.com  # 在信息列表时显示主机名称
    prefer-ip-address: true     # 访问的路径变为IP地址


15.4.4 메인 시작 클래스 StreamMQMain8802

여기에 이미지 설명을 삽입하세요.

package com.angenin.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

15.4.5 비즈니스 클래스

여기에 이미지 설명을 삽입하세요.

package com.angenin.springcloud.controller;


import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

@Component
@EnableBinding(Sink.class) //指信道channel和exchange绑定在一起
public class ReceiveMessageListener {
    
    

    @Value("${server.port}")
    private String serverPort;


    @StreamListener(Sink.INPUT) //监听队列,用于消费者的队列的消息接收
    public void input(Message<String> message) {
    
    
        System.out.println("消费者1号,----->接受到的消息: "+message.getPayload()+"\t  port: "+serverPort);
    }


}

15.4.6 메시지를 보내려면 8801을 테스트하고 메시지를 받으려면 8802를 테스트하세요.

  • 7001, Rabbitmq, 8801, 8802 시작
  • http://localhost:8801/sendMessage
  • Rabbitmq 관리 인터페이스를 확인하세요.
    여기에 이미지 설명을 삽입하세요.
    여기에 이미지 설명을 삽입하세요.
  • 메시지 생성자가 메시지를 보냅니다.
    여기에 이미지 설명을 삽입하세요.
  • 메시지 소비자가 메시지를 받습니다.
    여기에 이미지 설명을 삽입하세요.

15.5 집단 소비와 지속성

15.1 8802 소비자에 따라 복사본을 복제하고 8803 소비자를 실행합니다.

  • 클라우드 스트림-rabbitmq-consumer8803
    여기에 이미지 설명을 삽입하세요.

  • 디렉토리 구조:
    여기에 이미지 설명을 삽입하세요.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.angenin.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-stream-rabbitmq-consumer8803</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <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>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--基础配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>
  • YML
server:
  port: 8803

spring:
  application:
    name: cloud-stream-consumer
  cloud:
    stream:
      binders: # 在此处配置要绑定的rabbitmq的服务信息;
        defaultRabbit: # 表示定义的名称,用于于binding整合
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
                host: 192.168.10.140
                port: 5672
                username: admin
                password: 123456
      bindings: # 服务的整合处理
        input: # 这个名字是一个通道的名称     生产者使用output,消费者使用input
          destination: studyExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
          binder: defaultRabbit # 设置要绑定的消息服务的具体设置

eureka:
  client: # 客户端进行Eureka注册的配置
    service-url:
      defaultZone: http://localhost:7001/eureka
  instance:
    lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
    lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
    instance-id: receive-8803.com  # 在信息列表时显示主机名称
    prefer-ip-address: true     # 访问的路径变为IP地址


  • 메인 스타트업 수업
package com.angenin.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

  • 비즈니스 클래스
package com.angenin.springcloud.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

@Component
@EnableBinding(Sink.class)
public class ReceiveMessageListener
{
    
    
    @Value("${server.port}")
    private String serverPort;

    @StreamListener(Sink.INPUT)
    public void input(Message message)
    {
    
    
        System.out.println("消费者2号,------->接收到的消息:" + message.getPayload()+"\t port: "+serverPort);
    }
}

15.2 시작

  • RabbitMQ 시작
  • 7001 서비스 등록 시작
  • 8801 메시지 생성 시작
  • 8802 메시지 소비 시작
  • 8803 메시지 소비 시작

15.3 실행 후 두 가지 문제가 발생합니다

  • 반복적으로 섭취하는 문제가 있습니다.
  • 메시지 지속성 문제

15.4 소비

현재 8802/8803을 동시에 받았는데, 반복적으로 소모되는 문제가 있습니다.

  • http://localhost:8801/sendMessage: 생산자 8801이 메시지를 보냈고 소비자 8802와 8803이 모두 메시지를 받았다는 것을 확인했습니다.
    여기에 이미지 설명을 삽입하세요.

  • 해결 방법

    • 分组和持久化属性group
  • 생산 실제 사례
    여기에 이미지 설명을 삽입하세요.

  • 기본적으로 8802와 8803은 서로 다른 그룹이므로 반복해서 사용할 수 있습니다.
    여기에 이미지 설명을 삽입하세요.
    여기에 이미지 설명을 삽입하세요.

15.5 그룹화

원칙

  • 마이크로서비스 애플리케이션을 동일한 그룹에 배치하면 애플리케이션 중 하나에서 메시지가 한 번만 소비되도록 할 수 있습니다.
  • 不同的组是可以消费的,同一个组内会发生竞争关系,只有其中一个可以消费。

8802/8803은 서로 다른 그룹이 되었으며, 두 그룹은 서로 다릅니다.

  • 그룹: atguiguA、atguiguB

  • 8802 YML 수정:group: atguiguA
    여기에 이미지 설명을 삽입하세요.

  • 8803 YML 수정:group: atguiguB
    여기에 이미지 설명을 삽입하세요.

  • 8802, 8803을 다시 시작하면 적용됩니다.

  • 우리가 직접 구성합니다

    • 고가용성 및 로드 밸런싱을 달성하기 위해 분산 마이크로서비스 애플리케이션은 실제로 여러 인스턴스를 배포합니다. 이 예에서 Yang Ge는 두 개의 소비자 마이크로서비스(8802/8803)를 시작했습니다. 대부분의 경우 생산자가 특정 마이크로서비스에 메시지를 보낼 때 우리는 한 번 소비되기를 바랍니다. 두 개의 애플리케이션을 시작하는 위의 예에 따르면 동일한 애플리케이션에 속하더라도 메시지는 두 번 소비됩니다. 이 문제를 해결하기 위해 Spring Cloud Stream에 개념이 제공된다 消费组.
      여기에 이미지 설명을 삽입하세요.
      여기에 이미지 설명을 삽입하세요.
  • 결론: 아니면 반복적으로 섭취한다

    • 생산자가 메시지를 보내고 3번 클릭함
      여기에 이미지 설명을 삽입하세요.

    • 프로듀서 콘솔 8801
      여기에 이미지 설명을 삽입하세요.

    • 소비자 콘솔 8802
      여기에 이미지 설명을 삽입하세요.

    • 소비자 콘솔 8803
      여기에 이미지 설명을 삽입하세요.

8802/8803은 동일한 그룹이 되며 두 그룹은 동일합니다.

  • 그룹: atguiguA

  • 8802 YML 수정: atguiguA
    여기에 이미지 설명을 삽입하세요.

  • 8803 YML 수정: atguiguA
    여기에 이미지 설명을 삽입하세요.

  • 재시작이 적용됩니다:

  • 우리는 그것을 직접 구성합니다:

    • Rabbitmq 관리 인터페이스를 살펴보면 atguiguA와 atguiguB라는 두 그룹을 발견했습니다. atguiguB는 이전 이력 기록이며 그것과 아무 관련이 없습니다.

    • 앳구이구 그룹 A에는 2명의 컨슈머(8802, 8803)가 있는데, 이때 그룹 A로 메시지를 보내어 매번 경쟁을 하게 되는데, 같은 그룹 내에서는 한 인스턴스만이 이를 얻을 수 있어 반복적인 소비를 피할 수 있다.
      여기에 이미지 설명을 삽입하세요.
      여기에 이미지 설명을 삽입하세요.

    • atguiguA를 클릭하면 내부에 2명의 Consumer가 있는 것을 볼 수 있습니다.
      여기에 이미지 설명을 삽입하세요.
      여기에 이미지 설명을 삽입하세요.

    • 클릭 atguiguB: 소비자 수는 0입니다.
      여기에 이미지 설명을 삽입하세요.
      여기에 이미지 설명을 삽입하세요.

  • 결론: 동일한 그룹에 있는 여러 마이크로서비스 인스턴스 중에서 한 번에 하나만 얻을 수 있습니다.

    • 생산자가 메시지를 보내고 2번 클릭함
      여기에 이미지 설명을 삽입하세요.

    • 프로듀서 콘솔 8801
      여기에 이미지 설명을 삽입하세요.

    • 소비자 콘솔 8802
      여기에 이미지 설명을 삽입하세요.

    • 소비자 콘솔 8803
      여기에 이미지 설명을 삽입하세요.

  • 8802/8803은 폴링 그룹화를 구현합니다. 소비자가 하나만 있을 때마다
    8801 모듈에서 보낸 메시지는 8802 또는 8803 중 하나만 수신할 수 있으므로 반복적인 소비를 피할 수 있습니다.

15.6 지구화

  • 위의 내용을 통해 반복적인 소비의 문제를 해결한 후 지속성을 살펴보자.

  • 8802/8803을 중지하고 8802 그룹을 제거합니다: atguiguA
    여기에 이미지 설명을 삽입하세요.

    • 그룹 그룹 8803: atguiguA가 제거되지 않았습니다.
      여기에 이미지 설명을 삽입하세요.
  • 8801은 먼저 Rabbitmq에 4개의 메시지를 보냅니다:http://localhost:8801/sendMessage
    여기에 이미지 설명을 삽입하세요.
    여기에 이미지 설명을 삽입하세요.

  • 8802를 먼저 시작하면 그룹 속성 구성이 없으며 백그라운드에 메시지가 인쇄되지 않습니다.
    여기에 이미지 설명을 삽입하세요.

  • 8803을 다시 시작하고 그룹 속성을 구성하면 MQ의 메시지가 백그라운드에서 인쇄됩니다.
    여기에 이미지 설명을 삽입하세요.

  • 요약: 여러 가지 문제로 인해 Consumer가 다운된 상태인데, 이때 producer는 계속해서 메시지를 보낸 후, Consumer를 다시 시작하게 됩니다 .Rabbitmq에서 소비 되지 않은 메시지를 Consumer가 配置了分组소비 하는 경우, 결함 문제, 메시지로 인해 소비되어 메시지가 손실됩니다.没有配置分组不会

16 SpringCloud Sleuth 분산 요청 링크 추적

16.1 개요

16.1 이 기술은 왜 등장하는가?

  • 이 기술은 왜 등장했나요? 어떤 문제를 해결해야 합니까?
    • 마이크로서비스 프레임워크에서 클라이언트가 시작한 요청은 백엔드 시스템의 여러 서비스 노드에서 호출되어 최종 요청 결과를 공동으로 생성합니다. 이전의 각 요청은 복잡한 분산 서비스 호출 체인을 형성합니다. 높은 지연 또는 오류 링크의 모든 링크에서 전체 요청이 결국 실패하게 됩니다.
    • 따라서 마이크로서비스 아키텍처에서는 더 많은 링크가 호출될수록 서비스 A에서 수행한 단계 수, 각 단계에 걸리는 시간, 링크 호출을 완료한 후 수행한 단계 수를 알아야 합니다. 많은 마이크로서비스가 사용되었으며 어떤 노드가 전달되었습니다.
    • 매우 큰 시스템에 대한 분산 요청 링크 추적. 80이 8001을 호출하고, 8001이 8002를 호출하여 링크를 형성하는 등 마이크로서비스 모듈이 매우 많을 때 사용해야 하며, 링크 내의 링크가 실패하면 Sleuth를 사용하여 링크를 추적할 수 있습니다. .
      여기에 이미지 설명을 삽입하세요.
      여기에 이미지 설명을 삽입하세요.

15.2이란 무엇입니까?

  • https://github.com/spring-cloud/spring-cloud-sleuth
    여기에 이미지 설명을 삽입하세요.

  • Spring Cloud Sleuth는 완벽한 서비스 추적 솔루션을 제공합니다.

  • 분산 시스템에서 추적 솔루션을 제공하며 zipkin과 호환됩니다.

  • sleuth는 추적을 담당하고 zipkin은 표시를 담당합니다.

16.3 해상도

  • 링크 데이터를 전송한 후 웹페이지 형태로 호출 효과를 표시합니다.
    여기에 이미지 설명을 삽입하세요.

16.2 링크 모니터링 설정 단계

16.2.1 집킨

1) 다운로드

  • SpringCloud는 더 이상 버전 F에서 Zipkin Server 서버를 구축할 필요가 없으며 jar 패키지만 호출하면 됩니다.

  • https://repo1.maven.org/maven2/io/zipkin/zipkin-server/
    여기에 이미지 설명을 삽입하세요.

  • zipkin-서버-2.24.3-exec.jar
    여기에 이미지 설명을 삽입하세요.

2) 항아리 실행

  • cmd로 들어가세요
  • 입력: java -jar zipkin-server-2.24.3-exec.jar
    여기에 이미지 설명을 삽입하세요.

3) 콘솔 실행

  • http://localhost:9411/zipkin/
    여기에 이미지 설명을 삽입하세요.

  • 용어

    • 통화 링크 완료
      • 요청 링크를 나타냅니다. 링크는 Trace ID로 고유하게 식별되며, Span은 시작된 요청 정보를 식별합니다. 각 범위는 상위 ID로 연결됩니다.
        여기에 이미지 설명을 삽입하세요.
    • 위 사진은 뭔가요?
      • 링크는 Trace ID로 고유하게 식별되고, Span은 시작된 요청 정보를 식별하며, 각 범위는 상위 ID로 연결됩니다.
        여기에 이미지 설명을 삽입하세요.
      • 전체 링크의 종속성은 다음과 같습니다.
        여기에 이미지 설명을 삽입하세요.
    • 용어 사전
      • Trace: 고유 식별자가 있는 통화 링크를 나타내는 트리 구조와 유사한 Span 컬렉션
      • 스팬(span): 호출 링크의 소스를 나타냅니다. 스팬에 대한 대중적인 이해는 정보 요청입니다.

16.2.2 서비스 제공자

1)클라우드 제공업체-결제8001

  • 새 프로젝트를 만드는 수고를 고려하여 여기서는 더 이상 새 프로젝트를 만들지 않고 이전 프로젝트를 직접 사용합니다.

2) 포엠

  • 종속성 추가
    여기에 이미지 설명을 삽입하세요.
   <!--包含了sleuth+zipkin-->
   <dependency>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-starter-zipkin</artifactId>
   </dependency>

3) YML

여기에 이미지 설명을 삽입하세요.

spring:
  application:
    #微服务名称,将此服务项目入住到注册中心,那么就需要给此项目取个名字
    name: cloud-payment-service
  zipkin:
    base-url: http://localhost:9411  # zipkin 地址
  sleuth:
    sampler:
      probability: 1  #采样率值介于0到1之间,1则表示全部采集(一般不为1,不然高并发性能会有影响)

4) 비즈니스 클래스 PaymentController

  • 앞서 작성한 컨트롤 레이어에 테스트 메소드를 추가합니다.
    여기에 이미지 설명을 삽입하세요.
    @GetMapping("/payment/zipkin")
    public String paymentZipkin() {
    
    
        
        return "hi ,i'am paymentzipkin server fall back,welcome to atguigu,O(∩_∩)O哈哈~";
    }

16.2.3 서비스 소비자(호출자)

1) 클라우드-소비자-주문80

  • 새 프로젝트를 만드는 수고를 고려하여 여기서는 더 이상 새 프로젝트를 만들지 않고 이전 프로젝트를 직접 사용합니다.

2) 포엠

  • 또한 이 종속성을 소개합니다.
    여기에 이미지 설명을 삽입하세요.
	<!-- 引入sleuth + zipkin -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>

3) YML

여기에 이미지 설명을 삽입하세요.

spring:
  application:
    name: cloud-order-service
  zipkin:
    base-url: http://localhost:9411  # zipkin 地址
  sleuth:
    sampler:
      # 采样率值 介于0-1之间 ,1表示全部采集
      probability: 1  

4) 비즈니스 클래스 OrderController

  • 앞서 작성한 컨트롤 레이어에 테스트 메소드를 추가합니다.
    여기에 이미지 설명을 삽입하세요.
    // ====================> zipkin+sleuth
    @GetMapping("/consumer/payment/zipkin")
    public String paymentZipkin() {
    
    

        String result = restTemplate.getForObject("http://localhost:8001"+"/payment/zipkin/", String.class);
        return result;
    }

16.2.4 테스트

  • eureka7001/8001/80을 순차적으로 시작

  • 80은 테스트를 위해 8001을 여러 번 호출합니다.http://localhost/consumer/payment/zipkin
    여기에 이미지 설명을 삽입하세요.

  • 브라우저를 열고 http://localhost:9411을 방문하세요.

    • 다음 인터페이스가 나타납니다
      여기에 이미지 설명을 삽입하세요.

    • 흔적 찾기
      여기에 이미지 설명을 삽입하세요.

    • 종속성 보기
      여기에 이미지 설명을 삽입하세요.

추천

출처blog.csdn.net/aa35434/article/details/132467982