comnic's Dev&Life

[MSA]5. Eureka를 통한 서비스 관리 본문

MSA(MicrosofService Architecture)

[MSA]5. Eureka를 통한 서비스 관리

comnic 2019. 5. 19. 15:47
반응형

Java Version: 11, Spring Boot 2.1.4

[MSA]1. Config Server를 통한 설정 관리
[MSA]2. 메시지 브로커를 통한 설정값 관리
[MSA]3. 마이크로 서비스 간 호출 #1 - Feign
[MSA]4. 마이크로 서비스 간 호출 #2 - Ribbon
[MSA]5. Eureka를 통한 서비스 관리

 

MSA를 운영하기 위한 기본적인 시스템은 갖추었으나, 여전히 아쉬운 것들이 남아 있습니다. 새로운 서버와 서비스의 확충과 관리에 대한 부분이 바로 그런 부분 중의 하나 일 것입니다. 그래서 이번에는 eureka를 이용해 서비스들이 자동으로 등록관리 될 수 있도록 해 보겠습니다.

 

Step 1. Eureka Server 프로젝트 생성

먼저 서비스들을 관리 할 eureka 서버를 추가해야 합니다. 아래처럼 추가 후 새로운 프로젝트를 만들어 줍니다.

 - Cloud Discovery / Eureka Server

implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'

 

Step 2. Eureka Server 설정

프로젝트 생성 후  먼저 아래와 같이 설정합니다. (application.properties)

server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false


그리고 Application 클래스에 @EnableEurekaServer 어노테이션을 추가 합니다.

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

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

}


설정을 마쳤다면, 바로 Run해 봅니다.

만약 아래와 같은 에러가 발생한다면, 

java.lang.TypeNotPresentException: Type javax.xml.bind.JAXBContext not present
	at java.base/sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:117) ~[na:na]
	at java.base/sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:125) ~[na:na]
	at java.base/sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49) ~[na:na]
	at java.base/sun.reflect.generics.visitor.Reifier.reifyTypeArguments(Reifier.java:68) ~[na:na]
	at java.base/sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:138) ~[na:na]
	at java.base/sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49) ~[na:na]
	at java.base/sun.reflect.generics.repository.ClassRepository.computeSuperInterfaces(ClassRepository.java:117) ~[na:na]
	at java.base/sun.reflect.generics.repository.ClassRepository.getSuperInterfaces(ClassRepository.java:95) ~[na:na]
	at java.base/java.lang.Class.getGenericInterfaces(Class.java:1138) ~[na:na]

다음을 build.gradle에 추가해 주시면 됩니다.

	implementation 'javax.xml.bind:jaxb-api:2.3.0'
	implementation 'org.glassfish.jaxb:jaxb-runtime:2.3.0'
	implementation 'javax.activation:activation:1.1.1'

이제 정상적으로 Run이 되는 것을 확인 하실 수 있습니다.
정상적으로 동작하는지 확인을 위해 브라우저에 [http://localhost:8761]을 입력하고 아래와 같은 화면이 뜬다면 일단 성공입니다.

 

Step 3. Service 등록을 위한 설정

Eureka Server가 마련되었다면, 이제 client들 즉, service들을 설정해 주어야 합니다. 모든 설정을 default로 할 것이기에 이 또한 어렵지 않습니다. 먼저, 기존의 서비스들 모두에 eureka client를 추가해 주어야 합니다.

implementation 'org.springframework.cloud:spring-cloud-starter-eureka'

혹시 에러 나면, [org.springframework.cloud:spring-cloud-starter-eureka:1.4.6.RELEASE]를 사용하시면 됩니다.

이제 각 서비스들의 이름을 각각의 application.properties파일에 아래와 같이 적어 줍니다.

spring.application.name=microservice-a

저는 UserName을 알려줄 서비스를 [microservice-a]로 하고, 이를 호출할 UserInfo 서비스를 [microservice-b]로 설정했습니다. 
이는 eureka 서버에 등록될 이름이며, feign, ribbon에서 사용할 이름입니다.

다음으로 Application 클래스에 @EnableDiscoveryClient 어노테이션을 추가합니다.

@EnableDiscoveryClient
@SpringBootApplication
public class ServiceAApplication {

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

}

이제 서비스들을 실행하면 자동으로 Eureka Server에 추가되는 것을 볼 수 있습니다.

브라우저를 리로드 해 보시면 서비스가 추가된 것을 볼 수 있습니다.

중간 아래쯤 [Instances currently registered with Eureka]에 보시면 [MICROSERVICE-A]라고 추가 된 것을 볼 수 있습니다.

 

Step 4. Service들 등록

이 상태에서 우리는 아래와 같이 서비스들을 등록해 보겠습니다.

  1. Config-Server
  2. Microservice-a 2개(8080, 8081)
  3. Microservice-b

모든 서비스들을 등록한 상태입니다.

[MICROSERVICE-A]를 보시면 Availability Zones와 Status에 2개가 등록된 것을 보실 수 있습니다. 동일한 이름으로 등록하였기에 이와 같이 노출됩니다.

이제 Eureka를 이용해 서비스들을 한곳에서 등록하고 관리 할 수 있도록 되었습니다. 그럼 이 상태에서 기존과 동일하게 서비스 B가 A의 서비스를 호출할 수 있도록 설정으 조금 더 변경해 보겠습니다.

다른 부분은 바꿀 필요학 없으며, 호출 할 Service-B만 수정하시면 됩니다.

@FeignClient(name="microservice-a")
public interface UserServiceProxy {
    @RequestMapping(value = "/getUserName", method = RequestMethod.GET)
    public Map<String, String> getUserName();
}

서비스 B의 UserSeviceProxy의 @FeignClient 어노테이션의 name을 Eureka 등록 이름과 동일하게 변경해 주시면 됩니다. 사실 처음 작성한 이름과 동일하게 세팅했다면 변경하지 않아도 되지만, 개념과 과정을 익히기 위해 바꾸었습니다. 변경 후 서비스를 내렸다 올리시면 자동으로 Eureka Server에 등록되고 사용이 가능합니다.

 

Step 5. Test

위와 같이 모든 설정이 마무리 되었다면, 기존과 같이 service-b(8090)의 getUserInfo를 호출해면 다음과 같이 값을 잘 받아 오는 것을 보실 수 있습니다. 내부적으로 user-name은 service-a(8080, 8081)의 호출해서 받아온 값입니다.

여러번 호출하여, service-a의 8080과 8081 로그를 확인해 보시면 로드밸런싱도 잘 된다는 것을 알 수 있습니다.

이 상태에서 만약 Eureka Server과 다운되면 어떻게 될까요?
실제로 Eureka Server을 중단하고 Service-B를 호출 했을 때, 잘 작동하는 것을 확인 하였습니다. 처음 서버에 접속후 캐싱을 해서 주소값들을 가지고 있는 듯 합니다.

아래는 Service-B의 로그입니다. 자세히 살펴보면, 5분마다 한번씩 Resolving eureka endpoints via configuration이 처리되고 있음을 볼 수 있으며, 서비스 호출시 ribbon과 loadbalancer의 처리도 볼 수 있습니다.

2019-05-19 15:23:58.362  INFO 3238 --- [  restartedMain] com.netflix.discovery.DiscoveryClient    : Discovery Client initialized at timestamp 1558247038361 with initial instances count: 3
2019-05-19 15:23:58.363  INFO 3238 --- [  restartedMain] o.s.c.n.e.s.EurekaServiceRegistry        : Registering application MICROSERVICE-B with eureka with status UP
2019-05-19 15:23:58.363  INFO 3238 --- [  restartedMain] com.netflix.discovery.DiscoveryClient    : Saw local status change event StatusChangeEvent [timestamp=1558247038363, current=UP, previous=STARTING]
2019-05-19 15:23:58.365  INFO 3238 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_MICROSERVICE-B/172.30.1.23:microservice-b:8090: registering service...
2019-05-19 15:23:58.389  INFO 3238 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_MICROSERVICE-B/172.30.1.23:microservice-b:8090 - registration status: 204
2019-05-19 15:23:58.406  INFO 3238 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8090 (http) with context path ''
2019-05-19 15:23:58.407  INFO 3238 --- [  restartedMain] .s.c.n.e.s.EurekaAutoServiceRegistration : Updating port to 8090
2019-05-19 15:23:58.414  INFO 3238 --- [  restartedMain] c.z.msa.serviceb.ServiceBApplication     : Started ServiceBApplication in 4.04 seconds (JVM running for 10.214)
2019-05-19 15:23:58.764  INFO 3238 --- [(3)-172.30.1.23] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-05-19 15:23:58.764  INFO 3238 --- [(3)-172.30.1.23] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2019-05-19 15:23:58.775  INFO 3238 --- [(3)-172.30.1.23] o.s.web.servlet.DispatcherServlet        : Completed initialization in 11 ms
2019-05-19 15:28:58.227  INFO 3238 --- [trap-executor-0] c.n.d.s.r.aws.ConfigClusterResolver      : Resolving eureka endpoints via configuration
2019-05-19 15:33:36.641  INFO 3238 --- [nio-8090-exec-1] c.netflix.config.ChainedDynamicProperty  : Flipping property: microservice-a.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2019-05-19 15:33:36.670  INFO 3238 --- [nio-8090-exec-1] c.n.u.concurrent.ShutdownEnabledTimer    : Shutdown hook installed for: NFLoadBalancer-PingTimer-microservice-a
2019-05-19 15:33:36.671  INFO 3238 --- [nio-8090-exec-1] c.netflix.loadbalancer.BaseLoadBalancer  : Client: microservice-a instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=microservice-a,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null
2019-05-19 15:33:36.678  INFO 3238 --- [nio-8090-exec-1] c.n.l.DynamicServerListLoadBalancer      : Using serverListUpdater PollingServerListUpdater
2019-05-19 15:33:36.701  INFO 3238 --- [nio-8090-exec-1] c.netflix.config.ChainedDynamicProperty  : Flipping property: microservice-a.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2019-05-19 15:33:36.703  INFO 3238 --- [nio-8090-exec-1] c.n.l.DynamicServerListLoadBalancer      : DynamicServerListLoadBalancer for client microservice-a initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=microservice-a,current list of Servers=[172.30.1.23:8080, 172.30.1.23:8081],Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone;	Instance count:2;	Active connections count: 0;	Circuit breaker tripped count: 0;	Active connections per server: 0.0;]
},Server stats: [[Server:172.30.1.23:8081;	Zone:defaultZone;	Total Requests:0;	Successive connection failure:0;	Total blackout seconds:0;	Last connection made:Thu Jan 01 09:00:00 KST 1970;	First connection made: Thu Jan 01 09:00:00 KST 1970;	Active Connections:0;	total failure count in last (1000) msecs:0;	average resp time:0.0;	90 percentile resp time:0.0;	95 percentile resp time:0.0;	min resp time:0.0;	max resp time:0.0;	stddev resp time:0.0]
, [Server:172.30.1.23:8080;	Zone:defaultZone;	Total Requests:0;	Successive connection failure:0;	Total blackout seconds:0;	Last connection made:Thu Jan 01 09:00:00 KST 1970;	First connection made: Thu Jan 01 09:00:00 KST 1970;	Active Connections:0;	total failure count in last (1000) msecs:0;	average resp time:0.0;	90 percentile resp time:0.0;	95 percentile resp time:0.0;	min resp time:0.0;	max resp time:0.0;	stddev resp time:0.0]
]}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@6d91e05a
2019-05-19 15:33:37.685  INFO 3238 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty  : Flipping property: microservice-a.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2019-05-19 15:33:58.236  INFO 3238 --- [trap-executor-0] c.n.d.s.r.aws.ConfigClusterResolver      : Resolving eureka endpoints via configuration
2019-05-19 15:38:58.241  INFO 3238 --- [trap-executor-0] c.n.d.s.r.aws.ConfigClusterResolver      : Resolving eureka endpoints via configuration

 

다음으로는 api-gateway를 살펴보도록 하겠습니다.

 

[MSA]1. Config Server를 통한 설정 관리
[MSA]2. 메시지 브로커를 통한 설정값 관리
[MSA]3. 마이크로 서비스 간 호출 #1 - Feign
[MSA]4. 마이크로 서비스 간 호출 #2 - Ribbon
[MSA]5. Eureka를 통한 서비스 관리

 

 

반응형
Comments