SpringCloud 마이크로서비스 아키텍처---기초

1. 마이크로서비스 이해

1.1 서비스 아키텍처의 진화

1.1.1 모놀리식 아키텍처

모놀리식 아키텍처 : 비즈니스의 모든 기능이 하나의 프로젝트에서 개발되고 배포를 위해 하나의 패키지로 패키징됩니다.

여기에 이미지 설명 삽입

모놀리식 아키텍처의 장점과 단점은 다음과 같습니다.

이점:

  • 간단한 구조
  • 낮은 배포 비용

결점:

  • 높은 결합도(유지 및 업그레이드 어려움)

1.1.2, 분산 아키텍처

분산 아키텍처 : 시스템은 비즈니스 기능에 따라 분할되고 각 비즈니스 기능 모듈은 서비스라고 하는 독립적인 프로젝트로 개발됩니다.

여기에 이미지 설명 삽입

분산 아키텍처의 장단점:

이점:

  • 서비스 결합 감소
  • 서비스 업그레이드 및 확장에 도움

결점:

  • 서비스 콜 관계가 복잡하다

분산 아키텍처는 서비스 결합을 줄이지만 서비스를 분할할 때 고려해야 할 많은 문제가 여전히 있습니다.

  • 서비스 분할의 세분성을 정의하는 방법은 무엇입니까?
  • 서비스 클러스터 주소를 유지하는 방법은 무엇입니까?
  • 서비스 간 원격 호출을 구현하는 방법은 무엇입니까?
  • 서비스 상태를 어떻게 인식합니까?

사람들은 분산 아키텍처를 제한하기 위해 일련의 효과적인 표준을 개발해야 합니다.

1.1.3 마이크로서비스

마이크로서비스의 아키텍처 특성:

  • 단일 책임: 마이크로 서비스 분할의 세분성은 더 작고 각 서비스는 단일 책임을 달성하기 위해 고유한 비즈니스 기능에 해당합니다.
  • 자율성: 독립적인 팀, 독립적인 기술, 독립적인 데이터, 독립적인 배포 및 제공
  • 서비스 지향: 서비스는 언어 및 기술과 독립적인 통합 표준 인터페이스를 제공합니다.
  • 강력한 격리: 서비스 호출이 격리되고 내결함성이 있으며 계단식 문제를 방지하기 위해 성능이 저하됩니다.

여기에 이미지 설명 삽입

위의 마이크로서비스의 특성은 실제로 분산 아키텍처의 표준을 설정하고 서비스 간의 결합을 더욱 줄이고 서비스의 독립성과 유연성을 제공합니다. 높은 응집력과 낮은 결합도를 달성합니다.

따라서 마이크로서비스는 아키텍처가 잘 설계된 분산 아키텍처 솔루션 이라고 할 수 있습니다 .

그러나 그 계획은 어떻게 실행되어야 하는가? 어떤 기술 스택을 선택해야 합니까? 전 세계 인터넷 기업들은 자체 마이크로서비스 구현 솔루션을 적극적으로 시도하고 있습니다.

그 중 자바 분야에서 가장 눈길을 끄는 것은 스프링 클라우드에서 제공하는 솔루션이다.

1.1.4 요약

모놀리식 아키텍처 기능?

  • 간단하고 편리하며 고도로 결합되고 확장성이 좋지 않아 소규모 프로젝트에 적합합니다. 예: 학생 관리 시스템

분산 아키텍처의 특징?

  • 결합이 느슨하고 확장성이 좋지만 구조가 복잡하고 어렵습니다. JD.com 및 Taobao와 같은 대규모 인터넷 프로젝트에 적합

마이크로서비스: 우수한 분산 아키텍처 솔루션

  • 장점: 더 작은 분할 세분성, 더 독립적인 서비스 및 더 낮은 결합
  • 단점 : 구조가 매우 복잡하고 운영 및 유지 보수, 모니터링 및 배치의 어려움이 증가함
  • SpringCloud는 마이크로서비스 아키텍처를 위한 원스톱 솔루션으로, 다양하고 우수한 마이크로서비스 기능 구성 요소를 통합합니다.

1.2 마이크로서비스 기술 비교

1.2.1 마이크로서비스 구조

마이크로서비스 솔루션은 이를 구현하기 위한 기술적 프레임워크가 필요하며, 전 세계 인터넷 기업들이 자체 마이크로서비스 구현 기술을 적극적으로 시도하고 있다. 중국에서 가장 잘 알려진 것은 SpringCloud와 Alibaba의 Dubbo입니다.

여기에 이미지 설명 삽입

1.2.2 마이크로서비스 비교

여기에 이미지 설명 삽입

여기에 이미지 설명 삽입

1.3、스프링클라우드

SpringCloud는 현재 중국에서 가장 널리 사용되는 마이크로서비스 프레임워크입니다. 공식 웹사이트 주소: https://spring.io/projects/spring-cloud.

SpringCloud는 다양한 마이크로 서비스 기능 구성 요소를 통합하고 SpringBoot를 기반으로 이러한 구성 요소의 자동 어셈블리를 실현하여 우수한 기본 경험을 제공합니다.

여기에 이미지 설명 삽입

2. 마이크로서비스 분할 및 원격 호출

2.1 서비스 분할 원칙

  • 서로 다른 마이크로 서비스, 동일한 비즈니스를 반복적으로 개발하지 마십시오.
  • 마이크로서비스 데이터는 독립적이며 다른 마이크로서비스의 데이터베이스에 액세스하지 않습니다.
  • 마이크로서비스는 다른 마이크로서비스가 호출할 수 있도록 비즈니스를 인터페이스로 노출할 수 있습니다.

여기에 이미지 설명 삽입

2.2 서비스 분할 예시

cloud-demo: 상위 프로젝트, 종속성 관리

  • order-service: 주문 관련 업무를 담당하는 주문 마이크로서비스
  • user-service: 사용자 관련 비즈니스를 담당하는 사용자 마이크로서비스

필요하다:

  • 주문 마이크로서비스와 사용자 마이크로서비스 모두 서로 독립적인 자체 데이터베이스를 가져야 합니다.
  • 주문 서비스와 사용자 서비스 모두 Restful 인터페이스를 외부 세계에 노출합니다.
  • 주문 서비스가 사용자 정보를 조회해야 하는 경우 사용자 서비스의 Restful 인터페이스만 호출할 수 있으며 사용자 데이터베이스를 조회할 수 없습니다.

2.2.1 Sql 문 가져오기

2.2.2 데모 프로젝트 가져오기

3. 유레카 등록 센터

3.1, 유레카 원리

여기에 이미지 설명 삽입

소비자는 서비스 제공자에 대한 구체적인 정보를 어떻게 얻어야 합니까?

  • 서비스 제공자는 유레카 시작 시 자신의 정보를 유레카에 등록
  • 유레카는 이 정보를 저장합니다
  • 소비자는 서비스 이름에 따라 유레카에서 공급자 정보를 가져옵니다.

서비스 제공자가 여러 개인 경우 소비자는 어떻게 선택해야 합니까?

  • 서비스 소비자는 부하 분산 알고리즘을 사용하여 서비스 목록에서 서비스를 선택합니다.

소비자는 서비스 제공자의 건강 상태를 어떻게 인식합니까?

  • 서비스 공급자는 상태를 보고하기 위해 30초마다 EurekaServer에 하트비트 요청을 보냅니다.
  • eureka는 레코드 서비스 목록 정보를 업데이트하고 비정상적인 하트비트를 제거합니다.
  • 소비자는 최신 정보를 가져올 수 있습니다.

Eureka 아키텍처에는 두 가지 유형의 마이크로서비스 역할이 있습니다.

  • EurekaServer: 서버, 등록 센터

    • 서비스 정보 기록
    • 하트비트 모니터링
  • 유레카 클라이언트: 클라이언트

    • Provider: 서비스 제공자 등의 사용자 서비스인 경우

      • 자신의 정보를 EurekaServer에 등록
      • 30초마다 EurekaServer에 하트비트 전송
    • 소비자 : 주문 서비스 등 서비스 소비자의 경우

      • 서비스 이름에 따라 EurekaServer에서 서비스 목록을 가져옵니다.

      • 서비스 목록을 기반으로 부하 분산을 수행하고 마이크로 서비스를 선택한 후 원격 호출을 시작합니다.

3.2 유레카 서버 구축

3.2.1 유레카 서버 서비스 생성

3.2.2 유레카 종속성 소개

eureka를 위해 SpringCloud에서 제공하는 스타터 종속성을 소개합니다.

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

3.2.3, 시작 클래스 작성

eureka-server 서비스를 위한 시작 클래스를 작성하려면 @EnableEurekaServer 주석을 추가하여 eureka의 등록 센터 기능을 활성화해야 합니다.

package cn.test.eureka;

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

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

3.2.4 구성 파일 쓰기

다음 내용으로 application.yml 파일을 작성합니다.

server:
  port: 10086
spring:
  application:
    name: eureka-server
eureka:
  client:
    service-url: 
      defaultZone: http://127.0.0.1:10086/eureka

3.2.5 서비스 시작

마이크로 서비스를 시작한 다음 브라우저에서 http://127.0.0.1:10086을 방문하십시오.

다음 결과가 성공해야 합니다.

여기에 이미지 설명 삽입

3.3 서비스 등록

3.3.1 종속성 소개

user-service의 pom 파일에서 다음 eureka-client 종속성을 도입합니다.

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

3.3.2 구성 파일

user-service에서 application.yml 파일을 수정하고 서비스 이름과 eureka 주소를 추가합니다.

spring:
  application:
    name: userservice
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka

3.3.3 여러 사용자 서비스 인스턴스 시작하기

서비스에 여러 인스턴스가 있는 시나리오를 시연하기 위해 SpringBoot 시작 구성을 추가하고 사용자 서비스를 시작합니다.

3.4 서비스 검색

3.4.1 종속성 소개

앞에서 언급했듯이 서비스 검색 및 서비스 등록은 모두 eureka-client 종속성으로 캡슐화되므로 이 단계는 서비스 등록과 일치합니다.

order-service의 pom 파일에서 다음 eureka-client 종속성을 도입합니다.

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

3.4.2 구성 파일

서비스 검색도 유레카 주소를 알아야 하므로 두 번째 단계는 유레카 정보를 구성하는 서비스 등록과 일치합니다.

order-service에서 application.yml 파일을 수정하고 서비스 이름과 eureka 주소를 추가합니다.

spring:
  application:
    name: orderservice
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka

3.4.3 서비스 풀과 로드 밸런싱

마지막으로 eureka-server에서 사용자 서비스 서비스의 인스턴스 목록을 가져와 로드 밸런싱을 구현합니다.

그러나 이러한 작업을 수행할 필요는 없으며 일부 주석만 추가하면 됩니다.

order-service의 OrderApplication에서 RestTemplate Bean에 @LoadBalanced 주석을 추가합니다.

Spring은 자동으로 서비스 이름 userservice에 따라 eureka-server 측에서 인스턴스 목록을 얻은 다음 로드 밸런싱을 완료하도록 도와줍니다.

3.5 요약

유레카 서버 구축

  • 유레카 서버 종속성 소개

  • @EnableEurekaServer 주석 추가

  • application.yml에서 유레카 주소 구성

서비스 등록

  • 유레카 클라이언트 종속성 소개

  • application.yml에서 유레카 주소 구성

서비스 디스커버리

  • 유레카 클라이언트 종속성 소개
  • application.yml에서 유레카 주소 구성
  • RestTemplate에 @LoadBalanced 주석 추가
  • 서비스 제공자의 서비스 이름으로 원격 호출

4. 리본 로드 밸런싱의 원리

4.1 로드 밸런싱의 원리

Spring Cloud의 하단 레이어는 실제로 리본이라는 구성 요소를 사용하여 로드 밸런싱을 구현합니다.

여기에 이미지 설명 삽입

4.2 소스 코드 추적

서비스 이름을 입력해야만 액세스할 수 있는 이유는 무엇입니까? 또한 이전에 ip와 포트를 가져와야 합니다.

분명히 누군가 서비스 이름을 기반으로 서비스 인스턴스의 IP와 포트를 얻는 데 도움을 주었습니다. LoadBalancerInterceptor, 이 클래스는 RestTemplate 요청을 가로챈 다음 서비스 ID에 따라 Eureka에서 서비스 목록을 얻은 다음 로드 밸런싱 알고리즘을 사용하여 실제 서비스 주소 정보를 얻고 서비스 ID를 대체합니다.

우리는 소스 코드 추적을 수행합니다.

4.2.1、로드밸런서 인터셉터

여기에 이미지 설명 삽입
여기서 가로채기 메서드가 사용자의 HttpRequest 요청을 가로챈 다음 여러 작업을 수행하는 것을 볼 수 있습니다.

  • request.getURI(): 요청 URI를 가져옵니다. 이 경우에는 http://user-service/user/8입니다.
  • originalUri.getHost(): 실제 서비스 ID인 uri 경로의 호스트 이름을 가져옵니다.user-service
  • this.loadBalancer.execute(): 서비스 ID 및 사용자 요청을 처리합니다.

다음은 유형 this.loadBalancer입니다 . 계속해서 따르십시오.LoadBalancerClient

4.2.2、로드밸런서클라이언트

실행 방법을 계속 따르십시오.

여기에 이미지 설명 삽입
코드는 다음과 같습니다.

  • getLoadBalancer(serviceId): 서비스 ID에 따라 ILoadBalancer를 가져오고 ILoadBalancer는 서비스 ID를 eureka로 가져와 서비스 목록을 가져와서 저장합니다.
  • getServer(loadBalancer): 내장된 부하 분산 알고리즘을 사용하여 서비스 목록에서 하나를 선택합니다. 이 예에서는 포트 8082의 서비스가 확보되었음을 알 수 있습니다.

릴리스 후 다시 방문하여 추적한 결과 8081이라는 결과를 얻었습니다.

여기에 이미지 설명 삽입

당연히 로드 밸런싱이 달성됩니다.

4.2.3, 로드 밸런싱 전략 IRule

지금 코드에서 액세스 서비스가 getServer로드 밸런싱을 수행하는 방법을 사용하는 것을 볼 수 있습니다.

여기에 이미지 설명 삽입

우리는 계속해서 후속 조치를 취합니다.
여기에 이미지 설명 삽입

소스 코드 chooseServer 메서드를 계속 추적하고 다음과 같은 코드 조각을 찾았습니다.

여기에 이미지 설명 삽입

이 규칙이 누구인지 봅시다:
여기에 이미지 설명 삽입

여기서 규칙의 기본값은 RoundRobinRule입니다. 클래스 소개를 참조하세요.

여기에 이미지 설명 삽입
여론조사 그런거 아니죠?

이 시점에서 전체 로드 밸런싱 프로세스가 명확해졌습니다.

4.2.4 요약

SpringCloudRibbon의 최하위 레이어는 인터셉터를 사용하여 RestTemplate이 보낸 요청을 가로채고 주소를 수정합니다. 사진으로 요약하자면 다음과 같습니다.

여기에 이미지 설명 삽입

기본 프로세스는 다음과 같습니다.

  • RestTemplate 요청 http://userservice/user/1 가로채기
  • RibbonLoadBalancerClient는 사용자 서비스인 요청 URL에서 서비스 이름을 가져옵니다.
  • DynamicServerListLoadBalancer는 사용자 서비스에 따라 eureka에서 서비스 목록을 가져옵니다.
  • eureka는 localhost:8081, localhost:8082 목록을 반환합니다.
  • IRule은 기본 제공 부하 분산 규칙을 ​​사용합니다. 목록에서 localhost:8081과 같은 규칙을 선택합니다.
  • RibbonLoadBalancerClient는 요청 주소를 수정하고 userservice를 localhost:8081로 바꾸고 http://localhost:8081/user/1을 가져오고 실제 요청을 시작합니다.

4.3 부하 분산 전략

4.3.1, 로드 밸런싱 전략

부하 분산 규칙은 IRule 인터페이스에서 정의되며 IRule에는 다양한 구현 클래스가 있습니다.

여기에 이미지 설명 삽입

다양한 규칙의 의미는 다음과 같습니다.

기본 제공 로드 밸런싱 규칙 클래스 규칙 설명
라운드 로빈 규칙 서비스 목록을 폴링하여 서버를 선택하기만 하면 됩니다. 리본의 기본 로드 밸런싱 규칙입니다.
가용성 필터링 규칙 다음 두 서버는 무시하십시오. (1) 기본적으로 이 서버가 3번 연결에 실패하면 이 서버는 "단락" 상태로 설정됩니다. 단락 상태는 30초 동안 지속되며 연결이 다시 실패하면 단락 기간이 기하급수적으로 증가합니다. (2) 동시성이 너무 높은 서버. 서버의 동시 연결 수가 너무 많으면 AvailabilityFilteringRule 규칙으로 구성된 클라이언트도 이를 무시합니다. 동시 연결 수의 상한은 클라이언트의 ..ActiveConnectionsLimit 속성으로 구성할 수 있습니다.
WeightedResponseTimeRule 각 서버에 가중치 값을 할당합니다. 서버 응답 시간이 길수록 이 서버의 가중치가 줄어듭니다. 이 규칙은 무작위로 서버를 선택하며 이 가중치는 서버 선택에 영향을 미칩니다.
ZoneAvoidanceRule 서버 선택은 해당 지역에서 사용 가능한 서버를 기반으로 합니다. Zone을 사용하여 서버를 분류합니다. 이 Zone은 전산실, 랙 등으로 이해될 수 있습니다. 그런 다음 영역에서 여러 서비스를 폴링합니다.
BestAvailableRule 단락된 서버는 무시하고 동시성이 낮은 서버를 선택하십시오.
무작위 규칙 사용 가능한 서버를 무작위로 선택합니다.
재시도 규칙 재시도 메커니즘의 선택 논리

기본 구현은 폴링 체계인 ZoneAvoidanceRule입니다.

4.3.2, 커스텀 로드 밸런싱 전략

로드 밸런싱 규칙은 IRule 구현을 정의하여 수정할 수 있습니다.

  1. 코드 방법: 주문 서비스의 OrderApplication 클래스에서 새 IRule을 정의합니다.
@Bean
public IRule randomRule(){
    
    
    return new RandomRule();
}
  1. 구성 파일 방법: order-service의 application.yml 파일에서 새 구성을 추가하면 규칙도 수정할 수 있습니다.
userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则 

기본 부하 분산 규칙은 일반적으로 수정 없이 사용됩니다 .

4.4 지연 로딩

리본은 기본적으로 지연 로딩을 사용합니다. 즉, LoadBalanceClient는 처음 액세스할 때만 생성되며 요청 시간이 매우 깁니다.

Hunger loading은 첫 방문 시간을 줄이기 위해 프로젝트 시작 시 생성됩니다. 다음 구성을 통해 Hunger loading을 활성화합니다.

ribbon:
  eager-load:
    enabled: true
    clients: userservice

4.5 요약

리본 부하 분산 규칙

  • 규칙 인터페이스는 IRule입니다.

  • 기본 구현은 ZoneAvoidanceRule이며 영역에 따라 서비스 목록을 선택한 다음 폴링합니다.

커스텀 로드 밸런싱 방식

  • 코드 방식: 유연한 구성이지만 수정 시 재패키징 및 릴리스 필요

  • 구성 방법: 직관적이고 편리하며 다시 패키징 및 게시할 필요가 없지만 전역 구성이 불가능합니다.

배고픔 로딩

  • 기아 로딩 활성화

  • 기아 로딩을 위한 마이크로서비스 이름 지정

5. 나코스 등록 센터

5.1 Nacos 이해 및 설치

5.1.1, 윈도우 설치

5.1.1.1 설치 패키지 다운로드

Nacos의 GitHub 페이지에는 컴파일된 Nacos 서버 또는 소스 코드를 다운로드할 수 있는 다운로드 링크가 있습니다.

GitHub 홈페이지: https://github.com/alibaba/nacos

GitHub의 릴리스 다운로드 페이지: https://github.com/alibaba/nacos/releases

그림과 같이:

여기에 이미지 설명 삽입

5.1.1.2, 압축 해제

그림과 같이 중국어가 아닌 디렉토리에 이 패키지의 압축을 풉니다.

여기에 이미지 설명 삽입

디렉토리 설명:

  • 빈: 시작 스크립트
  • conf: 구성 파일

5.1.1.3, 포트 구성

Nacos의 기본 포트는 8848입니다. 컴퓨터의 다른 프로세스가 포트 8848을 사용하는 경우 먼저 프로세스를 닫으십시오.

포트 8848을 점유하는 프로세스를 닫을 수 없는 경우 nacos의 conf 디렉토리에 들어가 구성 파일에서 포트를 수정할 수도 있습니다.

여기에 이미지 설명 삽입

5.1.1.4, 시작

시작은 매우 간단합니다. bin 디렉토리를 입력하면 구조는 다음과 같습니다.

여기에 이미지 설명 삽입

그런 다음 다음 명령을 실행합니다.

  • 윈도우 명령:

    startup.cmd -m standalone
    

실행 후 효과는 다음과 같습니다.

여기에 이미지 설명 삽입

5.1.1.5 액세스

브라우저에 주소를 입력하십시오: http://127.0.0.1:8848/nacos:

여기에 이미지 설명 삽입
다음을 입력한 후 기본 계정과 암호는 모두 nacos입니다.

여기에 이미지 설명 삽입

5.1.2, 리눅스 설치

5.1.2.1, JDK 설치

Nacos는 실행을 위해 JDK에 의존하며 JDK는 인덱스 Linux에 설치되어야 합니다.

jdk 설치 패키지를 업로드합니다.

예를 들어 디렉토리에 업로드하십시오./usr/local/

그런 다음 압축을 풉니다.

tar -xvf jdk-8u144-linux-x64.tar.gz

그런 다음 이름을 java로 바꿉니다.

환경 변수를 구성합니다.

export JAVA_HOME=/usr/local/java
export PATH=$PATH:$JAVA_HOME/bin

환경 변수 설정:

source /etc/profile

5.1.2.2 설치 패키지 업로드

그림과 같이:

여기에 이미지 설명 삽입

/usr/local/src예를 들어 다음 디렉터리 아래의 Linux 서버 디렉터리에 업로드합니다 .

여기에 이미지 설명 삽입

5.1.2.3, 압축 해제

설치 패키지 압축 해제 명령:

tar -xvf nacos-server-1.4.1.tar.gz

그런 다음 설치 패키지를 제거합니다.

rm -rf nacos-server-1.4.1.tar.gz

디렉토리의 최종 스타일:
여기에 이미지 설명 삽입

디렉토리 내부:
여기에 이미지 설명 삽입

5.1.2.4, 포트 구성

윈도우와 유사

5.1.2.5, 시작

nacos/bin 디렉토리에서 다음 명령을 입력하여 Nacos를 시작합니다.

sh startup.sh -m standalone

5.2 Nacos 빠른 시작

Nacos는 SpringCloudAlibaba의 구성 요소이며 SpringCloudAlibaba도 SpringCloud에 정의된 서비스 등록 및 서비스 검색 사양을 따릅니다. 따라서 마이크로서비스에 Nacos를 사용하는 것과 Eureka를 사용하는 것에는 큰 차이가 없습니다.

주요 차이점은 다음과 같습니다.

  • 다른에 따라 달라집니다
  • 서비스 주소가 다릅니다

5.2.1 종속성 소개

cloud-demo 상위 프로젝트의 pom 파일 <dependencyManagement>에서 SpringCloudAlibaba의 종속성을 소개합니다 .

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
    <version>2.2.6.RELEASE</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

그런 다음 user-service 및 order-service의 pom 파일에 nacos-discovery 종속성을 도입합니다.

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

참고 : eureka 종속성을 주석 처리하는 것을 잊지 마십시오.

5.2.2 nacos 주소 구성

user-service 및 order-service의 application.yml에 nacos 주소를 추가합니다.

spring:
  cloud:
    nacos:
      server-addr: localhost:8848

참고 : 유레카 주소를 주석 처리하는 것을 잊지 마십시오.

5.2.3, 재시작

마이크로 서비스를 다시 시작한 후 nacos 관리 페이지에 로그인하면 마이크로 서비스 정보를 볼 수 있습니다.

여기에 이미지 설명 삽입

요약하다:

나코스 서비스 구축

  • 설치 패키지 다운로드
  • 압축을 풀다
  • bin 디렉터리에서 다음 명령을 실행합니다. startup.cmd -m standalone

Nacos 서비스 등록 또는 검색

  • nacos.discovery 의존성 소개
  • nacos 주소 spring.cloud.nacos.server-addr 구성

5.3, Nacos 서비스 계층적 스토리지 모델

서비스 사용자 서비스와 같은 여러 인스턴스를 가질 수 있으며 다음을 가질 수 있습니다.

  • 127.0.0.1:8081
  • 127.0.0.1:8082
  • 127.0.0.1:8083

이러한 인스턴스가 전국의 다른 전산실에 분산되어 있는 경우 예를 들면 다음과 같습니다.

  • 127.0.0.1:8081, 상하이 전산실
  • 127.0.0.1:8082, 상하이 전산실
  • 127.0.0.1:8083, 항저우 전산실

Nacos는 동일한 전산실의 인스턴스를 클러스터 로 나눕니다 .

즉, 사용자 서비스는 서비스입니다.서비스는 항저우 및 상하이와 같은 여러 클러스터를 포함할 수 있습니다.각 클러스터는 그림과 같이 계층적 모델을 형성하는 여러 인스턴스를 가질 수 있습니다.

여기에 이미지 설명 삽입

마이크로서비스가 서로 액세스할 때 로컬 액세스가 더 빠르기 때문에 가능한 한 동일한 클러스터 인스턴스에 액세스해야 합니다. 클러스터를 사용할 수 없을 때만 다른 클러스터에 액세스하십시오. 예를 들어:

여기에 이미지 설명 삽입

항저우 전산실의 주문 서비스는 같은 전산실의 사용자 서비스에 우선적으로 접근해야 합니다.

요약하다:

Nacos 서비스 계층적 스토리지 모델

  • 첫 번째 수준은 userservice와 같은 서비스입니다.
  • 두 번째 수준은 항저우 또는 상하이와 같은 클러스터입니다.
  • 세 번째 수준은 사용자 서비스를 배포하는 항저우의 컴퓨터실에 있는 서버와 같은 인스턴스입니다.

인스턴스에 대한 클러스터 속성을 설정하는 방법

  • application.yml 파일을 수정하고 spring.cloud.nacos.discovery.cluster-name 속성을 추가합니다.

5.3.1 사용자 서비스를 위한 클러스터 구성

user-service의 application.yml 파일을 수정하고 클러스터 구성을 추가합니다.

spring:
  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: HZ # 集群名称

두 개의 사용자 서비스 인스턴스를 다시 시작한 후 nacos 콘솔에서 다음 결과를 볼 수 있습니다.
여기에 이미지 설명 삽입
사용자 서비스 시작 구성을 다시 복사하고 속성을 추가합니다.

-Dserver.port=8083 -Dspring.cloud.nacos.discovery.cluster-name=SH

구성은 그림에 나와 있습니다.
여기에 이미지 설명 삽입

UserApplication3을 시작한 후 nacos 콘솔을 다시 확인합니다.
여기에 이미지 설명 삽입

5.3.2 클러스터 우선순위가 같은 로드 밸런싱

기본적으로 ZoneAvoidanceRule동일한 클러스터의 우선순위에 따라 로드 밸런싱을 달성할 수 없습니다.

따라서 Nacos는 NacosRule동일한 클러스터에서 인스턴스를 우선적으로 선택할 수 있는 구현을 제공합니다.

1) 주문 서비스를 위한 클러스터 정보 구성

order-service의 application.yml 파일을 수정하고 클러스터 구성을 추가합니다.

spring:
  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: HZ # 集群名称

2) 부하 분산 규칙 수정

order-service의 application.yml 파일을 수정하고 부하 분산 규칙을 ​​수정합니다.

userservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则 

NacosRule 부하 분산 전략

  • 동일한 클러스터에 있는 서비스 인스턴스 목록의 우선 순위 지정
  • 로컬 클러스터는 공급자를 찾을 수 없으므로 다른 클러스터로 이동하여 공급자를 찾고 경고가 보고됩니다.
  • 사용 가능한 인스턴스 목록을 결정한 후 임의 로드 밸런싱을 사용하여 인스턴스를 선택합니다.

5.4 무게 구성

실제 배포에서는 다음과 같은 시나리오가 나타납니다.

서버 장비의 성능이 다릅니다.일부 인스턴스는 성능이 더 좋고 다른 인스턴스는 성능이 낮습니다.성능이 더 좋은 시스템이 더 많은 사용자 요청을 감당할 수 있기를 바랍니다.

그러나 기본적으로 NacosRule은 머신의 성능을 고려하지 않고 동일한 클러스터에서 무작위로 선택됩니다.

따라서 Nacos에서는 접근 빈도를 제어하기 위한 가중치 구성을 제공하며, 가중치가 클수록 접근 빈도가 높아집니다.

nacos 콘솔에서 사용자 서비스 인스턴스 목록을 찾아 편집을 클릭하면 가중치를 수정할 수 있습니다.
여기에 이미지 설명 삽입
팝업 편집 창에서 가중치를 수정합니다.
여기에 이미지 설명 삽입

참고 : 가중치가 0으로 수정되면 해당 인스턴스는 절대 방문하지 않습니다.

5.5 Nacos 환경 격리

Nacos는 환경 격리를 구현하기 위한 네임스페이스를 제공합니다.

  • nacos에는 여러 네임스페이스가 있을 수 있습니다.
  • 네임스페이스 아래에 그룹, 서비스 등이 있을 수 있습니다.
  • 서로 다른 네임스페이스는 서로 격리됩니다. 예를 들어 서로 다른 네임스페이스의 서비스는 서로 보이지 않습니다.

여기에 이미지 설명 삽입

5.5.1 네임스페이스 생성

기본적으로 모든 서비스, 데이터 및 그룹은 public이라는 동일한 네임스페이스에 있습니다.

여기에 이미지 설명 삽입

페이지에서 추가 버튼을 클릭하여 네임스페이스를 추가할 수 있습니다.

여기에 이미지 설명 삽입
그런 다음 양식을 작성하십시오.

여기에 이미지 설명 삽입

페이지에서 새 네임스페이스를 볼 수 있습니다.

여기에 이미지 설명 삽입

5.5.2 마이크로서비스용 네임스페이스 구성

마이크로서비스에 대한 네임스페이스 구성은 구성을 수정해야만 달성할 수 있습니다.

예를 들어 order-service의 application.yml 파일을 수정합니다.

spring:
  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: HZ
        namespace: 492a7d5d-237b-46a1-a99a-fa8e98e4b0f9 # 命名空间,填ID

order-service를 재시작한 후 콘솔에 접속하면 다음과 같은 결과를 확인할 수 있습니다.

여기에 이미지 설명 삽입
여기에 이미지 설명 삽입

이때 order-service에 액세스할 때 네임스페이스가 다르기 때문에 userservice를 찾을 수 없으며 콘솔에서 오류를 보고합니다.

여기에 이미지 설명 삽입

요약하다:

Nacos 환경 격리

  • 각 네임스페이스에는 고유한 ID가 있습니다.
  • 서비스가 네임스페이스를 설정할 때 name 대신 id를 쓴다.
  • 서로 다른 네임스페이스의 서비스는 서로에게 보이지 않습니다.

5.6 나코스와 유레카의 차이점

Nacos 서비스 인스턴스는 두 가지 유형으로 나뉩니다.

  • 임시 인스턴스: 인스턴스가 일정 시간 이상 다운되면 기본 유형인 서비스 목록에서 제거됩니다.

  • 비임시 인스턴스: 인스턴스가 다운되더라도 서비스 목록에서 제거되지 않으며 영구 인스턴스라고도 할 수 있습니다.

서비스 인스턴스를 영구 인스턴스로 구성합니다.

spring:
  cloud:
    nacos:
      discovery:
        ephemeral: false # 设置为非临时实例

Nacos와 Eureka의 전체 구조는 서비스 등록, 서비스 풀, 하트비트 대기와 유사하지만 몇 가지 차이점이 있습니다.

여기에 이미지 설명 삽입

  • 나코스와 유레카의 공통점

    • 서비스 등록 및 서비스 풀 모두 지원
    • 둘 다 상태 감지를 위한 서비스 공급자의 하트비트 방법을 지원합니다.
  • 나코스와 유레카의 차이점

    • Nacos는 서버가 공급자 상태를 능동적으로 감지하도록 지원합니다. 임시 인스턴스는 하트비트 모드를 채택하고 비임시 인스턴스는 활성 감지 모드를 채택합니다.
    • 심장 박동이 비정상적인 임시 인스턴스는 제거되지만 비임시 인스턴스는 제거되지 않습니다.
    • Nacos는 서비스 목록 변경의 메시지 푸시 모드를 지원하며 서비스 목록은 더 적시에 업데이트됩니다.
    • Nacos 클러스터는 기본적으로 AP 모드를 채택하며 클러스터에 비임시 인스턴스가 있는 경우 CP 모드를 채택하고 Eureka는 AP 모드를 채택합니다.

6. Nacos 구성 관리

6.1 통합 구성 관리

점점 더 많은 마이크로 서비스 인스턴스가 배포되어 수십 또는 수백에 이르면 마이크로 서비스 구성을 하나씩 수정하면 사람들이 미치고 오류가 발생하기 쉽습니다. 모든 인스턴스의 구성을 중앙에서 관리할 수 있는 통합 구성 관리 솔루션이 필요합니다.

여기에 이미지 설명 삽입
한편으로 Nacos는 구성을 중앙에서 관리할 수 있고, 다른 한편으로 구성이 변경되면 적시에 마이크로 서비스에 알려 구성의 핫 업데이트를 실현할 수 있습니다.

6.1.1 nacos에서 구성 파일 추가

nacos에서 구성을 관리하는 방법은 무엇입니까?
여기에 이미지 설명 삽입

그런 다음 팝업 양식에 구성 정보를 입력합니다.
여기에 이미지 설명 삽입

참고: 핫 업데이트 구성이 필요한 경우에만 프로젝트의 핵심 구성을 nacos에서 관리해야 합니다. 마이크로 서비스에서 로컬로 변경되지 않을 일부 구성을 저장하는 것이 좋습니다.

6.1.2 마이크로서비스에서 구성 가져오기

마이크로 서비스는 nacos에서 관리되는 구성을 가져와서 로컬 application.yml 구성과 병합하여 프로젝트 시작을 완료해야 합니다.

그러나 application.yml이 아직 읽히지 않았다면 nacos의 주소를 어떻게 알 수 있습니까?

따라서 spring은 application.yml보다 먼저 읽히는 새로운 구성 파일인 bootstrap.yaml 파일을 도입합니다. 프로세스는 다음과 같습니다.

여기에 이미지 설명 삽입

1) nacos-config 의존성 소개

먼저 사용자 서비스 서비스에서 nacos-config의 클라이언트 종속성을 도입합니다.

<!--nacos配置管理依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

2) bootstrap.yaml 추가

그런 다음 사용자 서비스에 다음 콘텐츠와 함께 bootstrap.yaml 파일을 추가합니다.

spring:
  application:
    name: userservice # 服务名称
  profiles:
    active: dev #开发环境,这里是dev 
  cloud:
    nacos:
      server-addr: localhost:8848 # Nacos地址
      config:
        file-extension: yaml # 文件后缀名

여기에서 nacos 주소는 spring.cloud.nacos.server-addr에 따라 얻은 다음

${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}파일 ID로 구성을 읽습니다.

이 예에서는 다음과 같이 읽습니다 userservice-dev.yaml.

여기에 이미지 설명 삽입

3) nacos 구성 읽기

사용자 서비스의 UserController에 비즈니스 로직을 추가하고 pattern.dateformat 구성을 읽습니다.

여기에 이미지 설명 삽입

전체 코드:

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
    
    

    @Autowired
    private UserService userService;

    @Value("${pattern.dateformat}")
    private String dateformat;
    
    @GetMapping("now")
    public String now(){
    
    
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dateformat));
    }
    // ...略
}

페이지를 방문하면 다음과 같은 효과를 볼 수 있습니다.

여기에 이미지 설명 삽입

요약하다:

구성을 Nacos 관리로 넘기는 단계

  • Nacos에 구성 파일 추가
  • 마이크로서비스에 nacos 구성 종속성 도입
  • 마이크로 서비스에 bootstrap.yml을 추가하고 nacos 주소, 현재 환경, 서비스 이름 및 파일 확장자를 구성합니다. 프로그램이 시작될 때 nacos에서 읽을 파일을 결정합니다.

6.2 구성 핫 업데이트

우리의 궁극적인 목표는 nacos에서 구성을 수정하여 마이크로서비스가 다시 시작하지 않고 구성을 적용할 수 있도록 하는 것입니다. 즉, 구성 핫 업데이트 입니다 .

구성 핫 업데이트를 달성하기 위해 두 가지 방법을 사용할 수 있습니다.

6.2.1 방법 1

@Value에 의해 주입된 변수가 있는 클래스에 @RefreshScope 주석을 추가합니다.

여기에 이미지 설명 삽입

6.2.2 방법 2

@Value 주석 대신 @ConfigurationProperties 주석을 사용하십시오.

사용자 서비스 서비스에서 patternern.dateformat 속성을 읽을 클래스를 추가합니다.

@Component
@Data
@ConfigurationProperties(prefix = "pattern")
public class PatternProperties {
    
    
    private String dateformat;
}

UserController에서 @Value 대신 이 클래스를 사용하십시오.

여기에 이미지 설명 삽입

전체 코드:

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
    
    

    @Autowired
    private UserService userService;

    @Autowired
    private PatternProperties patternProperties;

    @GetMapping("now")
    public String now(){
    
    
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(patternProperties.getDateformat()));
    }

    // 略
}

요약하다:

Nacos 구성이 변경된 후 다음과 같은 방법으로 마이크로서비스를 핫 업데이트할 수 있습니다.

  • 새로 고침을 위해 @RefreshScope와 결합된 @Value 주석을 통해 주입됨
  • @ConfigurationProperties를 통해 주입, 자동으로 새로 고침

지침:

  • 모든 구성이 구성 센터에 배치하기에 적합하지 않아 유지 관리가 번거로움

  • 일반적으로 사용자 지정 구성인 nacos 구성 센터에 런타임 시 조정해야 하는 몇 가지 주요 매개변수 및 매개변수를 입력하는 것이 좋습니다.

6.3, 구성 공유

실제로 마이크로 서비스가 시작되면 nacos로 이동하여 여러 구성 파일을 읽습니다. 예를 들면 다음과 같습니다.

  • [spring.application.name]-[spring.profiles.active].yaml, 예: userservice-dev.yaml

  • [spring.application.name].yaml, 예: userservice.yaml

[spring.application.name].yaml환경을 포함 하지 않으므로

사례를 통해 구성 공유를 테스트해 보자

6.3.1 환경 공유 구성 추가

nacos에 userservice.yaml 파일을 추가합니다.

여기에 이미지 설명 삽입

6.3.2 사용자 서비스에서 공유 구성 읽기

사용자 서비스 서비스에서 PatternProperties 클래스를 수정하여 새로 추가된 속성을 읽습니다.
여기에 이미지 설명 삽입

사용자 서비스 서비스에서 UserController를 수정하고 메서드를 추가합니다.
여기에 이미지 설명 삽입

6.3.3 프로필이 다른 두 개의 사용자 애플리케이션 실행

시작 항목 UserApplication2를 수정하고 프로필 값을 변경합니다.

이와 같이 UserApplication(8081)에서 사용하는 프로파일은 dev이고 UserApplication2(8082)에서 사용하는 프로파일은 test입니다.

UserApplication 및 UserApplication2 시작

http://localhost:8081/user/prop를 방문하면 결과는 다음과 같습니다.
여기에 이미지 설명 삽입

http://localhost:8082/user/prop를 방문하면 결과는 다음과 같습니다.
여기에 이미지 설명 삽입

개발 환경과 테스트 환경 모두 envSharedValue 속성의 값을 읽은 것을 볼 수 있습니다.

6.3.4 공유 우선 순위 구성

nacos와 service local이 동시에 동일한 속성을 가질 때 우선 순위는 높음과 낮음으로 나뉩니다.
여기에 이미지 설명 삽입
요약:

기본적으로 마이크로서비스에서 읽는 구성 파일:

  • [서비스 이름]-[spring.profile.active].yaml, 기본 구성
  • [서비스 이름].yaml, 다중 환경 공유

다양한 마이크로서비스에서 공유하는 구성 파일:

  • 공유 구성에 의해 지정됨
  • extension-configs에 의해 지정됨

우선 사항:

  • 환경 구성 > 서비스 이름.yaml > 확장 구성 > 확장 구성 > 공유 구성 > 로컬 구성

6.2 Nacos 클러스터 구축

6.2.1 클러스터 구조도

공식 Nacos 클러스터 다이어그램:

여기에 이미지 설명 삽입

여기에는 3개의 nacos 노드와 로드 밸런서 프록시 3개의 Nacos가 포함됩니다. 여기서 로드 밸런서는 nginx를 사용할 수 있습니다.

계획된 클러스터 구조:

여기에 이미지 설명 삽입

3개의 nacos 노드 주소:

마디 아이피 포트
나코스1 192.168.150.1 8845
나코스2 192.168.150.1 8846
나코스3 192.168.150.1 8847

6.2.2 클러스터 구축

클러스터를 구축하는 기본 단계:

  • 데이터베이스 구축 및 데이터베이스 테이블 구조 초기화
  • nacos 설치 패키지 다운로드
  • 나코스 구성
  • 나코스 클러스터 시작
  • nginx 리버스 프록시

6.2.2.1 데이터베이스 초기화

Nacos 기본 데이터는 프로덕션에서 사용할 수 있는 데이터베이스가 아닌 임베디드 데이터베이스 Derby에 저장됩니다.

공식적으로 권장되는 모범 사례는 마스터-슬레이브와 함께 고가용성 데이터베이스 클러스터를 사용하는 것입니다. 여기서는 단일 지점 데이터베이스를 예로 들어 설명합니다.

먼저 새 데이터베이스를 만들고 이름을 nacos로 지정한 후 다음 SQL을 가져옵니다.

CREATE TABLE `config_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(255) DEFAULT NULL,
  `content` longtext NOT NULL COMMENT 'content',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
  `app_name` varchar(128) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  `c_desc` varchar(256) DEFAULT NULL,
  `c_use` varchar(64) DEFAULT NULL,
  `effect` varchar(64) DEFAULT NULL,
  `type` varchar(64) DEFAULT NULL,
  `c_schema` text,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';

/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = config_info_aggr   */
/******************************************/
CREATE TABLE `config_info_aggr` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(255) NOT NULL COMMENT 'group_id',
  `datum_id` varchar(255) NOT NULL COMMENT 'datum_id',
  `content` longtext NOT NULL COMMENT '内容',
  `gmt_modified` datetime NOT NULL COMMENT '修改时间',
  `app_name` varchar(128) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租户字段';


/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = config_info_beta   */
/******************************************/
CREATE TABLE `config_info_beta` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL COMMENT 'content',
  `beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';

/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = config_info_tag   */
/******************************************/
CREATE TABLE `config_info_tag` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
  `tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL COMMENT 'content',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';

/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = config_tags_relation   */
/******************************************/
CREATE TABLE `config_tags_relation` (
  `id` bigint(20) NOT NULL COMMENT 'id',
  `tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
  `tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
  `nid` bigint(20) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`nid`),
  UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
  KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';

/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = group_capacity   */
/******************************************/
CREATE TABLE `group_capacity` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群',
  `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
  `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
  `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
  `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,,0表示使用默认值',
  `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
  `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表';

/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = his_config_info   */
/******************************************/
CREATE TABLE `his_config_info` (
  `id` bigint(64) unsigned NOT NULL,
  `nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `data_id` varchar(255) NOT NULL,
  `group_id` varchar(128) NOT NULL,
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL,
  `md5` varchar(32) DEFAULT NULL,
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `src_user` text,
  `src_ip` varchar(50) DEFAULT NULL,
  `op_type` char(10) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  PRIMARY KEY (`nid`),
  KEY `idx_gmt_create` (`gmt_create`),
  KEY `idx_gmt_modified` (`gmt_modified`),
  KEY `idx_did` (`data_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造';


/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = tenant_capacity   */
/******************************************/
CREATE TABLE `tenant_capacity` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
  `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
  `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
  `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
  `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数',
  `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
  `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表';


CREATE TABLE `tenant_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `kp` varchar(128) NOT NULL COMMENT 'kp',
  `tenant_id` varchar(128) default '' COMMENT 'tenant_id',
  `tenant_name` varchar(128) default '' COMMENT 'tenant_name',
  `tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
  `create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
  `gmt_create` bigint(20) NOT NULL COMMENT '创建时间',
  `gmt_modified` bigint(20) NOT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
  KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';

CREATE TABLE `users` (
	`username` varchar(50) NOT NULL PRIMARY KEY,
	`password` varchar(500) NOT NULL,
	`enabled` boolean NOT NULL
);

CREATE TABLE `roles` (
	`username` varchar(50) NOT NULL,
	`role` varchar(50) NOT NULL,
	UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE
);

CREATE TABLE `permissions` (
    `role` varchar(50) NOT NULL,
    `resource` varchar(255) NOT NULL,
    `action` varchar(8) NOT NULL,
    UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE
);

INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);

INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');

6.2.2.2 나코스 다운로드

nacos는 GitHub에 다운로드 주소가 있습니다: https://github.com/alibaba/nacos/tags, 다운로드할 버전을 선택할 수 있습니다.

6.2.2.3, Nacos 구성

그림과 같이 중국어가 아닌 디렉토리에 이 패키지의 압축을 풉니다.
여기에 이미지 설명 삽입

디렉토리 설명:

  • 빈: 시작 스크립트
  • conf: 구성 파일

nacos의 conf 디렉토리에 들어가 구성 파일 cluster.conf.example을 수정하고 이름을 cluster.conf로 바꿉니다.

그런 다음 콘텐츠를 추가합니다.

127.0.0.1:8845
127.0.0.1.8846
127.0.0.1.8847

그런 다음 application.properties 파일을 수정하고 데이터베이스 구성을 추가합니다.

spring.datasource.platform=mysql

db.num=1

db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=123

6.2.2.4, 시작

nacos 폴더를 세 번 복사하고 이름을 nacos1, nacos2, nacos3로 지정합니다.

그런 다음 세 개의 폴더에서 각각 application.properties를 수정합니다.

나코스1:

server.port=8845

나코스2:

server.port=8846

나코스3:

server.port=8847

그런 다음 각각 3개의 nacos 노드를 시작합니다.

startup.cmd

6.2.2.5, nginx 리버스 프록시

nginx 설치 패키지를 찾아 중국어가 아닌 디렉토리에 압축을 풉니다.

conf/nginx.conf 파일을 수정합니다. 구성은 다음과 같습니다.

upstream nacos-cluster {
    server 127.0.0.1:8845;
	server 127.0.0.1:8846;
	server 127.0.0.1:8847;
}

server {
    listen       80;
    server_name  localhost;

    location /nacos {
        proxy_pass http://nacos-cluster;
    }
}

그런 다음 브라우저에서 http://localhost/nacos를 방문하십시오.

코드의 application.yml 파일 구성은 다음과 같습니다.

spring:
  cloud:
    nacos:
      server-addr: localhost:80 # Nacos地址

6.2.2.6 최적화

  • 실제 배포 시 리버스 프록시 역할을 하는 nginx 서버에 대한 도메인 이름을 설정해야 나중에 서버를 마이그레이션할 경우 nacos 클라이언트의 구성을 변경할 필요가 없습니다.

  • Nacos의 각 노드는 재해 복구 및 격리를 위해 여러 개의 서로 다른 서버에 배포되어야 합니다.

요약하다:

클러스터 구성 단계:

  • MySQL 클러스터 구축 및 데이터베이스 테이블 초기화
  • 나코스 다운로드 및 압축 해제
  • 클러스터 구성(노드 정보), 데이터베이스 구성 수정
  • 여러 nacos 노드를 개별적으로 시작
  • nginx 리버스 프록시

세븐, 가짜 원격 호출

먼저 RestTemplate을 사용하여 원격 호출을 시작하는 데 사용한 코드를 살펴보겠습니다.
여기에 이미지 설명 삽입

다음과 같은 문제가 있습니다.

• 낮은 코드 가독성 및 일관되지 않은 프로그래밍 경험

• 복잡한 매개변수가 포함된 URL은 유지 관리가 어렵습니다.

Feign은 선언적 http 클라이언트, 공식 주소: https://github.com/OpenFeign/feign

그 역할은 http 요청 전송을 우아하게 구현하고 위에서 언급한 문제를 해결하는 데 도움을 주는 것입니다.

7.1, Feign이 RestTemplate을 대체함

Fegin을 사용하는 단계는 다음과 같습니다.

7.1.1 종속성 소개

order-service 서비스의 pom 파일에 feign 종속성을 도입합니다.

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

7.1.2 주석 추가

Feign의 기능을 활성화하려면 order-service의 시작 클래스에 주석을 추가하십시오.

여기에 이미지 설명 삽입

7.1.3, Feign 클라이언트 작성

다음 콘텐츠를 사용하여 order-service에서 새 인터페이스를 만듭니다.

@FeignClient("userservice")
public interface UserClient {
    
    
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}

이 클라이언트는 주로 SpringMVC 주석을 기반으로 다음과 같은 원격 호출 정보를 선언합니다.

  • 서비스 이름: userservice
  • 요청 방법: GET
  • 요청 경로: /user/{id}
  • 요청 매개변수: 긴 ID
  • 반환 값 유형: 사용자

이러한 방식으로 Feign은 RestTemplate을 사용하여 직접 http 요청을 보내지 않고도 http 요청을 보낼 수 있도록 도와줍니다.

7.1.4 테스트

order-service의 OrderService 클래스에서 queryOrderById 메서드를 수정하고 RestTemplate 대신 Feign 클라이언트를 사용합니다.

여기에 이미지 설명 삽입

더 고급스러워 보이지 않나요?

7.1.5 요약

Feign을 사용하는 단계:

① 의존성 도입

② @EnableFeignClients 주석 추가

③ FeignClient 인터페이스 작성

④ RestTemplate 대신 FeignClient에 정의된 메소드 사용

7.2, 맞춤형 구성

Feign은 다음 표와 같이 많은 사용자 지정 구성을 지원할 수 있습니다.

유형 효과 설명하다
feign.Logger.Level 로그 수준 수정 NONE, BASIC, HEADERS, FULL의 네 가지 레벨을 포함합니다.
feign.codec.Decoder 응답 결과 파서 json 문자열을 Java 객체로 구문 분석하는 것과 같은 http 원격 호출 결과 구문 분석
feign.codec.Encoder 요청 매개변수 인코딩 http 요청을 통해 전송하기 위한 인코딩 요청 매개변수
척. 계약 지원되는 주석 형식 기본값은 SpringMVC의 주석입니다.
척. 재시도자 실패 재시도 메커니즘 요청 실패에 대한 재시도 메커니즘, 기본값은 아니요이지만 리본의 재시도가 사용됩니다.

일반적인 상황에서는 기본값이면 충분하며 사용자 지정하려는 경우 기본 Bean을 재정의하기 위해 사용자 정의 @Bean을 생성하기만 하면 됩니다.

다음은 로그를 예로 사용하여 구성을 사용자 정의하는 방법을 보여줍니다.

7.2.1 구성 파일 방식

구성 파일을 기반으로 feign의 로그 수준을 수정하면 단일 서비스를 대상으로 할 수 있습니다.

feign:  
  client:
    config: 
      userservice: # 针对某个微服务的配置
        loggerLevel: FULL #  日志级别 

모든 서비스를 대상으로 지정할 수도 있습니다.

feign:  
  client:
    config: 
      default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
        loggerLevel: FULL #  日志级别 

로그 수준은 네 가지 유형으로 나뉩니다.

  • NONE: 로그 정보를 기록하지 않으며 기본값입니다.
  • BASIC: 요청 방법, URL, 응답 상태 코드 및 실행 시간만 기록
  • HEADERS: BASIC을 기반으로 요청 및 응답의 헤더 정보를 추가로 기록
  • 전체: 헤더 정보, 요청 본문 및 메타데이터를 포함하여 모든 요청 및 응답의 세부 정보를 기록합니다.

7.2.2, 자바 코드 방식

Java 코드를 기반으로 로그 수준을 수정하고 먼저 클래스를 선언한 다음 Logger.Level 개체를 선언할 수도 있습니다.

public class DefaultFeignConfiguration  {
    
    
    @Bean
    public Logger.Level feignLogLevel(){
    
    
        return Logger.Level.BASIC; // 日志级别为BASIC
    }
}

전역적으로 적용 하려면 시작 클래스의 @EnableFeignClients 주석에 넣으십시오.

@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class) 

로컬로 유효한 경우 해당 @FeignClient 주석에 넣으십시오.

@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration .class) 

요약하다:

Feign의 로그 구성:

  • 첫 번째 방법은 feign.client.config.xxx.loggerLevel 파일을 구성하는 것입니다.

    • xxx가 기본값이면 전역을 의미합니다.
    • xxx가 userservice와 같은 서비스 이름인 경우 서비스를 나타냅니다.
  • 두 번째 방법은 Java 코드에서 Logger.Level Bean을 구성하는 것입니다.

    • @EnableFeignClients 주석에 선언된 경우 전역을 나타냅니다.
    • @FeignClient 주석에 선언된 경우 서비스를 나타냅니다.

7.3, 위장 사용 최적화

Feign의 맨 아래 계층은 http 요청을 시작하고 다른 프레임워크에 의존합니다. 기본 클라이언트 구현에는 다음이 포함됩니다.

  • URLConnection: 기본 구현, 연결 풀링을 지원하지 않음

  • Apache HttpClient: 연결 풀 지원

  • OKHttp: 연결 풀 지원

따라서 Feign의 성능 최적화에는 주로 다음이 포함됩니다.

  • 기본 URLConnection 대신 연결 풀 사용
  • 로그 수준, 가급적이면 기본 또는 없음

여기서는 Apache의 HttpClient를 사용하여 시연합니다.

7.3.1 종속성 소개

order-service의 pom 파일에 Apache의 HttpClient 종속성을 도입합니다.

<!--httpClient的依赖 -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

7.3.2, 연결 풀 구성

order-service의 application.yml에 구성을 추가합니다.

feign:
  client:
    config:
      default: # default全局的配置
        loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
  httpclient:
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数
    max-connections-per-route: 50 # 每个路径的最大连接数

요약하다

  • 기본을 로그 수준으로 사용하십시오.

  • URLConnection 대신 HttpClient 또는 OKHttp 사용

    • feign-httpClient 종속성 도입

    • 구성 파일은 httpClient 기능을 활성화하고 연결 풀 매개변수를 설정합니다.

7.4 모범 사례

소위 최근 관행은 사용 과정에서 요약된 경험, 이를 사용하는 가장 좋은 방법을 말합니다.

자가 학습 관찰에 따르면 Feign의 클라이언트는 서비스 공급자의 컨트롤러 코드와 매우 유사합니다.

가짜 클라이언트:

여기에 이미지 설명 삽입

사용자 컨트롤러:

여기에 이미지 설명 삽입

이 반복되는 코딩을 단순화할 수 있는 방법이 있습니까?

7.4.1 상속 방법

상속을 통해 동일한 코드를 공유할 수 있습니다.

1) API 인터페이스를 정의하고, 정의 메소드를 사용하고, SpringMVC 주석을 기반으로 명령문을 작성하십시오.

2) Feign 클라이언트와 컨트롤러 모두 인터페이스를 통합합니다.
여기에 이미지 설명 삽입

이점:

  • 단순한
  • 코드 공유

결점:

  • 서비스 제공자와 서비스 소비자는 밀접하게 연결되어 있습니다.

  • 매개변수 목록의 주석 매핑은 상속되지 않으므로 메서드, 매개변수 목록 및 주석은 Controller에서 다시 선언해야 합니다.

7.4.2 추출 방법

Feign의 Client를 독립된 모듈로 추출하고 인터페이스와 관련된 POJO와 기본 Feign 구성을 이 모듈에 넣어 모든 소비자에게 제공한다.

예를 들어 UserClient, User, Feign의 기본 구성은 모두 feign-api 패키지로 추출되며 이 종속성 패키지를 참조하여 모든 마이크로 서비스를 직접 사용할 수 있습니다.

여기에 이미지 설명 삽입

요약하다:

Feign의 모범 사례:

  • 컨트롤러와 FeignClient가 동일한 인터페이스를 상속하도록 합니다.
  • 모든 소비자가 사용할 수 있도록 FeignClient, POJO 및 Feign의 기본 구성을 하나의 프로젝트로 정의합니다.

7.4.3 추출 기반 모범 사례 구현

7.4.3.1 추출

먼저 feign-api라는 모듈을 만듭니다.

feign-api에서 feign의 스타터 종속성을 도입합니다.

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

그러면 order-service에 작성된 UserClient, User, DefaultFeignConfiguration이 모두 feign-api 프로젝트에 복사됩니다.

7.4.3.2 주문 서비스에서 feign-api 사용

먼저 order-service에서 UserClient, User, DefaultFeignConfiguration과 같은 클래스나 인터페이스를 삭제합니다.

order-service의 pom 파일에서 feign-api의 종속성을 소개합니다.

<dependency>
    <groupId>cn.test.demo</groupId>
    <artifactId>feign-api</artifactId>
    <version>1.0</version>
</dependency>

order-service에서 위 3가지 컴포넌트와 관련된 package import 부분을 모두 수정하고 feign-api에서 package import로 변경한다.

7.4.3.3, 테스트 재시작

다시 시작한 후 서비스에서 오류를 보고한 것을 발견했습니다.

이것은 UserClient가 이제 cn.test.feign.clients 패키지 아래에 있기 때문입니다.

order-service의 @EnableFeignClients 주석은 동일한 패키지가 아닌 cn.test.order 패키지 아래에 있으며 UserClient를 스캔할 수 없습니다.

7.4.3.4, 스캐닝 패키지 문제 해결

방법 1:

Feign이 검사해야 하는 패키지를 지정합니다.

@EnableFeignClients(basePackages = "cn.test.feign.clients")

방법 2:

로드해야 하는 클라이언트 인터페이스를 지정합니다.

@EnableFeignClients(clients = {
    
    UserClient.class})

다른 패키지의 FeignClient를 가져오는 방법에는 두 가지가 있습니다.

  • @EnableFeignClients 주석에 basePackages를 추가하여 FeignClient가 있는 패키지를 지정합니다.
  • @EnableFeignClients 주석에 클라이언트를 추가하여 특정 FeignClient의 바이트코드를 지정합니다.

요약하다:

모범 사례 방법 2를 구현하는 단계는 다음과 같습니다.

  • 먼저 feign-api라는 모듈을 만든 다음 feign의 스타터 종속성을 도입합니다.
  • order-service에 작성된 UserClient, User, DefaultFeignConfiguration을 feign-api 프로젝트에 복사합니다.
  • order-service에서 feign-api의 종속성 도입
  • order-service에서 위 3가지 컴포넌트와 관련된 import 부분을 모두 수정하고 feign-api에서 package를 import하도록 변경한다.
  • 테스트 재시작

8. 게이트웨이 서비스 게이트웨이

Spring Cloud Gateway는 Spring 5.0, Spring Boot 2.0 및 Project Reactor 및 기타 반응 프로그래밍 및 이벤트 흐름 기술을 기반으로 개발된 게이트웨이인 Spring Cloud의 새로운 프로젝트로 간단하고 효과적인 통합 API 경로 관리 방법을 제공하는 것을 목표로 합니다.

8.1 게이트웨이가 필요한 이유

게이트웨이는 우리 서비스의 문지기이자 모든 마이크로서비스의 통합 입구입니다.

게이트웨이의 핵심 기능적 특성 :

  • 요청 라우팅
  • 액세스 제어
  • 제한

아키텍처 다이어그램:

[외부 링크 이미지 전송 실패, 소스 사이트에 거머리 방지 메커니즘이 있을 수 있으므로 이미지를 저장하고 직접 업로드하는 것이 좋습니다(img-jD806LhV-1681478872549)(assets/image-20210714210131152.png)]

액세스 제어 : 게이트웨이는 마이크로 서비스의 진입점으로서 사용자가 요청에 적합한지 여부를 확인하고 그렇지 않은 경우 가로채야 합니다.

라우팅 및 로드 밸런싱 : 모든 요청은 게이트웨이를 먼저 통과해야 하지만 게이트웨이는 비즈니스를 처리하지 않고 특정 규칙에 따라 요청을 마이크로 서비스로 전달하며 이 프로세스를 라우팅이라고 합니다. 물론 라우팅 대상 서비스가 여러 개인 경우 부하 분산도 필요하다.

전류 제한 : 요청 트래픽이 너무 높으면 게이트웨이는 다운스트림 마이크로 서비스가 허용할 수 있는 속도에 따라 요청을 해제하여 과도한 서비스 압력을 방지합니다.

Spring Cloud에는 두 가지 유형의 게이트웨이 구현이 있습니다.

  • 게이트웨이

Zuul은 Servlet 기반 구현이며 차단 프로그래밍에 속합니다. Spring Cloud Gateway는 Spring 5에서 제공하는 WebFlux를 기반으로 반응형 프로그래밍을 구현한 것으로 성능이 더 좋습니다.

요약하다:

게이트웨이의 역할:

  • 사용자 요청에 대한 ID 인증 및 권한 확인 수행
  • 사용자 요청을 마이크로서비스로 라우팅하고 로드 밸런싱 구현
  • 사용자 요청 제한

8.2, 게이트웨이 빠른 시작

다음으로 게이트웨이의 기본 라우팅 기능을 시연합니다. 기본 단계는 다음과 같습니다.

  1. SpringBoot 프로젝트 게이트웨이 생성 및 게이트웨이 종속성 도입
  2. 시작 클래스 작성
  3. 기본 구성 및 라우팅 규칙 작성
  4. 테스트를 위해 게이트웨이 서비스 시작

8.2.1 게이트웨이 서비스 생성 및 종속성 도입

서비스를 만들고 종속성을 도입합니다.

<!--网关-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

8.2.2 스타트업 클래스 작성하기

@SpringBootApplication
public class GatewayApplication {
    
    

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

8.2.3 기본 구성 및 라우팅 규칙 작성

다음 콘텐츠로 application.yml 파일을 만듭니다.

server:
  port: 10010 # 网关端口
spring:
  application:
    name: gateway # 服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos地址
    gateway:
      routes: # 网关路由配置
        - id: user-service # 路由id,自定义,只要唯一即可
          # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
          uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
          predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
            - Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求

Path규칙과 일치하는 모든 요청을 매개 uri변수로 지정된 주소로 프록시합니다 .

/user/**이 예제에서는 초기 요청을 프록시하고 lb://userservicelb는 로드 밸런싱이며 서비스 이름에 따라 서비스 목록을 가져오고 로드 밸런싱을 실현합니다.

8.2.4, 테스트 재시작

게이트웨이를 다시 시작하고 http://localhost:10010/user/1에 액세스하면 규칙을 준수하고 /user/**요청이 uri: http://userservice/user/1로 전달되고 결과를 얻습니다.

8.2.5 게이트웨이 라우팅 흐름도

전체 액세스 프로세스는 다음과 같습니다.

여기에 이미지 설명 삽입

요약하다:

관문 구성 단계:

  1. 프로젝트 생성, nacos 서비스 검색 및 게이트웨이 종속성 소개

  2. 기본 서비스 정보, nacos 주소, 라우팅을 포함하여 application.yml 구성

라우팅 구성에는 다음이 포함됩니다.

  1. 경로 ID: 경로의 고유 식별자

  2. 라우팅 대상(uri): 라우팅의 대상 주소, http는 고정 주소, lb는 서비스 이름에 따른 로드 밸런싱을 나타냅니다.

  3. 라우팅 어설션(술어): 라우팅을 판단하기 위한 규칙,

  4. 경로 필터(필터): 요청 또는 응답 처리

8.3 어설션 팩토리

게이트웨이 경로에서 구성할 수 있는 콘텐츠는 다음과 같습니다.

  • 경로 ID: 경로의 고유 식별자
  • uri: 라우팅 대상, lb 및 http 모두 지원
  • 술어: 요청이 요구 사항을 충족하는지 여부를 결정하기 위한 라우팅 어설션, 요구 사항을 충족하면 라우팅 대상으로 전달됩니다.
  • 필터: 라우팅 필터, 요청 또는 응답 처리

구성 파일에 작성하는 어설션 규칙은 문자열일 뿐이며 Predicate Factory에서 읽고 처리하여 라우팅 판단을 위한 조건으로 전환됩니다.

예를 들어 Path=/user/**는 경로에 따라 일치합니다. 이 규칙은 다음에 의해 결정됩니다.

org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory클래스

처리를 위해 Spring Cloud Gateway에는 다음과 같은 12개 이상의 어설션 팩토리가 있습니다.

이름 설명하다
후에 특정 시점 이후의 요청입니다. - 변경 후=2037-01-20T17:42:47.789-07:00[미국/덴버]
전에 특정 시점 이전의 요청입니다. - 이전=2031-04-13T15:14:47.433+08:00[아시아/상하이]
사이 특정 두 시점 이전의 요청입니다. - 사이=2037-01-20T17:42:47.789-07:00[미국/덴버], 2037-01-21T17:42:47.789-07:00[미국/덴버]
쿠키 요청에는 특정 쿠키가 포함되어야 합니다. - 쿠키=초콜릿, ch.p
머리글 요청에는 특정 헤더가 포함되어야 합니다. - 헤더=X-요청-Id, \d+
주인 요청은 특정 호스트(도메인 이름)에 대한 액세스여야 합니다. - 호스트= .somehost.org, .anotherhost.org
방법 요청 방법을 지정해야 합니다. - 방법=GET,POST
요청 경로는 지정된 규칙을 준수해야 합니다. - 경로=/red/{세그먼트},/파란색/**
질문 요청 매개변수는 지정된 매개변수를 포함해야 합니다. - 검색어=이름, Jack 또는 - 검색어=이름
원격 주소 요청자의 IP는 지정된 범위에 있어야 합니다. - 원격주소=192.168.1.1/24
무게 웨이트 처리

Path의 라우팅 엔지니어링만 마스터하면 됩니다.

8.4 필터 공장

GatewayFilter는 게이트웨이에 제공되는 필터로, 게이트웨이에 들어오는 요청과 마이크로 서비스가 반환하는 응답을 처리할 수 있습니다.

여기에 이미지 설명 삽입

8.4.1 라우팅 필터의 종류

Spring은 31개의 서로 다른 경로 필터 팩토리를 제공합니다. 예를 들어:

이름 설명하다
추가 요청 헤더 현재 요청에 요청 헤더 추가
RemoveRequestHeader 요청에서 요청 헤더 제거
추가 응답 헤더 응답 결과에 응답 헤더 추가
응답 헤더 제거 응답 결과에서 응답 헤더가 제거되었습니다.
RequestRateLimiter 요청의 양을 제한하다

8.4.2 요청 헤더 필터

AddRequestHeader를 예로 들어 설명하겠습니다.

요구 사항 : userservice를 입력하는 모든 요청에 ​​요청 헤더를 추가합니다. Truth=test is freaking awesome!

게이트웨이 서비스의 application.yml 파일을 수정하고 경로 필터링을 추가하기만 하면 됩니다.

spring:
  cloud:
    gateway:
      routes:
      - id: user-service 
        uri: lb://userservice 
        predicates: 
        - Path=/user/** 
        filters: # 过滤器
        - AddRequestHeader=Truth, test is freaking awesome! # 添加请求头

현재 필터는 userservice 경로 아래에 작성되므로 userservice 액세스 요청에만 유효합니다.

8.4.3, 기본 필터

모든 경로에 적용하려면 default 아래에 필터 팩토리를 작성할 수 있습니다. 형식은 다음과 같습니다.

spring:
  cloud:
    gateway:
      routes:
      - id: user-service 
        uri: lb://userservice 
        predicates: 
        - Path=/user/**
      default-filters: # 默认过滤项
      - AddRequestHeader=Truth, test is freaking awesome! 

8.4.4 요약

필터의 역할은 무엇입니까?

① 요청 헤더 추가 등 라우팅 요청 또는 응답 처리

② 해당 경로에 설정된 필터는 현재 경로의 요청에 대해서만 적용됩니다.

defaultFilters의 역할은 무엇입니까?

① 모든 경로에 효과적인 필터

8.5 글로벌 필터

上次学习的过滤器,网关提供了31种,但每一种过滤器的作用都是固定的。如果我们希望拦截请求,做自己的业务逻辑则没办法实现。

8.5.1、全局过滤器作用

全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样。区别在于GatewayFilter通过配置定义,处理逻辑是固定的;而GlobalFilter的逻辑需要自己写代码实现。

定义方式是实现GlobalFilter接口。

public interface GlobalFilter {
    
    
    /**
     *  处理当前请求,有必要的话通过{@link GatewayFilterChain}将请求交给下一个过滤器处理
     *
     * @param exchange 请求上下文,里面可以获取Request、Response等信息
     * @param chain 用来把请求委托给下一个过滤器 
     * @return {@code Mono<Void>} 返回标示当前过滤器业务结束
     */
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}

在filter中编写自定义逻辑,可以实现下列功能:

  • 登录状态判断
  • 权限校验
  • 请求限流等

8.5.2、自定义全局过滤器

需求:定义全局过滤器,拦截请求,判断请求的参数是否满足下面条件:

  • 参数中是否有authorization,

  • authorization参数值是否为admin

如果同时满足则放行,否则拦截

实现:

在gateway中定义一个过滤器:

@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter {
    
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
    
        // 1.获取请求参数
        MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
        // 2.获取authorization参数
        String auth = params.getFirst("authorization");
        // 3.校验
        if ("admin".equals(auth)) {
    
    
            // 放行
            return chain.filter(exchange);
        }
        // 4.拦截
        // 4.1.禁止访问,设置状态码
        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
        // 4.2.结束处理
        return exchange.getResponse().setComplete();
    }
}

全局过滤器的作用是什么?

  • 对所有路由都生效的过滤器,并且可以自定义处理逻辑

实现全局过滤器的步骤?

  • 实现GlobalFilter接口
  • 添加@Order注解或实现Ordered接口
  • 编写处理逻辑

8.5.3、过滤器执行顺序

请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter

请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,合并到一个过滤器链(集合)中,排序后依次执行每个过滤器:

여기에 이미지 설명 삽입

排序的规则是什么呢?

  • 每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前
  • GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order值,由我们自己指定
  • 路由过滤器和defaultFilter的order由Spring指定,默认是按照声明顺序从1递增。
  • 当过滤器的order值一样时,会按照 defaultFilter > 路由过滤器 > GlobalFilter的顺序执行。

자세한 내용은 소스 코드를 볼 수 있습니다.

org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters()방법은 defaultFilters를 먼저 불러온 다음 특정 경로의 필터를 불러온 다음 병합하는 것입니다.

org.springframework.cloud.gateway.handler.FilteringWebHandler#handle()메서드는 전역 필터를 로드하고 이전 필터와 병합한 후 순서에 따라 정렬하고 필터 체인을 구성합니다.

요약:
라우팅 필터, defaultFilter 및 전역 필터의 실행 순서는?

  • 주문 값이 작을수록 우선 순위가 높아집니다.
  • 순서 값이 같으면 defaultFilter가 먼저, 로컬 라우팅 필터, 마지막으로 전역 필터가 순서입니다.

8.6 도메인 간 문제

8.6.1 도메인 간 문제란 무엇인가

교차 도메인: 일치하지 않는 도메인 이름은 주로 다음을 포함하는 교차 도메인입니다.

  • 다른 도메인 이름: www.taobao.com 및 www.taobao.org 및 www.jd.com 및 miaosha.jd.com

  • 동일한 도메인 이름, 다른 포트: localhost:8080 및 localhost8081

교차 도메인 문제: 브라우저는 요청의 발신자가 서버와 교차 도메인 ajax 요청을 하는 것을 금지하고 브라우저에서 요청을 가로챕니다.

솔루션: CORS, 이것은 이전에 배웠어야 하므로 여기에서 반복하지 않겠습니다. 모르는 친구는 https://www.ruanyifeng.com/blog/2016/04/cors.html에서 확인할 수 있습니다.

8.6.2 도메인 간 문제 시뮬레이션

localhost:8090에서 localhost:10010에 액세스하면 포트가 다르며 분명히 도메인 간 요청입니다.

8.6.3 도메인 간 문제 해결

게이트웨이 서비스의 application.yml 파일에서 다음 구성을 추가합니다.

spring:
  cloud:
    gateway:
      # 。。。
      globalcors: # 全局的跨域处理
        add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
        corsConfigurations:
          '[/**]':
            allowedOrigins: # 允许哪些网站的跨域请求 
              - "http://localhost:8090"
            allowedMethods: # 允许的跨域ajax的请求方式
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*" # 允许在请求中携带的头信息
            allowCredentials: true # 是否允许携带cookie
            maxAge: 360000 # 这次跨域检测的有效期

8.7 제한 필터

전류 제한: 애플리케이션 서버의 요청을 제한하여 너무 많은 요청으로 인한 서버의 과부하 또는 다운타임을 방지합니다. 두 가지 일반적인 전류 제한 알고리즘이 있습니다.

  • 창 카운터 알고리즘, 슬라이딩 창 카운터 알고리즘을 포함한 카운터 알고리즘
  • 새는 양동이
  • 토큰 버킷 알고리즘(토큰 버킷)

여기에 이미지 설명 삽입

여기에 이미지 설명 삽입

여기에 이미지 설명 삽입

Supongo que te gusta

Origin blog.csdn.net/shuai_h/article/details/130140455
Recomendado
Clasificación