마이크로서비스 풀 스택: 심층적인 핵심 구성 요소 및 개발 기술


간단히 말해서 마이크로서비스는 독립적으로 실행될 수 있고 종종 비즈니스 기능을 중심으로 구축되는 소규모 자율 서비스 세트로 애플리케이션을 구성하는 설계 접근 방식입니다. 이러한 서비스는 서로 독립적으로 실행되며 잘 정의된 API를 통해 통신합니다. 모놀리식 애플리케이션에 비해 마이크로서비스 아키텍처는 더 큰 유연성과 확장성을 제공하므로 팀이 독립적으로 서비스를 개발, 배포 및 확장할 수 있습니다.

이미지-20230915114824429

1. 서비스 등록 및 검색

마이크로서비스 세계에서 서비스 등록 및 검색은 각 독립 서비스가 다른 서비스를 찾고 상호 작용할 수 있도록 하는 핵심 메커니즘입니다. 애플리케이션의 크기와 복잡성이 증가함에 따라 이러한 서비스 간의 상호 작용을 명확하게 이해하고 관리하는 것이 중요해졌습니다.

1.1 클라이언트 등록(ZooKeeper)

분산 시스템의 견고한 초석인 Apache ZooKeeper는 업계에서 많은 존경을 받았습니다. 다양한 마이크로서비스 프레임워크를 포함한 많은 분산 시스템은 ZooKeeper를 사용하여 이름 지정, 구성 관리, 그룹화 서비스 및 분산 동기화와 같은 중요한 서비스를 제공합니다. 하지만 여기서는 마이크로서비스 아키텍처에서 클라이언트 레지스트리로서의 애플리케이션에 중점을 둘 것입니다.

ZooKeeper 소개
ZooKeeper 다운로드 링크
ZooKeeper는 원래 Yahoo에서 만들어졌지만 나중에 Apache의 최상위 프로젝트가 되었습니다. 이는 분산 애플리케이션용으로 설계되었으며 부분적인 오류가 발생하는 경우에도 분산 애플리케이션이 계속 작동할 수 있는 일련의 서비스를 제공합니다. 이는 소형 ​​컴퓨터 노드를 연결하여 강력한 분산 프레임워크를 형성하도록 설계된 ZooKeeper의 핵심 아키텍처를 통해 달성됩니다.

ZooKeeper의 데이터 모델

ZooKeeper의 데이터 구조는 디렉터리와 파일로 구성된 분산 파일 시스템과 매우 유사합니다. 하지만 ZooKeeper에서는 각 노드를 "znode"라고 합니다. 각 znode는 데이터를 저장할 수 있으며 하위 노드를 가질 수 있습니다.

마이크로서비스가 자신을 등록하려고 하면 ZooKeeper에서 자체적으로 znode를 생성합니다. 일반적으로 이 znode는 IP 주소, 포트 및 기타 메타데이터와 같은 서비스에 대한 주요 정보를 저장합니다.

서비스 등록 과정

  1. 시작 및 연결 : 마이크로서비스가 시작되면 ZooKeeper 클러스터에 대한 연결을 초기화합니다.
  2. znode 생성 : 마이크로서비스는 일반적으로 서비스 이름을 기반으로 지정된 경로에 znode를 생성합니다.
  3. 데이터 저장 : 서비스는 이 znode에 메타데이터를 저장합니다. 이 메타데이터에는 IP 주소, 포트, 버전 번호, 시작 시간 등이 포함될 수 있습니다.
  4. 주기적 하트비트 : ZooKeeper에게 서비스가 여전히 활성 상태임을 알리기 위해 서비스는 주기적으로 하트비트를 해당 z노드에 보냅니다.
  5. 로그아웃 : 서비스가 종료되면 ZooKeeper에서 해당 znode를 삭제합니다.

[ZooKeeper 클라이언트 등록]

import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;

// 初始化ZooKeeper客户端并注册服务
public class ServiceRegistry {
    
    
    private static final String ZK_ADDRESS = "localhost:2181";
    private ZooKeeper zooKeeper;

    public ServiceRegistry() throws Exception {
    
    
        // 连接ZooKeeper
        this.zooKeeper = new ZooKeeper(ZK_ADDRESS, 5000, watchedEvent -> {
    
    });
    }

    // 注册服务
    public void registerService(String serviceName, String serviceInfo) throws Exception {
    
    
        String path = "/services/" + serviceName;
        if (zooKeeper.exists(path, false) == null) {
    
    
            zooKeeper.create(path, serviceInfo.getBytes(),
            ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        }
    }
}

// 使用方法:
ServiceRegistry registry = new ServiceRegistry();
registry.registerService("myService", "serviceInstanceInfo");

ZooKeeper의 일관성 모델

ZooKeeper는 "Zab"이라는 프로토콜을 사용하여 데이터의 일관성을 보장합니다. Zab 프로토콜은 모든 쓰기 작업이 순서대로 이루어지도록 보장합니다. 즉, 여러 노드의 모든 작업이 동일한 순서로 수행된다는 의미입니다.

안전

ZooKeeper는 관리자가 어떤 클라이언트가 어떤 작업을 수행할 수 있는지 제어할 수 있는 ACL 기반 보안 모델을 제공합니다. 이는 악의적이거나 잘못 구성된 클라이언트가 시스템에 해를 끼치는 것을 방지하는 데 유용합니다.

이미지-20230915111318244

요약하다

분산 시스템의 핵심 구성 요소인 ZooKeeper는 마이크로서비스를 위한 안정적이고 가용성이 높은 서비스 등록 플랫폼을 제공합니다. 내부 작동 방식을 이해함으로써 이를 활용하여 마이크로서비스 아키텍처를 강화할 수 있습니다.

1.2. 제3자 등록(독립 서비스 등록기관)

마이크로서비스 아키텍처의 인기가 높아짐에 따라 각 서비스를 직접 등록하는 것은 때로는 복잡하고 시간이 많이 걸릴 수 있습니다. 따라서 이러한 서비스를 관리하는 데 도움을 주기 위해 제3자 서비스 등록 메커니즘, 즉 독립적인 서비스 등록자를 도입할 필요가 있습니다.

제3자 서비스 등록기관이란 무엇입니까?

타사 서비스 Registrar는 마이크로서비스와 서비스 등록 센터 사이의 중간 계층입니다. 마이크로서비스를 자동으로 감지, 등록 및 등록 취소할 수 있습니다. 이 접근 방식은 각 마이크로서비스에 직접 의존하여 등록하는 대신 관리 및 모니터링을 위한 중앙 집중식 위치를 제공합니다.

제3자 등록이 필요한 이유는 무엇입니까?

  1. 자동화된 관리 : 마이크로서비스가 증가함에 따라 서비스 인스턴스를 수동으로 등록, 업데이트 및 등록 취소하는 것이 번거로울 수 있습니다. 타사 등록을 통해 이러한 작업을 자동으로 처리할 수 있습니다.
  2. 중앙 집중식 모니터링 : 타사 레지스트리를 사용하여 개발자와 운영 팀은 한 곳에서 모든 서비스의 상태를 모니터링할 수 있습니다.
  3. 보안 강화 : 모든 등록 및 등록 취소 작업이 중앙 지점을 거치기 때문에 어떤 서비스를 등록할 수 있는지 더 효과적으로 제어할 수 있어 악성 서비스 등록을 방지할 수 있습니다.

제3자 등록 작동 방식

  1. 서비스 검색 : 등록 기관은 정기적으로 네트워크나 특정 엔드포인트를 검색하여 새로운 서비스 인스턴스를 찾습니다.
  2. 서비스 등록 : 새로운 서비스 인스턴스가 발견되면 Registrar는 이를 자동으로 서비스 등록 센터에 등록합니다.
  3. 상태 점검 : 등록자는 각 서비스 인스턴스의 상태를 정기적으로 확인합니다. 서비스 인스턴스가 더 이상 정상이 아니거나 연결할 수 없는 것으로 확인되면 서비스 레지스트리에서 인스턴스를 등록 취소합니다.
  4. 메타데이터 관리 : 추가 구성이 필요한 서비스의 경우 등록 기관은 이러한 메타데이터를 저장하고 관리하여 각 서비스가 예상대로 실행되도록 할 수 있습니다.

사용되는 장면

다음은 타사 서비스 등록 기관이 필요할 수 있는 몇 가지 시나리오입니다.

  • 대규모 배포 : 수백 또는 수천 개의 마이크로서비스 인스턴스가 있는 경우 각 인스턴스를 수동으로 관리하는 것은 비현실적입니다.
  • 동적 환경 : 클라우드 환경에서는 서비스 인스턴스가 자주 시작되고 종료될 수 있습니다. 타사 등록을 통해 서비스 레지스트리가 항상 최신 상태로 유지됩니다.
  • 높은 보안 요구 사항 : 높은 보안 환경에서는 신뢰할 수 있는 서비스만 등록할 수 있도록 보장해야 할 수도 있습니다.

과제와 고려사항

  1. 네트워크 오버헤드 : 서비스 인스턴스의 상태를 자주 확인해야 하므로 많은 양의 네트워크 트래픽이 발생할 수 있습니다.
  2. 단일 실패 지점 : 등록자 자체가 실패하면 모든 서비스 등록 및 등록 취소 작업에 영향을 미칠 수 있습니다.

이미지-20230915111346338

타사 서비스 Registrar를 사용하면 마이크로서비스의 관리 및 모니터링을 크게 단순화할 수 있습니다. 그러나 적절한 등록자 솔루션을 선택하고 배포하려면 해당 솔루션이 특정 환경의 요구 사항을 충족하는지 확인하기 위한 신중한 계획과 테스트가 필요합니다.

1.3 클라이언트 검색

마이크로서비스 세계에서 서비스 검색은 핵심 구성 요소 중 하나입니다. 서비스가 다른 서비스와 상호 작용해야 하는 경우 먼저 다른 서비스의 위치를 ​​알아야 합니다. 이것이 서비스 검색의 목적입니다. 클라이언트 검색 모드에서 호출 서비스는 상호 작용해야 하는 서비스 인스턴스를 파악하는 역할을 합니다.

클라이언트 검색이란 무엇입니까?

클라이언트 검색은 클라이언트 또는 소비자 서비스가 네트워크에서 사용 가능한 서비스 인스턴스를 결정한 다음 인스턴스와 직접 통신하는 서비스 검색 패턴입니다. 이는 API 게이트웨이 또는 로드 밸런서가 어떤 서비스 인스턴스와 통신해야 하는지 결정하는 서버 측 검색 모델과 대조됩니다.

클라이언트 검색 작동 방식

  1. 등록 : 서비스 인스턴스가 시작되어 사용 가능해질 때마다 해당 주소를 서비스 레지스트리에 등록합니다.
  2. 쿼리 : 클라이언트가 서비스와 통신해야 할 때 먼저 서비스 등록 센터에 쿼리하여 사용 가능한 모든 서비스 인스턴스 목록을 얻습니다.
  3. 선택 : 클라이언트는 획득한 서비스 목록 중 하나를 선택하여 통신합니다. 여기에는 일반적으로 라운드 로빈이나 무작위 선택과 같은 일종의 로드 밸런싱이 포함됩니다.
  4. 통신 : 클라이언트는 선택한 서비스 인스턴스와 직접 통신합니다.

이점

  1. 유연성 : 클라이언트는 필요에 따라 자체 로드 밸런싱 전략을 구현할 수 있습니다.
  2. 대기 시간 단축 : 요청을 처리하는 중개 구성 요소(예: API 게이트웨이 또는 로드 밸런서)가 없으므로 통신 대기 시간이 줄어듭니다.

결점

  1. 클라이언트 복잡성 : 각 클라이언트는 서비스 검색 및 로드 밸런싱 논리를 구현해야 합니다.
  2. 일관성 과제 : 모든 클라이언트는 서비스 검색 논리와 정책을 일관되게 업데이트해야 합니다.

클라이언트 검색을 위한 도구 및 기술

Eureka, Consul 및 Zookeeper와 같은 많은 서비스 검색 도구는 클라이언트 검색 모드를 지원합니다.

  1. Eureka : Netflix가 만든 Eureka는 마이크로서비스 아키텍처에서 가장 널리 사용되는 서비스 검색 도구 중 하나입니다. Eureka 클라이언트는 내장된 로드 밸런싱 전략을 제공하며 Spring Cloud와 쉽게 통합될 수 있습니다.
  2. Consul : HashiCorp에서 개발한 Consul은 상태 확인, KV 스토리지 및 여러 데이터 센터를 지원하는 다목적 서비스 검색 솔루션을 제공합니다.
  3. Zookeeper : 앞서 언급했듯이 Zookeeper는 분산 조정 서비스로 서비스 검색에도 자주 사용됩니다.

이미지-20230915111430618

클라이언트 검색은 마이크로서비스가 다른 서비스를 찾고 통신할 수 있는 유연하고 지연 시간이 짧은 방법을 제공합니다. 그러나 클라이언트 복잡성도 증가하며 모든 클라이언트에 걸쳐 논리적 및 정책 일관성이 필요합니다. 클라이언트 측 검색 사용 여부는 특정 요구 사항과 제약 조건에 따라 결정됩니다.

1.4 서버 측 검색

서버 측 검색은 마이크로서비스 아키텍처의 일반적인 서비스 검색 패턴입니다. 클라이언트측 검색과 달리 서버측 검색은 서비스 검색 책임을 클라이언트에서 서버로 옮깁니다.

서버측 검색이란 무엇입니까?

서버 측 검색에서 클라이언트 애플리케이션은 먼저 중앙 로드 밸런서 또는 API 게이트웨이에 서비스 위치를 확인하도록 요청합니다. 이 중앙 구성 요소는 서비스 레지스트리를 쿼리하고 서비스 인스턴스의 위치를 ​​확인한 다음 요청을 해당 서비스 인스턴스로 라우팅합니다.

서버측 검색 작동 방식

  1. 등록 : 클라이언트 검색과 마찬가지로 서비스 인스턴스는 시작 시 서비스 레지스트리에 해당 위치를 등록합니다.
  2. 라우팅된 요청 : 클라이언트는 요청을 서비스 인스턴스로 직접 보내는 대신 중앙 로드 밸런서 또는 API 게이트웨이로 보냅니다.
  3. 서비스 인스턴스 선택 : 로드 밸런서는 서비스 레지스트리를 쿼리하고, 사용 가능한 서비스 인스턴스를 찾고, 요청을 라우팅할 인스턴스를 결정합니다.
  4. 요청 전달 : 로드 밸런서는 클라이언트의 요청을 선택한 서비스 인스턴스로 전달합니다.

[ZooKeeper 서비스 살펴보기]

// 从ZooKeeper中发现服务
public List<String> discoverService(String serviceName) throws Exception {
    
    
    String path = "/services/" + serviceName;
    return zooKeeper.getChildren(path, false);
}

// 使用方法:
List<String> serviceInstances = discoverService("myService");

이점

  1. 단순화된 클라이언트 : 클라이언트 논리는 더 간단하며 중앙 로드 밸런서의 위치만 알면 됩니다.
  2. 중앙 집중식 트래픽 관리 : 트래픽 형태, 라우팅 및 로드 밸런싱 정책을 중앙 위치에서 관리할 수 있습니다.

결점

  1. 지연 시간 증가 : 요청이 추가 점프를 거쳐야 하므로 약간의 지연이 발생할 수 있습니다.
  2. 단일 장애 지점 위험 : 중앙 로드 밸런서나 API 게이트웨이에 문제가 있을 경우 모든 요청이 영향을 받을 수 있습니다.

이미지-20230915111510336

사용되는 장면

서버 측 검색은 모바일 애플리케이션, 타사 개발자 또는 다중 프런트 엔드 인터페이스와 같이 클라이언트 다양성이 높은 환경에 특히 적합합니다.

1.5. 영사

Consul은 HashiCorp에서 개발한 서비스 검색 및 구성 배포 도구입니다. 이는 데이터 센터 전반에 걸쳐 고가용성과 지원을 제공하도록 설계되었습니다.

img

영사 주요 기능

  1. 서비스 검색 : Consul은 애플리케이션이 다른 서비스를 제공 및 검색할 수 있도록 하며 서비스 인스턴스의 상태를 확인하기 위한 상태 확인을 제공합니다.
  2. 키/값 저장소 : 구성 및 동적 서비스 구성을 위한 분산 키/값 저장소입니다.
  3. 다중 데이터 센터 : Consul은 다중 데이터 센터를 지원하므로 대규모 애플리케이션에 이상적입니다.

영사 이용방법

  1. 설치 및 실행 : Consul은 공식 웹사이트에서 다운로드할 수 있는 단일 바이너리 파일입니다. 각 노드에 Consul 에이전트가 있는 에이전트 모드에서 실행됩니다.
  2. 서비스 등록 : 서비스 정의 파일을 정의한 후 consul agent명령어를 이용하여 서비스를 등록할 수 있다.
  3. Health check : Consul은 다양한 방법(HTTP, TCP, 특정 스크립트 실행 등)을 통해 정기적으로 서비스 인스턴스의 Health 상태를 확인할 수 있습니다.

Consul과 기타 서비스 검색 도구 비교

Eureka, Zookeeper 및 기타 도구도 서비스 검색 기능을 제공하는 반면 Consul은 다중 데이터 센터 지원 및 키/값 저장소와 같은 몇 가지 고유한 기능을 제공합니다.

1.6. 유레카

Eureka는 Netflix가 오픈소스로 제공하는 서비스 검색 도구로, 특히 클라우드 환경의 대규모 분산 시스템에 적합합니다. 그 이름은 "나는 그것을 발견했다!"라는 뜻의 그리스어에서 유래되었습니다.

유레카의 핵심 구성 요소

  1. 유레카 서버 : 서비스 등록 서비스를 제공합니다. 서비스를 제공하는 모든 클라이언트 애플리케이션은 Eureka에 등록하고 메타데이터 정보를 제공해야 합니다.
  2. 유레카 클라이언트 : 유레카 서버와의 상호 작용을 단순화하는 데 사용되는 Java 클라이언트입니다. 클라이언트에는 로드 밸런서도 내장되어 있습니다.

유레카의 작동 방식

  1. 서비스 등록 : 유레카 클라이언트가 시작되면 자신의 정보를 유레카 서버에 등록하고 주기적으로 하트비트를 보내 계약을 갱신합니다.
  2. 서비스 소비 : 서비스 소비자는 Eureka 서버에서 레지스트리 정보를 가져와 로컬로 캐시합니다. 소비자는 이 정보를 사용하여 서비스 제공자를 찾습니다.
  3. 서비스가 오프라인 상태가 됨 : 클라이언트가 종료되면 Eureka 서버에 레지스트리의 인스턴스를 삭제하라는 요청을 보냅니다.

유레카의 특징

  1. 가용성 : Eureka는 네트워크 문제로 인한 부분적인 장애를 매우 잘 처리합니다. 클라이언트가 네트워크 분할로 인해 서비스에 접속할 수 없는 경우 클라이언트는 서버의 상태를 캐시하고 이 정보를 사용하여 요청을 처리합니다.
  2. 로드 밸런싱 : Eureka 클라이언트에는 서비스 인스턴스에 대한 요청에 대한 로드 밸런싱을 제공할 수 있는 로드 밸런서가 포함되어 있습니다.
  3. Spring Cloud와의 통합 : Eureka는 Spring Cloud와 원활하게 통합될 수 있으므로 Spring Boot 애플리케이션에 이상적입니다.

1.7. 스마트스택

SmartStack은 Airbnb에서 개발한 서비스 검색 도구이며 Nerve와 Synapse라는 두 가지 주요 구성 요소를 기반으로 합니다.

신경 이상

Nerve는 각 서비스 인스턴스에서 실행되도록 설계된 데몬입니다. Zookeeper에 서비스를 등록하는 역할을 담당합니다. 서비스 인스턴스가 비정상이 되면 Nerve는 Zookeeper에서 해당 인스턴스의 등록을 취소해야 합니다.

시냅스

Synapse는 서비스를 검색해야 하는 모든 컴퓨터에서 실행되도록 설계된 또 다른 데몬입니다. Zookeeper에서 주기적으로 서비스 등록 정보를 가져오고 로컬 로드 밸런서(예: HAProxy)의 구성을 업데이트합니다.

스마트스택 기능

  1. 자동 상태 확인 : Nerve와 Synapse가 함께 작동하여 정상적인 서비스 인스턴스만 라우팅되도록 합니다.
  2. 복원력 및 안정성 : SmartStack은 네트워크 파티션이나 기타 장애가 발생하는 경우에도 서비스의 높은 가용성을 보장합니다.
  3. 기존 기술과의 통합 : Zookeeper를 중앙 스토리지로, HAProxy를 로드 밸런서로 사용하면 SmartStack을 기존 기술 스택과 쉽게 통합할 수 있습니다.

1.8. 기타

Etcd는 오픈 소스, 고가용성 분산 키-값 저장소로 주로 공유 구성 및 서비스 검색에 사용됩니다. CoreOS에서 개발한 etcd는 특히 Kubernetes에 안정적인 데이터 스토리지를 제공하기 위해 대규모 클러스터용으로 설계되었습니다.

etcd의 핵심 기능

  1. 일관성 및 고가용성 : Etcd는 Raft 알고리즘을 기반으로 분산 시스템에서 데이터 일관성을 보장합니다.
  2. 분산 잠금 : etcd를 사용하여 분산 시스템에 대한 잠금 메커니즘을 구현합니다.
  3. 모니터링 및 알림 : 구성 변경, 서비스 등록/등록 취소 등의 변경 사항에 대해 키-값 쌍을 모니터링할 수 있습니다.
  4. Simple API : etcd는 간단한 RESTful API를 제공하여 다양한 애플리케이션과 쉽게 통합할 수 있습니다.

기타 이용방법

  1. 설치 및 시작 : etcd의 GitHub 저장소에서 바이너리를 다운로드할 수 있습니다. etcd가 시작된 후 클라이언트 요청 수신이 시작됩니다.
  2. 키-값 작업 : 사용자는 HTTP API 또는 제공된 명령줄 클라이언트를 사용하여 etcdctl키-값 쌍을 설정, 가져오기, 삭제 및 모니터링할 수 있습니다.
  3. 서비스 검색 : etcd에서 서비스 인스턴스는 시작 시 주소와 기타 메타데이터를 키-값 쌍으로 저장합니다. 이러한 서비스가 필요한 클라이언트는 etcd를 쿼리하여 검색할 수 있습니다.

etcd와 다른 서비스 검색 도구 비교

Zookeeper 및 Consul과 같은 도구에 비해 etcd는 더 간단하고 직접적인 API를 제공합니다. Kubernetes와 같은 최신 컨테이너 클러스터의 요구 사항을 충족하도록 설계되었으므로 이 환경에서 사용하기에 매우 적합합니다.

2. API 게이트웨이

마이크로서비스 아키텍처에서 API 게이트웨이는 시스템의 진입점이자 요청 라우팅, API 구성, 로드 밸런싱, 인증, 권한 부여, 보안 등을 담당하는 서버입니다.img

API 게이트웨이가 필요한 이유는 무엇입니까?

API 게이트웨이는 서버이며, 시스템에 진입하는 유일한 노드라고도 할 수 있습니다. 이는 객체 지향 디자인 패턴의 Facade 패턴과 매우 유사합니다. API 게이트웨이는 내부 시스템 아키텍처를 캡슐화하고 다양한 클라이언트에 API를 제공합니다. 또한 인증, 모니터링, 로드 밸런싱, 캐싱, 요청 샤딩 및 관리, 정적 응답 처리 등과 같은 다른 기능도 있을 수 있습니다.

  1. 단일 입구 : 외부 소비자를 위한 통합 API 입구를 제공하여 시스템 내부 구조를 숨깁니다.
  2. API 구성 : 여러 마이크로서비스의 작업을 하나의 복합 작업으로 결합하여 클라이언트와 서버 간의 요청 및 응답 수를 줄입니다.
  3. 로드 밸런싱 : 들어오는 요청을 여러 인스턴스에 분산하여 시스템 확장성과 가용성을 향상시킵니다.
  4. 보안 : 인증, 권한 부여, SSL 처리 등 중앙 집중식 보안 조치.

API 게이트웨이의 공통 기능

  1. 요청 라우팅 : API 요청을 적절한 마이크로서비스로 전달합니다.
  2. 요청/응답 변환 : 클라이언트와 서비스 간의 요청 및 응답 형식을 수정합니다.
  3. API 집계 : 여러 서비스의 데이터와 기능을 하나의 일관된 API로 결합합니다.
  4. 보안 : 속도 제한, 인증 및 권한 부여가 포함됩니다.
  5. 캐싱 : 일반적인 요청에 대한 캐싱을 제공하여 응답 시간과 서비스 로드를 줄입니다.

[API 게이트웨이 기능 예시]

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

// Spring Cloud Gateway的一个简单配置示例
public class ApiGatewayConfiguration {
    
    
    @Bean
    public RouteLocator gatewayRoutes(RouteLocatorBuilder builder) {
    
    
        return builder.routes()
            .route(r -> r.path("/service-api/**")
            .uri("http://localhost:8080/"))
            .build();
    }
}

API 게이트웨이는 요청 전달, 구성 및 프로토콜 변환을 담당합니다. 클라이언트의 모든 요청은 먼저 API 게이트웨이를 통과한 다음 이러한 요청을 해당 마이크로서비스로 라우팅해야 합니다. API 게이트웨이는 여러 마이크로서비스를 호출하고 여러 서비스의 결과를 집계하여 요청을 처리하는 경우가 많습니다. 웹 프로토콜과 HTTP 프로토콜 및 WebSocket 프로토콜과 같이 내부적으로 사용되는 웹 친화적이지 않은 프로토콜 간에 변환할 수 있습니다. 아래 그림은 현재 아키텍처에 적합한 API Gateway를 보여줍니다.

2.1. 요청 전달

마이크로서비스 아키텍처에서 요청 전달은 API 게이트웨이의 핵심 기능 중 하나입니다. 클라이언트가 요청을 하면 어떤 서비스가 요청을 처리해야 하는지 결정하고 이를 적절한 서비스 인스턴스로 전달하는 것은 API 게이트웨이의 책임입니다.

작동 원리

  1. 동적 라우팅 : 특정 서비스의 주소를 하드 코딩하는 대신 게이트웨이가 동적으로 경로를 결정합니다. 이는 일반적으로 앞에서 설명한 Eureka 또는 etcd와 같은 서비스 검색 메커니즘을 기반으로 합니다.
  2. 로드 밸런싱 : 요청은 단순히 서비스 인스턴스로 전달되는 것이 아니라 각 인스턴스의 로드 및 상태가 고려됩니다.
  3. 필터 체인 : 요청을 전달하기 전과 후에 게이트웨이는 보안 필터, 응답 변환 필터 등과 같은 일련의 필터를 적용할 수 있습니다.

전달 전략

  1. Loop Robin : 각 서비스 인스턴스를 순차적으로 선택합니다.
  2. Least Connections : 연결이 가장 적은 인스턴스로 요청을 전달합니다.
  3. 지연 시간 인식 : 각 인스턴스의 지연 시간을 고려하여 전달을 결정합니다.
  4. 지리적 위치 : 요청 소스의 지리적 위치를 기반으로 전달합니다.

2.2 응답 병합

마이크로서비스 환경에서 클라이언트 요청에는 최종 응답을 생성하기 위해 여러 서비스가 함께 작동해야 할 수 있습니다. API 게이트웨이는 여러 서비스의 응답을 집계하여 클라이언트에 통일되고 일관된 응답을 제공할 수 있습니다.

사용되는 장면

  1. 결합된 보기 : 예를 들어 사용자의 프로필 보기는 사용자 서비스, 주문 서비스 및 리뷰 서비스에서 데이터를 가져와야 할 수 있습니다.
  2. 분석 및 보고 : 여러 서비스의 데이터를 집계하여 복잡한 보고서를 생성합니다.

성취하다

  1. 병렬 요청 : API Gateway는 여러 서비스에 요청을 병렬로 보내 전체 응답 시간을 단축할 수 있습니다.
  2. 데이터 변환 : 다양한 서비스의 데이터 형식을 변환하고 표준화합니다.
  3. 오류 처리 : 서비스 중 하나가 오류를 반환하거나 시간 초과되면 수행할 작업을 결정합니다.

2.3 프로토콜 변환

기술이 발전함에 따라 다양한 서비스가 다양한 통신 프로토콜을 사용할 수 있습니다. API 게이트웨이는 클라이언트 요청을 한 프로토콜에서 다른 프로토콜로 변환하는 프로토콜 변환기 역할을 할 수 있습니다.

  1. HTTP to gRPC : 클라이언트는 HTTP/REST를 사용하고, 내부 서비스는 gRPC를 사용할 수 있습니다. API 게이트웨이는 이 두 가지 유형의 통신을 변환할 수 있습니다.
  2. 버전 변환 : 이전 클라이언트는 오래된 API 버전을 사용할 수 있습니다. 게이트웨이는 이러한 요청을 새 버전 요청으로 변환할 수 있습니다.

2.4 데이터 변환

마이크로서비스 아키텍처에서는 역사적 이유, 기술 선택 또는 팀 선호도에 따라 다양한 서비스가 다양한 데이터 형식을 사용할 수 있습니다. API 게이트웨이는 마이크로서비스와 클라이언트 사이의 중개자 역할을 하며 때로는 데이터 형식을 변환해야 합니다.

사용되는 장면

  1. 버전 호환성 : 서비스가 업그레이드되고 데이터 형식이 변경되면 이전 클라이언트가 계속 작동할 수 있도록 게이트웨이는 이전 형식의 데이터를 새 형식으로 변환할 수 있습니다.
  2. 형식 표준화 : XML을 JSON으로 변환하거나 공급업체별 형식을 표준 형식으로 변환합니다.

데이터 변환 전략

  1. XSLT 변환 : XML 데이터의 경우 XSLT를 사용하여 데이터를 변환할 수 있습니다.
  2. JSON 변환 : Jackson이나 Gson과 같은 라이브러리를 사용하여 JSON 데이터를 변환합니다.
  3. 데이터 매핑 : 소스와 대상 데이터 구조 간의 매핑을 정의합니다.

2.5 보안인증

API 게이트웨이는 모든 인바운드 요청에 대한 첫 번째 연락 지점이기 때문에 애플리케이션 보안을 담당하는 경우가 많습니다.

주요 안전 기능

  1. 인증 : 요청자가 누구인지 확인합니다. 일반적인 방법에는 JWT와 같은 토큰 기반 인증이 포함됩니다.
  2. Authorization : 요청자가 수행할 수 있는 작업을 결정합니다. 예를 들어 일부 사용자에게는 읽기 권한만 있고 다른 사용자에게는 쓰기 권한이 있을 수 있습니다.
  3. 속도 제한 : 남용이나 공격을 방지하기 위해 사용자 또는 IP 주소를 기반으로 요청 속도를 제한합니다.
  4. 방화벽 기능 : 악의적인 소스의 요청을 차단하거나 특정 유형의 요청을 차단합니다.

실행전략

  1. API 키 : 각 요청에는 게이트웨이가 요청자를 식별하고 인증하는 데 사용되는 API 키가 포함되어야 합니다.
  2. OAuth : 타사 애플리케이션이 사용자 계정에 제한된 액세스를 허용하는 표준 인증 프레임워크입니다.
  3. JWT(JSON 웹 토큰) : 수신자 간의 정보 요청을 표현하는 간결하고 독립적인 방법입니다.

3. 구성 센터

마이크로서비스 아키텍처에서 구성 센터는 외부 구성을 저장하는 서비스입니다. 외부 구성은 애플리케이션과 별도의 구성이며 애플리케이션을 다시 시작하지 않고도 변경할 수 있습니다.

구성 센터가 필요한 이유는 무엇입니까?

  1. 동적 변경 : 서비스를 다시 시작하지 않고도 런타임 시 구성을 동적으로 변경합니다.
  2. 중앙 집중식 관리 : 다수의 마이크로서비스를 갖춘 대규모 시스템의 경우 중앙 집중식 구성 관리가 필요합니다.
  3. 버전 관리 : 구성의 기록 버전을 저장하고 이전 버전으로 롤백할 수 있습니다.

3.1. 사육사 구성 센터

Apache ZooKeeper는 분산 애플리케이션을 위한 고성능 분산 오픈 소스 조정 서비스입니다. 구성 관리를 위해 특별히 설계된 것은 아니지만 이 시나리오에서 자주 사용됩니다.

이미지-20230915112147300

ZooKeeper 구성 센터의 장점

  1. 고가용성 : ZooKeeper는 분산 특성으로 인해 고가용성과 내결함성을 제공할 수 있습니다.
  2. 실시간 : 구성 변경 시 관련 서비스 인스턴스에 실시간으로 통보할 수 있습니다.
  3. 분산 잠금 : ZooKeeper는 여러 서비스에서 구성을 동기화하는 데 유용한 분산 잠금을 지원합니다.

ZooKeeper를 구성 센터로 사용하는 방법

  1. 노드 생성 : ZooKeeper에서는 영구 노드 또는 임시 노드를 생성하여 구성 정보를 저장할 수 있습니다. 클라이언트 연결이 끊어지면 임시 노드가 사라집니다.
  2. 구성 변경 수신 : 서비스는 구성 노드의 변경 사항을 수신할 수 있습니다. 다른 서비스나 관리자가 구성을 변경하면 서비스에 알림이 전송되고 구성을 다시 로드할 수 있습니다.
  3. 버전 관리 : ZooKeeper는 각 znode(ZooKeeper의 데이터 노드)에 대한 버전 번호를 제공하므로 동시 변경 문제를 방지하는 데 도움이 됩니다.

[ZooKeeper에서 구성 가져오기]

// 从ZooKeeper获取配置
public String getConfig(String configKey) throws Exception {
    
    
    String path = "/config/" + configKey;
    if (zooKeeper.exists(path, false) != null) {
    
    
        return new String(zooKeeper.getData(path, false, null));
    }
    return null;
}

// 使用方法:
String myConfigValue = getConfig("myConfigKey");

3.2 구성센터 데이터 분류

대규모 마이크로서비스 환경에서는 구성 데이터가 방대할 수 있으므로 효과적으로 관리하고 분류해야 합니다.

환경별로 분류

  1. 개발 환경 : 개발자가 로컬에서 사용하는 구성입니다.
  2. 테스트 환경 : QA 및 자동화된 테스트에 사용되는 환경입니다.
  3. 제작환경 : 실제 사용자가 사용하는 환경입니다.

서비스별로 분류

각 마이크로서비스마다 고유한 구성이 있습니다.

기능별로 분류

예를 들어 데이터베이스 구성, 메시지 대기열 구성, 타사 서비스 구성 등이 있습니다.

권한 및 액세스 제어

모든 서비스나 사람이 모든 구성에 액세스할 수 있는 것은 아닙니다. 구성 센터는 권한이 부여된 서비스나 직원만 구성을 읽거나 수정할 수 있도록 역할 기반 액세스 제어를 지원해야 합니다.

이미지-20230915112208695

4. 이벤트 스케줄링(Kafka)

Apache Kafka는 실시간, 내결함성, 처리량이 높은 데이터 스트리밍 파이프라인을 구축하는 데 사용되는 분산 스트림 처리 플랫폼입니다. 마이크로서비스 아키텍처에서 Kafka는 이벤트 중심 아키텍처의 핵심 구성 요소로 자주 사용됩니다.

카프카의 장점

  1. 높은 처리량 : Kafka는 초당 수백만 개의 이벤트 또는 메시지를 처리하도록 설계되었습니다.
  2. 내구성 : 소비자가 일시적으로 사용할 수 없거나 충돌하는 경우에도 메시지가 저장됩니다.
  3. 분산형 : Kafka 클러스터는 내결함성과 고가용성을 제공하기 위해 여러 시스템에 분산될 수 있습니다.

마이크로서비스에 Kafka 적용

  1. 이벤트 소스 : 트랜잭션, 감사, 복구 목적으로 발생하는 모든 이벤트를 기록합니다.
  2. 데이터 통합 : 여러 마이크로서비스의 데이터를 대규모 데이터 웨어하우스 또는 데이터 레이크로 통합합니다.
  3. 비동기 처리 : Kafka를 통해 생산자와 소비자를 분리하면 비동기 처리가 가능합니다.

[Kafka를 사용하여 이벤트 게시]

import org.apache.kafka.clients.producer.*;

// Kafka事件发布服务
public class KafkaProducerService {
    
    
    private final Producer<String, String> producer;
    private static final String TOPIC = "event-topic";

    public KafkaProducerService(Properties properties) {
    
    
        this.producer = new KafkaProducer<>(properties);
    }

    public void sendEvent(String key, String value) {
    
    
        producer.send(new ProducerRecord<>(TOPIC, key, value));
        producer.close();
    }
}

// 使用方法:
Properties properties = new Properties();
properties.put("bootstrap.servers", "localhost:9092");
properties.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
properties.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

KafkaProducerService kafkaService = new KafkaProducerService(properties);
kafkaService.sendEvent("eventKey", "eventValue");

5. 서비스 추적(시작-탐색)

복잡한 마이크로서비스 환경에서는 요청이 다양한 서비스를 통해 전파되는 방식을 이해하는 것이 중요합니다. 이는 성능 문제를 진단하고, 오류를 추적하고, 시스템의 전반적인 동작을 최적화하는 데 도움이 됩니다. 이것이 바로 서비스 추적의 목적입니다.

Spring Cloud Sleuth는 Spring Boot 애플리케이션에 추적을 추가하는 간단하고 효과적인 방법을 제공하는 Spring Cloud 제품군의 구성 요소입니다.

Spring Cloud Sleuth의 작동 방식

  1. 요청 ID : Sleuth는 시스템에 들어오는 각 요청에 대해 "추적 ID"라고 하는 고유 ID를 자동으로 생성합니다. 이 ID는 요청을 통해 시스템 전체에 전파됩니다.
  2. Span ID : 새로운 서비스에 요청이 도착하거나 새로운 활동이 시작될 때마다 Sleuth는 새로운 "span id"를 생성합니다. 이는 서로 다른 서비스에서 동일한 요청의 서로 다른 부분을 구별하는 데 도움이 됩니다.

【Spring Cloud Sleuth 배치】

import org.springframework.cloud.sleuth.zipkin2.ZipkinSpanReporter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SleuthConfig {
    
    

    @Bean
    public ZipkinSpanReporter makeZipkinSpanReporter() {
    
    
        return new ZipkinSpanReporter() {
    
    
            @Override
            public void report(zipkin2.Span span) {
    
    
                System.out.println(
                    String.format("Reporting span [%s] to Zipkin", span)
                );
            }
        };
    }
}

이 코드는 Zipkin과 통합되어 Zipkin에 추적 데이터를 보고하도록 Spring Cloud Sleuth를 구성하는 방법을 보여줍니다.

다른 도구와 통합

Spring Cloud Sleuth는 Zipkin, Elasticsearch, Logstash, Kibana(ELK 스택) 등과 같은 도구와 통합되어 추적 데이터를 시각화하고 분석할 수 있습니다.

6. 서비스 차단기(Hystrix)

마이크로서비스 아키텍처에서는 하나의 서비스가 실패하면 전체 시스템이 중단되는 연쇄 반응이 발생할 수 있습니다. 서비스 퓨즈는 전기 회로의 퓨즈처럼 작동합니다. 비정상적인 상태가 감지되면 추가 손상을 방지하기 위해 "트립"됩니다.

Netflix Hystrix는 가장 잘 알려진 서비스 회로 차단기 구현 중 하나입니다.

Hystrix의 작동 방식

  1. 명령 패턴 : Hystrix를 사용하여 HystrixCommand 개체에서 원격 서비스를 호출하는 코드를 캡슐화합니다.
  2. 격리(Isolation) : Hystrix는 스레드 풀이나 세마포어를 통해 각 서비스 호출에 대한 격리를 제공하여 한 서비스의 장애가 다른 서비스에 영향을 미치지 않도록 보장합니다.
  3. 회로 차단기 : 원격 서비스가 임계값까지 지속적으로 실패하면 Hystrix는 "트립"되어 서비스에 대한 모든 호출을 자동으로 중지합니다.

[Hystrix 회로 차단기 예시]

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;

public class SimpleHystrixCommand extends HystrixCommand<String> {
    
    

    private final String name;

    public SimpleHystrixCommand(String name) {
    
    
        super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
        this.name = name;
    }

    @Override
    protected String run() throws Exception {
    
    
        // 这里放可能会失败的代码
        return "Hello, " + name + "!";
    }

    @Override
    protected String getFallback() {
    
    
        return "Fallback for: " + name;
    }
}

// 使用方法:
String response = new SimpleHystrixCommand("Test").execute();

6.1 Hystrix 회로 차단기 메커니즘

회로 차단기는 Hystrix의 핵심입니다. 작동 원리는 실제 회로 퓨즈의 작동 원리와 유사합니다.

  1. Closed 상태 : 정상적인 상태로 모든 요청이 정상적으로 처리됩니다. 고장률이 미리 결정된 임계값을 초과하면 회로 차단기가 "열림" 상태로 전환됩니다.
  2. 열린 상태 : 이 상태에서는 추가 피해를 방지하기 위해 원격 서비스 호출을 시도하지 않고 모든 요청이 자동으로 실패합니다.
  3. 반 개방 상태 : 일정 시간이 지나면 회로 차단기가 반 개방 상태로 전환되어 일부 요청이 통과될 수 있습니다. 이러한 요청이 성공하면 회로 차단기는 닫힌 상태로 돌아가고, 그렇지 않으면 다시 열립니다.

이러한 세 가지 상태는 장애 발생 시 시스템이 신속하게 복구될 수 있도록 하는 동시에 원격 서비스가 복구할 시간을 가질 수 있도록 버퍼를 제공합니다.

이미지-20230915112343517

7. API 관리

마이크로서비스가 광범위하게 적용되면서 API의 수, 다양성, 복잡성이 크게 증가했습니다. 효과적인 API 관리는 API의 설계, 배포, 유지 관리, 모니터링을 단순화하는 동시에 보안, 안정성, 가용성을 보장하는 것을 목표로 합니다.

API 관리의 핵심 구성요소

  1. API 게이트웨이 : API의 진입점으로 요청 라우팅, 조합, 변환, 검증, 속도 제한 등을 담당합니다.
  2. API 설계 및 문서화 : 표준화된 API 설계 지침 세트를 제공하고 API 문서를 지속적으로 유지 관리합니다.
  3. API 모니터링 및 분석 : API 사용량, 성능, 오류를 모니터링하고 데이터 기반 통찰력을 제공합니다.

API 관리 과제

  1. 버전 관리 : 비즈니스 요구 사항이 변경됨에 따라 API도 변경될 수 있습니다. 기존 클라이언트 관리 API 버전에 영향을 주지 않는 방법은 중요한 고려 사항입니다.
  2. 비율 제한 및 할당량 : 남용을 방지하고 공정한 사용을 보장하려면 API에 대한 사용 제한을 설정해야 합니다.
  3. 보안 : 인증, 승인, 악의적 공격 방지 등 포함
  4. 호환성 : 새로운 API 버전은 기존 사용자에게 영향을 주지 않도록 이전 버전과 호환되어야 합니다.

API 관리 모범 사례

  1. OAS(개방형 API 사양) : 일관성을 보장하기 위해 OpenAPI와 같은 표준 API 설명 형식을 사용합니다.
  2. API 테스트 : 소프트웨어 테스트와 유사하지만 API의 계약, 성능 및 보안에 더 중점을 둡니다.
  3. API 수명주기 관리 : 설계부터 폐기까지 API의 전체 수명주기를 정의하고, 이 수명주기에 따라 API를 관리합니다.

마이크로서비스 아키텍처에서 API 관리는 핵심 구성 요소가 되었습니다. 서비스 수가 증가하면 효과적인 API 관리 전략이 없으면 빠르게 혼란에 빠질 수 있습니다. 위의 방법과 도구를 통해 조직은 API의 상태, 안전 및 효율성을 보장할 수 있습니다.

[API 흐름 제어 예시]

// 使用Spring Boot Rate Limiter进行API流量控制
import io.github.bucket4j.Bucket;
import io.github.bucket4j.Bandwidth;
import io.github.bucket4j.Refill;
import io.github.bucket4j.local.LocalBucketBuilder;

import java.time.Duration;

public class RateLimiterService {
    
    

    private Bucket createNewBucket() {
    
    
        Refill refill = Refill.greedy(10, Duration.ofMinutes(1));
        Bandwidth limit = Bandwidth.classic(10, refill).withInitialTokens(1);
        return LocalBucketBuilder.builder().addLimit(limit).build();
    }

    public boolean tryConsumeToken(Bucket bucket) {
    
    
        return bucket.tryConsume(1);
    }
}

// 使用方法:
RateLimiterService rateLimiter = new RateLimiterService();
Bucket bucket = rateLimiter.createNewBucket();
boolean canProcessRequest = rateLimiter.tryConsumeToken(bucket);
if (canProcessRequest) {
    
    
    // 处理API请求
} else {
    
    
    // 超出限额,拒绝请求或等待
}

위 코드는 Bucket4j 라이브러리를 사용하여 Spring Boot 애플리케이션에서 API의 속도 제한을 구현하는 방법을 보여줍니다.

마이크로서비스의 보안은 또 다른 중요한 영역입니다. 주요 관심사에는 통신 보안(예: TLS 암호화 사용), API 인증 및 권한 부여, 데이터 보안이 포함됩니다.

[API 보안 인증 예시]

// 使用Spring Security进行API安全认证
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;

@EnableWebSecurity
public class APISecurityConfig extends WebSecurityConfigurerAdapter {
    
    

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    
    
        http
            .authorizeRequests()
                .antMatchers("/public/**").permitAll()
                .antMatchers("/private/**").authenticated()
                .and()
            .httpBasic();
    }
}

위의 코드 조각은 Spring Security를 ​​사용하여 API 경로에 대한 기본 인증을 설정하는 방법을 보여줍니다. /public/아래 API는 공개 API이고, /private/아래 API는 인증이 필요합니다.

추천

출처blog.csdn.net/weixin_46703995/article/details/132899828