어떻게 서 비 스 를 빠르게 시작 합 니까?

5983 단어 servermicroservice
소프트웨어 개발 에서 일반적인 방법 은 일부 기초, 간단 한 서 비 스 를 조합 하여 특정한 기능 을 가 진 특정한 서 비 스 를 형성 하 는 것 이다.이런 블록 을 쌓 는 구조 나 아래 에서 위로 의 조합 은 프로그램의 자원 격 리 와 유지 와 확대 에 유리 하 다.고 층 의 서 비 스 는 바 텀 서비스 에 의존 하여 업무 계산 을 제공 하고 저층 의 서 비 스 는 데이터 저장, 네트워크 전송 등 기초 작업 을 제공한다.
이런 저층 서 비 스 는 현실 세계 의 도시 인 프 라 처럼 도로 차량 이 없 으 면 운행 할 곳 이 없고 발전소 가 제공 하 는 전력 이 없 으 면 모든 전력 설비 가 작 동 하지 않 는 다.따라서 프로그램 세계 가 구축 되 었 을 때 이러한 기초 서 비 스 는 로드 (초기 화) 를 미리 완성 해 야 합 니 다.저층 인터페이스 와 고 층 인터페이스 가 비교적 많아 졌 을 때 그들의 관 계 는 복잡 하 게 뒤 섞 여 있다.그래서 합 리 적 으로 관리 하 는 것 이 필요 하 다!다음 에 우 리 는 몇 가지 흔히 볼 수 있 는 모델 을 토론 할 것 이다.
질서 있 게 불 러 오기
매우 간단 한 방식 은 모든 서 비 스 를 의존 등급 에 따라 하나씩 불 러 오 는 것 이다.다음 그림 에서 C 는 각각 A 와 B 에 의존 했다.프로그램 이 시 작 될 때 A - > B - > C 방식 으로 순서대로 불 러 올 수 있 습 니 다.
이런 방식 은 서비스 의존 을 효과적으로 해결 할 수 있다. 서비스 가 특별히 복잡 하지 않 고 의존 하 는 체인 이 길지 않 은 상황 에서 좋 은 선택 이 될 것 이다.그러나 이런 방식 은 모든 서 비 스 를 시작 할 때 길 어 집 니 다. 로 딩 이 하나씩 진행 되 기 때 문 입 니 다.따라서 대형 서비스 에 서 는 이런 방식 이 추천 되 지 않 는 다.
필요 에 따라 불 러 오기
다른 방식 은 필요 에 따라 불 러 오고 서비스 가 사 용 될 때 의존 하 는 서 비 스 를 불 러 오 는 것 이다.다음 그림 에서 2 개의 고 층 서비스 C 와 E 가 있 는데 이들 은 각각 기초 서비스 A, B 와 B, D 에 의존 하고 있다.
C 서 비 스 를 방문 할 때 필요 에 따라 C B A 를 불 러 옵 니 다.C. B 를 찾 아 불 러 오고 B 도 A 를 찾 아 불 러 옵 니 다.이것 은 모든 사용 기호 。 ,E E B D。

, 。 를 되 돌려 주 는 과정 이다.반복 적 으로 불 러 오 는 과정 을 피하 기 위해 서, 실제로 우 리 는 이러한 서 비 스 를 하나의 서비스 용기 에 넣 을 것 이다. 서비스의 불 러 오 는 것 은 용기 처리 가 있 을 것 이다. 우리 가 해 야 할 일 은 단지 하나의 용기 에서 그것들 을 찾 는 것 이다.예 를 들 어 위의 그림 에서 C, E 는 모두 B 에 의존 했다.
대부분의 응용 서 비 스 는 필요 에 따라 불 러 오 는 모델 을 선택 합 니 다. 여러 서 비 스 를 동시에 불 러 오지 못 하 는 문 제 를 피 할 수 있 을 뿐만 아니 라 필요 에 따라 불 러 오 는 것 은 실제 적 으로 방문 하지 않 은 서 비 스 를 불 러 오지 않 기 때문에 일부 자원 을 효과적으로 절약 할 수 있 습 니 다.
하지만 이것 이 궁 극적인 방안 인가?분명히 아니 야!다음은 세 번 째 모델 을 알 아 보 겠 습 니 다.
그룹 로 딩
그룹 로 딩 은 서 비 스 를 의존 하 는 등급 에 따라 서로 다른 것 으로 나 누 는 것 이다 ServiceGroup.ServiceGroup 사 이 는 순서대로 불 러 오지 만 ServiceGroup 내의 서 비 스 는 병렬 로 불 러 옵 니 다.이런 방식 은 모든 서 비 스 를 한꺼번에 불 러 올 수 있다.필요 에 따라 불 러 오 는 것 과 달리 그룹 로 딩 은 시작 이 성공 할 때 바로 서 비 스 를 할 수 있 습 니 다.동시에 순서대로 불 러 오 면 서 비 스 를 더욱 빠르게 시작 할 수 있 습 니 다.다음 그림 에서 ServiceGroup 1 중의 A, B, 'C' 는 병렬 로 로드 되 었 고 ServiceGroup 2ServiceGroup 1 로드 가 완 료 된 후에 야 로드 되 기 시작 했다.
서비스 A, B, D 사이 에 의존 하지 않 기 때문에 로 딩 은 무질서 할 수 있 습 니 다.ServiceGroup 1 로드 가 완료 되면 ServiceGroup 2 로드 하기 전에 필요 한 서 비 스 를 불 러 왔 습 니 다.이 럴 때 는 문제 가 없 을 것 이다 ServiceNotFound.다음 코드 는 DSL 을 사용 하여 전체 로 딩 과정 을 설명 합 니 다.

GroupedServiceBus serviceBus = ...
serviceBus.start(serviceA, serviceB, serviceD)
          .then(serviceC, serviceE)
          .awaitStarted();

소각 하 다
소각 순 서 는 로 딩 순서 의 역순 이 어야 합 니 다.이렇게 해야만 너 는 필요 한 서비스의 분실 을 보증 할 수 있다.
그룹 로 딩 실현
Gauva 의 서 비 스 를 서비스의 기본 인터페이스 로 사용 하고 다음은 그룹 로 딩 의 간단 한 실현 을 보 여 줍 니 다.
import com.google.common.util.concurrent.Service;

public interface GroupedServiceBus {
    void awaitStarted();

    void awaitStopped();

    GroupedServiceBus start(Service... services);

    GroupedServiceBus then(Service... services);

    GroupedServiceBus awaitServiceGroupStarted(Service... services);

}

DSL 방식 으로 API 를 설계 하면 사용 하기 쉽 고 이해 하기 쉽다.
public interface KernelService {

}

어떤 서비스 가 올 바 르 게 불 러 와 야 하 는 지 KernelService 를 지정 할 수 있 습 니 다. KernelService 불 러 오 는 데 실 패 했 을 때 올 바른 서 비 스 를 제공 할 수 없습니다. 이 때 프로그램 전 체 를 종료 할 수 있 습 니 다.

public class GroupedServiceBusImpl implements GroupedServiceBus {

    private final List serviceCluster = new ArrayList<>();
    private final ServiceManager.Listener listener = new ServiceManager.Listener() {
        @Override
        public void failure(Service service) {
            if (service instanceof KernelService) {
                logger.error("KernelService [{}] start failure, system will be exit 1.", service.getClass());
                System.exit(1);
            } else {
                logger.error("Service [{}] start failure.", service.getClass());
            }
        }
    };

    @Override
    public void awaitStarted() {
        if (!serviceCluster.isEmpty()) {
            for (final ServiceManager serviceManager : serviceCluster) {
                awaitStartedServiceManager(serviceManager);
            }
        }
    }

    @Override
    public void awaitStopped() {
        if (!serviceCluster.isEmpty()) {
            for (int i = serviceCluster.size() - 1; i > -1; i--) {
                final ServiceManager serviceManager = serviceCluster.get(i);
                serviceManager.stopAsync();
                serviceManager.awaitStopped();
            }
            serviceCluster.clear();
        }
    }

    @Override
    public GroupedServiceBus start(final Service... services) {
        then(services);
        return this;
    }

    @Override
    public GroupedServiceBus then(Service... services) {
        final ServiceManager serviceManager = new ServiceManager(ImmutableList.copyOf(services));
        serviceManager.addListener(listener);
        serviceCluster.add(serviceManager);
        return this;
    }

    private void awaitStartedServiceManager(final ServiceManager serviceManager) {
        if (!serviceManager.isHealthy()) {
            serviceManager.startAsync();
            serviceManager.awaitHealthy();
        }
    }
}

위의 serviceCluster 는 하나의 ServiceManager 집합 으로 여기 ServiceManager 가 바로 우리 가 위 에서 말 한 ServiceGroup 이다.ServiceGroup 에 있 는 모든 서 비 스 를 동시에 불 러 올 수 있 습 니 다.
총결산
이 세 가지 모델 중 어느 것 도 절대적 으로 정확 하고 우수한 것 이 없다.프로 그래 밍 에 서 는 성능, 안정성 등 을 고려 하 는 동시에 과도 한 디자인 의 함정 에 빠 지지 않도록 해 야 한다.당신 의 선택 은 당신 의 환경 에 적응 해 야 합 니 다!

좋은 웹페이지 즐겨찾기