with-RL
프로그램 / Java2024년 1월 20일

Spring Boot Micro Service Architecture 만들기 (2)

이 포스트는 이전 포스트에서 생성한 Spring Boot MSA 프로젝트를 기반으로 Load Balancing 테스트와 Log 기능을 만들어 보는 과정에 대한 설명입니다.

이 포스트는 다음 과정을 완료한 후에 참고하시길 바랍니다.

1. Gradle 빌드

2. Load Balancing 테스트

$ java "-Dspring.profiles.active=local" -jar .\app-eureka\build\libs\app-eureka-1.0.0.jar
$ java "-Dspring.profiles.active=local" -jar .\app-gateway\build\libs\app-gateway-1.0.0.jar
$ java "-Dspring.profiles.active=local" -jar .\app-web\build\libs\app-web-1.0.0.jar

3. Log 기능 추가

3.1. app-core에 MSAContext 클래스 생성

package com.mymsa.core.context;

import org.apache.commons.lang.RandomStringUtils;

public class MSAContext {

    private final String sessionID;

    public MSAContext() {
        this.sessionID = RandomStringUtils.randomAlphabetic(8);
    }

    public MSAContext(String sessionID) {
        this.sessionID = sessionID != null ? sessionID : RandomStringUtils.randomAlphabetic(8);
    }

    @Override
    public String toString() {
        return sessionID;
    }

}

3.2. app-gateway에 GlobalFilter 클래스 생성

package com.mymsa.gateway.filter;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

@Component
@Slf4j
public class GlobalFilter extends AbstractGatewayFilterFactory<GlobalFilter.Config> {

    public GlobalFilter() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            String sessionID = RandomStringUtils.randomAlphabetic(8);
            ServerHttpRequest request = exchange.getRequest().mutate()
                    .header("sessionID", sessionID)
                    .build();
            log.info("{}|gateway-begin|Y|src={},uri={},ms=", sessionID, exchange.getRequest().getRemoteAddress(), exchange.getRequest().getURI());
            return chain.filter(exchange.mutate().request(request).build())
                    .then(Mono.fromRunnable(() -> {
                        int code = exchange.getResponse().getStatusCode().value();
                        boolean result = code == 200;
                        log.info("{}|gateway-end|{}|code={}", sessionID, result ? "Y" : "N", code);
                    }));
        };
    }

    @Data
    public static class Config {
    }

}
      default-filters:
        - name: GlobalFilter

3.3. app-web의 HelloController 클래스 수정

package com.mymsa.web.controller;

import com.mymsa.core.context.MSAContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

@RequestMapping("/app-web")
@RestController
@Slf4j
public class HelloController {

    @GetMapping("/hello")
    public Mono<String> hello(@RequestHeader(value="sessionID", required=false) String sessionID) {
        MSAContext context = new MSAContext(sessionID);
        log.info("{}|hello-request||", context);
        return Mono.just("Hello: " + System.currentTimeMillis())
                .doOnSuccess(result -> {
                    log.error("{}|hello-request|Y|{}", context, result);
                })
                .doOnError(error -> {
                    log.error("{}|hello-request|N|", context, error);
                });
    }

}

4. Load Balancing 테스트 (Log 기능 확인)

$ java "-Dspring.profiles.active=local" -jar .\app-eureka\build\libs\app-eureka-1.0.0.jar
$ java "-Dspring.profiles.active=local" -jar .\app-gateway\build\libs\app-gateway-1.0.0.jar
$ java "-Dspring.profiles.active=local" -jar .\app-web\build\libs\app-web-1.0.0.jar

참고

이 포스트와 관련 포스트 입니다.