개발블로그

spring cloud api-gateway 사용하기 본문

Spring

spring cloud api-gateway 사용하기

개발자수니 2019. 12. 24. 14:57

MSA 기반으로 프로젝트를 구성하면, 파생되는 여러가지 단점(?)이 있다. 

이를테면, 각 서비스마다 호스트가 달라서 생기는 불편함이 있다. 각 서비스의 API들을 호출하는 쪽에서 서비스에 따라 어떤 호스트로 요청해야할지 신경 써야하기 때문이다.

 

따라서 MSA로 프로젝트를 구성하려 한다면, Service Mesh Architecture도 함께 고려해야한다. 

그 중 하나가 api-gateway이다. 

api-gateway의 역할 중 하나는 요청 URL에 따라 어떤 서비스로 요청을 라우팅할지 관리하는 것이다.

다시 말해, API를 호출하는 쪽에서는 api-gateway로만 요청을 전송한다. 실제로 요청이 어느 서비스에 라우팅시킬지 결정하는 것은 api-gateway의 역할이다. 

 


Api Gateway 서버 세팅


1. 사용할 spring-cloud version을 pom.xml의 dependencyManagement에 등록.

<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-dependencies</artifactId>
			<version>Greenwich.SR2</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>

 

2. api gateway을 pom.xml의 dependency에 추가.

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

 

3. Main class에 @EnableDiscoveryClient Setting

@EnableDiscoveryClient
@SpringBootApplication
class AirGatewayApplication

fun main(args: Array<String>) {
	runApplication<AirGatewayApplication>(*args)
}

 

4. Routes Setting

@Configuration
class Routes {
    @Bean
    fun myroutes(routeLocatorBuilder: RouteLocatorBuilder): RouteLocator =
            routeLocatorBuilder.routes {
                route{
                    path("/auth/**")
                    uri("lb://air-auth/") //eureka를 사용할 경우
                }
                route{
                    path("/topic/**")
                    uri("http://localhost:8083") //eureka를 사용하지 않을 경우
                }
            }
}

현재 프로젝트에서는 service mesh 요소 중 하나인 eureka를 사용하고 있어서 url을 eureka에 등록된 서비스로 설정했는데, 그게 아니라면 url을 입력하면 된다. 

 


이와 같이 api-gateway를 설정하는 것은 간단하다. 

그러나 문제가 있다. Routes 정보가 코드에 있다는 점이다.

따라서 이 정보를 MongoDB에 올려놓고, Routes에서는 조회해서 사용하도록 변경했다. 

 

@Configuration
class Routes(val repository: ApiRequestRepository) {
    @Bean
    fun myroutes(routeLocatorBuilder: RouteLocatorBuilder) =
        routeLocatorBuilder.routes {
            repository.findAll().forEach { apiRequest ->
                route {
                    path(apiRequest.path)
                    uri(apiRequest.uri)
                }
            }
        }

}

 

위 코드에서 사용된 ApiRequest는 uri와 path를 가진 DTO이다. 

@Document("ApiRequest")
data class ApiRequest(val path: String,
                      val uri: String) {
}

 

하지만, 여전히 문제점은 남아있다. 

DB정보가 수정되었을 때, 수정본을 반영하지 않는다는 점이다. 이에 대해서는 공부 후, 다루겠다. 

Comments