项目作者: spring-cloud-practices

项目描述 :
service discovery 예제
高级语言: Java
项目地址: git://github.com/spring-cloud-practices/service-discovery.git


Service discovery

목차


Overview

  • 클라우드 네이티브 시스템은 동적이다.(필요에 따라 그때그때 올라가고, 내려가기도 함)
  • 어떤 서비스가 내려가고 올라가더라도 그 서비스를 이용하는 다른 서비스는 영향을 받으면 안된다.
  • 해당 서비스를 아래와 같이 설정하면 클라이언트 -> 서버를 고정적으로 결합하므로 동적인 클라우드 네이티브 시스템에는 적합하지 않다.
    1. member-service:
    2. endpoints:
    3. - http://172.12.35.65:8080/members
    4. - http://172.12.35.67:8080/members
  • DNS를 이용할 수도 있지만, 클라우드 환경에서는 가장 좋은 방법이라고 볼 수 없다.
    • 클라이언트 내부에 캐시를 둘 수 있다는 것이 장점인데, 사용되지 않는 IP 주소를 캐시하고 있을 수 있다.
    • TTL(time to live) 값을 짧게 잡으면 DNS 레코드를 더 자주 받아오는데 많은 시간을 쓰게 된다.
    • DNS 로드밸런싱을 적용하면 스티키 세션(sticky session)은 지원하지만 그 이상의 기능이 필요하면 감당하기 어렵다.(예를들어 OAuth2나 JWT의
      access token 기반 밸런싱)
    • 프록시 역할을 하는 가상 로드밸런서는 시스템의 상태나 요청 처리에 필요한 작업량을 알지 못한다.
      • 초기 연결을 서비스에 분산할 뿐, 연결에 포함된 요청 처리에 필요한 작업량을 분산하지는 못한다.
  • 인프라가 아니라 프로그래밍을 통해 더 나은 라우팅 전략을 구현할 수 있다.(작업량은 어떻게 분산..?)

DiscoveryClient

  • 서비스 레지스트리는 서비스 인스턴스와 서비스가 제공하는 API를 내용으로 하는 테이블이다.
    • 서비스 레지스트리는 CAP(Consistency 일관성, Availability 가용성, Partition tolerance 분리 내구성) 정리의 제약도 받는다.
  • 스프링 클라우드는 DiscoveryClient 추상화를 통해 클라이언트가 다양한 유형의 서비스 레지스트리를 쉽게 이용할 수 있게 해준다.
    • 다양한 구현체들을 Plugin 하여 사용할 수 있다.
    • 클라우드 파운드리, 아파치 주키퍼, 해시코프 컨설, 넷플릭스 유레카, CoreOS etcd
  • 일부 서비스 레지스트리는 클라이언트도 레지스트리에 등록해야 한다.
    • 많은 DiscoveryClient 추상화 구현체는 애플리케이션 기동 시 자동으로 등록해준다.


DiscoveryClient.java

  1. package org.springframework.cloud.client.discovery;
  2. import java.util.List;
  3. import org.springframework.cloud.client.ServiceInstance;
  4. import org.springframework.core.Ordered;
  5. public interface DiscoveryClient extends Ordered {
  6. /**
  7. * Default order of the discovery client.
  8. */
  9. int DEFAULT_ORDER = 0;
  10. /**
  11. * A human-readable description of the implementation, used in HealthIndicator.
  12. * @return The description.
  13. */
  14. String description();
  15. /**
  16. * Gets all ServiceInstances associated with a particular serviceId.
  17. * @param serviceId The serviceId to query.
  18. * @return A List of ServiceInstance.
  19. */
  20. List<ServiceInstance> getInstances(String serviceId);
  21. /**
  22. * @return All known service IDs.
  23. */
  24. List<String> getServices();
  25. /**
  26. * Default implementation for getting order of discovery clients.
  27. * @return order
  28. */
  29. @Override
  30. default int getOrder() {
  31. return DEFAULT_ORDER;
  32. }
  33. }


간단하게 org.springframework.cloud.netflix.eureka.EurekaDiscoveryClient 살펴보면 com.netflix.discovery.EurekaClient를 이용하여
Spring cloud의 ServiceInstance로 컨버팅 해주고 있다.

  1. package org.springframework.cloud.netflix.eureka;
  2. ...
  3. public class EurekaDiscoveryClient implements DiscoveryClient {
  4. ...
  5. @Override
  6. public List<ServiceInstance> getInstances(String serviceId) {
  7. List<InstanceInfo> infos = this.eurekaClient.getInstancesByVipAddress(serviceId,
  8. false);
  9. List<ServiceInstance> instances = new ArrayList<>();
  10. for (InstanceInfo info : infos) {
  11. instances.add(new EurekaServiceInstance(info));
  12. }
  13. return instances;
  14. }
  15. @Override
  16. public List<String> getServices() {
  17. Applications applications = this.eurekaClient.getApplications();
  18. if (applications == null) {
  19. return Collections.emptyList();
  20. }
  21. List<Application> registered = applications.getRegisteredApplications();
  22. List<String> names = new ArrayList<>();
  23. for (Application app : registered) {
  24. if (app.getInstances().isEmpty()) {
  25. continue;
  26. }
  27. names.add(app.getName().toLowerCase());
  28. }
  29. return names;
  30. }
  31. ...
  32. }


ServiceInstance는 Spring Cloud에서 정의한 인터페이스로 host,port 등의 아래와 같은 정보들을 담고있다.

org.springframework.cloud.client.ServiceInstance.java

  1. /**
  2. * Represents an instance of a service in a discovery system.
  3. */
  4. public interface ServiceInstance {
  5. /**
  6. * @return The unique instance ID as registered.
  7. */
  8. default String getInstanceId() {
  9. return null;
  10. }
  11. /**
  12. * @return The service ID as registered.
  13. */
  14. String getServiceId();
  15. /**
  16. * @return The hostname of the registered service instance.
  17. */
  18. String getHost();
  19. /**
  20. * @return The port of the registered service instance.
  21. */
  22. int getPort();
  23. /**
  24. * @return Whether the port of the registered service instance uses HTTPS.
  25. */
  26. boolean isSecure();
  27. /**
  28. * @return The service URI address.
  29. */
  30. URI getUri();
  31. /**
  32. * @return The key / value pair metadata associated with the service instance.
  33. */
  34. Map<String, String> getMetadata();
  35. /**
  36. * @return The scheme of the service instance.
  37. */
  38. default String getScheme() {
  39. return null;
  40. }
  41. }

Netflix Eureka

Netflix Eureka 개요

Eureka highlevel architecture

Eureka Server

  • 위와 같이 Eureka Server와 Application에 포함된 Eureka Client가 존재한다.
  • Application Service를 살펴보면 Eureka Client를 통해 Eureka Server와 아래와 같은 상호작용을 하고 있다.

Eureka wiki-Understanding-eureka-client-server-communication

Register
;Client -> Server에게 등록 요청을 보낸다.

Renew
30초마다 heatbeat를 보내서 lease를 갱신한다. Server는 마지막 heatbeat를 보낸 시간보다 90초가 지났으면 해당 서비스를 Registry에서 제거한다.

Fetch Registry
Client는 Server로부터 registry 정보를 가져와 로컬 캐시에 담아둔다. 이러한 registry 정보는 service discovery하는데 사용된다.
아래의 com.netflix.discovery.DiscoveryClient를 살펴보면 delta를 조회하여 client의 이전 delta와 해시코드(문자열)를 비교하여 변경사항이 있으면 갱신한다.

  1. private void getAndUpdateDelta(Applications applications) throws Throwable {
  2. long currentUpdateGeneration = fetchRegistryGeneration.get();
  3. Applications delta = null;
  4. // /apps/delta?regions=... 호출
  5. EurekaHttpResponse<Applications> httpResponse = eurekaTransport.queryClient.getDelta(remoteRegionsRef.get());
  6. if (httpResponse.getStatusCode() == Status.OK.getStatusCode()) {
  7. delta = httpResponse.getEntity();
  8. }
  9. if (delta == null) {
  10. logger.warn("The server does not allow the delta revision to be applied because it is not safe. "
  11. + "Hence got the full registry.");
  12. getAndStoreFullRegistry();
  13. } else if (fetchRegistryGeneration.compareAndSet(currentUpdateGeneration, currentUpdateGeneration + 1)) {
  14. logger.debug("Got delta update with apps hashcode {}", delta.getAppsHashCode());
  15. String reconcileHashCode = "";
  16. if (fetchRegistryUpdateLock.tryLock()) {
  17. try {
  18. // client의 delta 갱신
  19. updateDelta(delta);
  20. // {instance_name}:{count}_{instance_name}_{count} ...
  21. reconcileHashCode = getReconcileHashCode(applications);
  22. } finally {
  23. fetchRegistryUpdateLock.unlock();
  24. }
  25. } else {
  26. logger.warn("Cannot acquire update lock, aborting getAndUpdateDelta");
  27. }
  28. ...
  29. }
  30. ...
  31. }

Cancel
Client는 애플리케이션 종료 시 Server에게 Cancel 요청을 보내 registry에서 제거된다.


Eureka interacts

Eureka interact

위와 같은 예를 들어보자.

  • Service1 : 애플리케이션 시작 시 Eureka 서버에서 Register 요청을 보낸 뒤 서버는 Registry에 추가한다.
  • Service2 : 주기적으로 Heatbeat를 보낸다.(Renew)
  • Service3 : 애플리케이션 종료 시 Eureka 서버에게 Cancel 요청을 보낸 뒤 서버는 Registry에서 제거한다.
  • Service4 : 애플리에키션 종료 시 Cancel 요청을 보내지 않은 상태이다.
  • Eureka Server : Service4에 대하여 마지막 Heatbeat로 부터 90초가 지나서 Registry에서 제거한다.

더 자세한 Endpoint는 WIKI-Eureka-REST-operations 를 살펴보자.


Netflix Eureka 시작하기

간단하게 Standalone Mode의 Eureka서버를 실행하고, Eureka Client를 포함하고 있는 account service를 실행해보자.

Eureka Server 설정

application.yaml

  1. eureka:
  2. # dashboard에 대한 설정으로, http://localhost:3000/eureka-ui 를 통해 확인할 수 있다.
  3. dashboard:
  4. path: /eureka-ui
  5. instance:
  6. hostname: localhost
  7. statusPageUrlPath: /info
  8. healthCheckUrlPath: /health
  9. # 등록된 인스턴스 중 많은 수가 정해진 시간 내에 Heatbeat를 보내지 않으면 Eureka는 이를 인스턴스 문제가 아닌
  10. # 네트워크 문제라고 간주하고 Registry를 그대로 유지한다. Example 실행을 위해 false로 설정
  11. server:
  12. enableSelfPreservation: false
  13. client:
  14. # Eureka client -> Eureka server로 등록 여부
  15. # standalone mode이므로 자기 자신을 등록할 필요가 없다.
  16. registerWithEureka: false
  17. # Eureka Client -> Eureka server로 Registry fetch 여부
  18. fetchRegistry: false

@EnableEurekaServer

  1. package server;
  2. import java.util.Arrays;
  3. import java.util.Map.Entry;
  4. import java.util.TreeMap;
  5. import java.util.function.Predicate;
  6. import org.springframework.boot.WebApplicationType;
  7. import org.springframework.boot.autoconfigure.SpringBootApplication;
  8. import org.springframework.boot.builder.SpringApplicationBuilder;
  9. import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
  10. import org.springframework.context.ConfigurableApplicationContext;
  11. import org.springframework.web.bind.annotation.GetMapping;
  12. import org.springframework.web.bind.annotation.RestController;
  13. import lombok.extern.slf4j.Slf4j;
  14. @Slf4j
  15. @SpringBootApplication
  16. @EnableEurekaServer
  17. public class EurekaServerApplication {
  18. public static void main(String[] args) {
  19. new SpringApplicationBuilder(EurekaServerApplication.class)
  20. .web(WebApplicationType.SERVLET).run(args);
  21. }
  22. }


Eureka Client 설정

bootstrap.yaml

  1. spring:
  2. application:
  3. name: account-service
  4. eureka:
  5. instance:
  6. # 랜덤값을 이용하여 instance id를 고유하게 재정의
  7. instance-id: ${spring.application.name}:${spring.application.instance_id:${random.value}}

application.yaml

  1. eureka:
  2. # service instance에 대한 설정
  3. instance:
  4. statusPageUrlPath: /actuator/info
  5. healthCheckUrlPath: /actuator/health
  6. # eureka client 설정
  7. client:
  8. serviceUrl:
  9. defaultZone: http://localhost:3000/eureka/
  10. # /actuator/info 호출 시 출력 된 Application 정보
  11. info:
  12. app:
  13. name: Account Example Application
  14. version: 1.0.0
  15. discription: This is a demo project for eurkea


미리 정의한 스크립트를 기반으로 Server와 AccountServer(EurekaClient)를 실행해보자.

start server/client

  1. // eureka 서버 시작하기
  2. $ ./tools/script/start.sh server
  3. // account 서버1 시작하기(profile:default, port:3100)
  4. $ ./tools/script/start.sh account default 3100
  5. // account 서버2 시작하기(profile:default, port:3101)
  6. $ ./tools/script/start.sh server default 3101

Eureka server dashboard 확인하기

http://localhost:3000/eureka-ui 를 접속하면 아래와 같은 화면을 확인할 수 있다.

Eureka Server Dashboard


DiscoveryClient의 ServiceInstance 리스트 조회하기

account service에 아래와 같은 코드를 추가해서 /discovery/services를 호출하면 모든 인스턴스를 반환하는 API를 추가하자.

  1. @Autowired
  2. private DiscoveryClient discoveryClient;
  3. @GetMapping("/discovery/services")
  4. public Map<String, List<ServiceInstance>> discoveryServices() {
  5. return discoveryClient.getServices()
  6. .stream()
  7. .collect(Collectors.toMap(s -> s, s -> discoveryClient.getInstances(s)));
  8. }


아래와 같이 요청하면 Spring cloud의 ServiceInstance 구현체인 EurekaServiceInstance의 응답 결과를 확인할 수 있다.
(instanceId ~ metadata는 ServiceInstance 스펙이고 instanceInfo는 eureka의 InstanceInfo 스펙이다.)

  1. $ curl -XGET http://localhost:3100/discovery/services | jq .
  1. {
  2. "account-service": [
  3. {
  4. "instanceId": "account-service:b12e61ad1432e7da69d396f443e8b1bf",
  5. "serviceId": "ACCOUNT-SERVICE",
  6. "host": "192.168.0.2",
  7. "port": 3101,
  8. "secure": false,
  9. "scheme": "http",
  10. "uri": "http://192.168.0.2:3101",
  11. "metadata": {
  12. "management.port": "3101"
  13. },
  14. "instanceInfo": {
  15. "instanceId": "account-service:b12e61ad1432e7da69d396f443e8b1bf",
  16. "app": "ACCOUNT-SERVICE",
  17. "appGroupName": null,
  18. "ipAddr": "192.168.0.2",
  19. "sid": "na",
  20. "homePageUrl": "http://192.168.0.2:3101/",
  21. "statusPageUrl": "http://192.168.0.2:3101/actuator/info",
  22. "healthCheckUrl": "http://192.168.0.2:3101/actuator/health",
  23. "secureHealthCheckUrl": null,
  24. "vipAddress": "account-service",
  25. "secureVipAddress": "account-service",
  26. "countryId": 1,
  27. "dataCenterInfo": {
  28. "@class": "com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo",
  29. "name": "MyOwn"
  30. },
  31. "hostName": "192.168.0.2",
  32. "status": "UP",
  33. "overriddenStatus": "UNKNOWN",
  34. "leaseInfo": {
  35. "renewalIntervalInSecs": 30,
  36. "durationInSecs": 90,
  37. "registrationTimestamp": 1598537803756,
  38. "lastRenewalTimestamp": 1598537923714,
  39. "evictionTimestamp": 0,
  40. "serviceUpTimestamp": 1598537803756
  41. },
  42. "isCoordinatingDiscoveryServer": false,
  43. "metadata": {
  44. "management.port": "3101"
  45. },
  46. "lastUpdatedTimestamp": 1598537803756,
  47. "lastDirtyTimestamp": 1598537803712,
  48. "actionType": "ADDED",
  49. "asgName": null
  50. }
  51. },
  52. {...}
  53. ]
  54. }

로그 살펴보기

  • (1) Client는 GET /eureka//apps/?를 호출하여 Registry 정보를 가져온다.
  1. // Client log
  2. 2020-08-27 23:36:57.663 INFO 17140 --- [ main] com.netflix.discovery.DiscoveryClient : Getting all instance registry info from the eureka server
  3. ...
  4. 2020-08-27 23:36:57.841 DEBUG 17140 --- [ main] n.d.s.t.j.AbstractJerseyEurekaHttpClient : Jersey HTTP GET http://localhost:3000/eureka//apps/?; statusCode=200
  5. 2020-08-27 23:36:57.841 DEBUG 17140 --- [ main] c.n.d.s.t.d.RedirectingEurekaHttpClient : Pinning to endpoint null
  6. 2020-08-27 23:36:57.841 INFO 17140 --- [ main] com.netflix.discovery.DiscoveryClient : The response status is 200
  7. 2020-08-27 23:36:57.841 DEBUG 17140 --- [ main] com.netflix.discovery.DiscoveryClient : Got full registry with apps hashcode
  8. 2020-08-27 23:36:57.842 DEBUG 17140 --- [ main] com.netflix.discovery.DiscoveryClient : The total number of all instances in the client now is 0
  9. // Server log
  10. 2020-08-27 23:36:57.797 DEBUG 17119 --- [nio-3000-exec-1] c.n.e.registry.AbstractInstanceRegistry : Fetching applications registry with remote regions: false, Regions argument []
  11. 2020-08-27 23:36:57.803 DEBUG 17119 --- [nio-3000-exec-1] c.n.eureka.registry.ResponseCacheImpl : New application cache entry {name=ALL_APPS, type=Application, format=JSON} with apps hashcode
  12. 2020-08-27 23:36:57.940 DEBUG 17119 --- [nio-3000-exec-2] c.n.d.util.DeserializerStringCache : clearing global-level cache with size 1
  13. 2020-08-27 23:36:57.940 DEBUG 17119 --- [nio-3000-exec-2] c.n.d.util.DeserializerStringCache : clearing app-level serialization cache with size 8
  • (2) Client는 POST /eureka//apps/ACCOUNT-SERVICE를 호출하여 자신의 인스턴스를 Register 후 204 Status code로 성공
  1. // client log
  2. 2020-08-27 23:36:57.843 INFO 17140 --- [ main] com.netflix.discovery.DiscoveryClient : Starting heartbeat executor: renew interval is: 30
  3. ...
  4. 2020-08-27 23:36:57.852 INFO 17140 --- [ main] o.s.c.n.e.s.EurekaServiceRegistry : Registering application ACCOUNT-SERVICE with eureka with status UP
  5. ...
  6. 2020-08-27 23:36:57.855 INFO 17140 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_ACCOUNT-SERVICE/account-service:a389e2d6e5bf85f9e1544048fbbf8eff: registering service...
  7. ...
  8. 2020-08-27 23:36:57.954 DEBUG 17140 --- [nfoReplicator-0] n.d.s.t.j.AbstractJerseyEurekaHttpClient : Jersey HTTP POST http://localhost:3000/eureka//apps/ACCOUNT-SERVICE with instance account-service:a389e2d6e5bf85f9e1544048fbbf8eff; statusCode=204
  9. 2020-08-27 23:36:57.954 DEBUG 17140 --- [nfoReplicator-0] c.n.d.s.t.d.RedirectingEurekaHttpClient : Pinning to endpoint null
  10. 2020-08-27 23:36:57.954 INFO 17140 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_ACCOUNT-SERVICE/account-service:a389e2d6e5bf85f9e1544048fbbf8eff - registration status: 204
  11. // server log
  12. 2020-08-27 23:36:57.940 DEBUG 17119 --- [nio-3000-exec-2] c.n.e.resources.ApplicationResource : Registering instance account-service:a389e2d6e5bf85f9e1544048fbbf8eff (replication=null)
  13. 2020-08-27 23:36:57.940 DEBUG 17119 --- [nio-3000-exec-2] o.s.c.n.eureka.server.InstanceRegistry : register ACCOUNT-SERVICE, vip account-service, leaseDuration 90, isReplication false
  14. 2020-08-27 23:36:57.941 DEBUG 17119 --- [nio-3000-exec-2] c.n.e.registry.AbstractInstanceRegistry : No previous lease information found; it is new registration
  15. 2020-08-27 23:36:57.941 DEBUG 17119 --- [nio-3000-exec-2] c.n.e.registry.AbstractInstanceRegistry : Processing override status using rule: [com.netflix.eureka.registry.rule.DownOrStartingRule, com.netflix.eureka.registry.rule.OverrideExistsRule, com.netflix.eureka.registry.rule.LeaseExistsRule, com.netflix.eureka.registry.rule.AlwaysMatchInstanceStatusRule]
  16. 2020-08-27 23:36:57.941 DEBUG 17119 --- [nio-3000-exec-2] c.n.e.r.r.AlwaysMatchInstanceStatusRule : Returning the default instance status UP for instance account-service:a389e2d6e5bf85f9e1544048fbbf8eff
  17. 2020-08-27 23:36:57.942 DEBUG 17119 --- [nio-3000-exec-2] c.n.eureka.registry.ResponseCacheImpl : Invalidating the response cache key : Application ACCOUNT-SERVICE V1 JSON, full
  18. 2020-08-27 23:36:57.943 DEBUG 17119 --- [nio-3000-exec-2] c.n.eureka.registry.ResponseCacheImpl : Invalidating the response cache key : Application ACCOUNT-SERVICE V1 JSON, compact
  19. ...
  • (3) Client는 PUT /eureka//apps/ACCOUNT-SERVICE/account-service:a389e2d6e5bf85f9e1544048fbbf8eff를 호출하여 Heartbeat를 보내 Renew 작업이 이루어진다.
  1. // client log
  2. 2020-08-27 23:37:27.878 DEBUG 17140 --- [tbeatExecutor-0] n.d.s.t.j.AbstractJerseyEurekaHttpClient : Jersey HTTP PUT http://localhost:3000/eureka//apps/ACCOUNT-SERVICE/account-service:a389e2d6e5bf85f9e1544048fbbf8eff; statusCode=200
  3. 2020-08-27 23:37:27.879 DEBUG 17140 --- [tbeatExecutor-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_ACCOUNT-SERVICE/account-service:a389e2d6e5bf85f9e1544048fbbf8eff - Heartbeat status: 200
  4. 2020-08-27 23:37:27.897 DEBUG 17140 --- [freshExecutor-0] c.n.d.shared.MonitoredConnectionManager : Released connection is reusable.
  5. ...
  6. 2020-08-27 23:37:27.897 DEBUG 17140 --- [freshExecutor-0] n.d.s.t.j.AbstractJerseyEurekaHttpClient : Jersey HTTP GET http://localhost:3000/eureka//apps/?; statusCode=200
  7. 2020-08-27 23:37:27.897 INFO 17140 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : The response status is 200
  8. // server log
  9. 2020-08-27 23:37:27.876 DEBUG 17119 --- [nio-3000-exec-4] o.s.c.n.eureka.server.InstanceRegistry : renew ACCOUNT-SERVICE serverId account-service:a389e2d6e5bf85f9e1544048fbbf8eff, isReplication {}false
  10. 2020-08-27 23:37:27.876 DEBUG 17119 --- [nio-3000-exec-4] c.n.e.registry.AbstractInstanceRegistry : Fetching applications registry with remote regions: false, Regions argument []
  • (4) Client는 DELETE /eureka//apps/ACCOUNT-SERVICE/account-service:a389e2d6e5bf85f9e1544048fbbf8eff를 호출하여 Cancel 요청을 보낸 후 서버는 Registry에서 제거한다.
  1. // client log
  2. 2020-08-28 00:02:33.149 INFO 19325 --- [extShutdownHook] o.s.c.n.e.s.EurekaServiceRegistry : Unregistering application ACCOUNT-SERVICE with eureka with status DOWN
  3. ...
  4. 2020-08-28 00:02:33.149 INFO 19325 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_ACCOUNT-SERVICE/account-service:a389e2d6e5bf85f9e1544048fbbf8eff: registering service...
  5. ...
  6. 2020-08-28 00:02:36.187 DEBUG 19325 --- [extShutdownHook] n.d.s.t.j.AbstractJerseyEurekaHttpClient : Jersey HTTP DELETE http://localhost:3000/eureka//apps/ACCOUNT-SERVICE/account-service:a389e2d6e5bf85f9e1544048fbbf8eff; statusCode=200
  7. 2020-08-28 00:02:36.187 INFO 19325 --- [extShutdownHook] com.netflix.discovery.DiscoveryClient : DiscoveryClient_ACCOUNT-SERVICE/account-service:a389e2d6e5bf85f9e1544048fbbf8eff - deregister status: 200
  8. // server log
  9. 2020-08-28 00:02:36.184 DEBUG 19308 --- [nio-3000-exec-6] o.s.c.n.eureka.server.InstanceRegistry : cancel ACCOUNT-SERVICE, serverId account-service:a389e2d6e5bf85f9e1544048fbbf8eff, isReplication false
  10. 2020-08-28 00:02:36.185 DEBUG 19308 --- [nio-3000-exec-6] c.n.eureka.registry.ResponseCacheImpl : Invalidating the response cache key : Application ACCOUNT-SERVICE V1 JSON, full
  11. ...
  12. 2020-08-28 00:02:36.186 INFO 19308 --- [nio-3000-exec-6] c.n.e.registry.AbstractInstanceRegistry : Cancelled instance ACCOUNT-SERVICE/account-service:a389e2d6e5bf85f9e1544048fbbf8eff (replication=false)
  13. 2020-08-28 00:02:36.186 DEBUG 19308 --- [nio-3000-exec-6] c.n.eureka.resources.InstanceResource : Found (Cancel): ACCOUNT-SERVICE - account-service:a389e2d6e5bf85f9e1544048fbbf8eff

Netflix Eureka Server HA


References