
Discovery Service
등록되어 있으면서, 찾을 수 있는 서비스
register-with-eureka
클라이언트가 자신을 Eureka 서버에 등록할지 여부를 결정
fetch-registry
Eureka서버로부터 인스턴스들의 정보를 주기적으로 가져올 것인지를 설정
Eureka 서버에서 아래와 같이 설정을 하는 이유는 설정의 기본 값이 true인 반면에, Eureka서버는 Client로 등록하지 않기 때문이다.
eureka:
client:
register-with-eureka: false
fetch-registry: false
eureka:
instance:
instance-id: ${spring.cloud.client.hostname}:${spring.application.instance_id:${random.value}}
client:
fetch-registry: true
register-with-eureka: true
다른 서비스의 RESTful API에 HTTP 요청을 보내고, 응답을 받아올 수 있는 방식의 RestTemplate은 아래와 같이 작성한다.
ResponseEntity<String> response = restTemplate.getForEntity("http://api.example.com/users", String.class);
if (response.getStatusCode().isSuccessful()) {
String responseBody = response.getBody();
} else {
throw new Exception(...);
}
Interface를 만들고, 호출하고 싶은 MicroService의 이름을 등록해서 호출 가능한 Feign Client는 아래와 같이 작성한다.
유저 서비스 예시 -> 유저가 Order서비스를 가지고 있는 것처럼 사용할 수 있다.
편하게 사용 가능
@FeignClient("order")
public interface OrderClient{
@RequestMapping(method=RequestMethod.GET, value="/order")
List<Order> getOrder();
}
Neflix의 Ribbon이라는 서비스를 사용했었지만, 최근 Functional Programming과 잘 맞지 않기 때문에 (비동기처리가 잘 X)그래서 사용을 잘X
Maintaning이 돼서 Spring Cloud 사용
public class CustomFilter extends AbstractGatewayFilterFactory<CustomFilter.Config> {
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
log.info("Custom Pre Filter: Request URI -> {}", request.getId());
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("Custom Post Filter: Response code -> {}", response.getStatusCode());
}));
};
}
아래의 방식은 따로 Custom Filter를 만들지 않고 적용하는 방식이다.
spring:
cloud:
gateway:
routes:
- id: user
uri: http://localhost:8080/
predicates:
- Path=/users/**
filters:
//request와 request-header는 Key, Value의 형태다.
-AddRequestHeader=user-request, user-request-header
-AddResponseHeader=user-response, user-response-header
- id: order
uri: http://localhost:8082/
predicates:
- Path=/orders/**
filters:
//request와 request-header는 Key, Value의 형태다.
-AddRequestHeader=order-request, order-request-header
-AddResponseHeader=order-response, order-response-header
아래의 방식은 Custom Filter을 만든 후 적용하는 방식이다. 인자 값이 없는 Filter
spring:
cloud:
gateway:
routes:
- id: user
uri: http://localhost:8080/
predicates:
- Path=/users/**
filters:
- CustomFilter
- id: order
uri: http://localhost:8082/
predicates:
- Path=/orders/**
filters:
- CustomFilter
아래처럼 default-filters 속성을 사용해서 커스터마이징한 Filter와 Config의 속성들에 값을 넣어주면 되고, 추가적으로 인자 값이 필요하기 때문에 주입해줘야 한다.
Ordered.HIGHEST_PRECEDENCE 또는 Ordered.LOWEST_PRECEDENCE 키워드는 Filter의 순서를 설정해준다. Ordered.HIGHEST_PRECEDENCE은 먼저, Ordered.LOWEST_PRECEDENCE는 가장 나중에 실행이 된다고 생각하면 됨
@Component
@Slf4j
public class LoggingFilter extends AbstractGatewayFilterFactory<LoggingFilter.Config> {
public LoggingFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
GatewayFilter filter = new OrderedGatewayFilter((exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
log.info("Logging Filter baseMessage = {}", config.getBaseMessage());
//Pre Filter
if (config.preLogger) {
log.info("Pre Filter Request ID = {}", request.getId());
}
//Post Filter
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
if (config.postLogger) {
log.info("Post Filter Response Code = {}", response.getStatusCode());
}
}));
},Ordered.HIGHEST_PRECEDENCE);
return filter;
}
//Config 클래스 static인 것에 주의
@Data
public static class Config {
//아래의 속성들은 application.yml에서 주입
private String baseMessage;
private boolean preLogger;
private boolean postLogger;
}
}
spring:
application:
name: api-gateway
cloud:
gateway:
default-filters:
- name: LoggingFilter
args:
baseMessage: Logging Filter
preLogger: true
postLogger: true
routes:
- id: user
uri: http://localhost:8080/
predicates:
- Path=/users/**
eureka:
instance:
instance-id: ${spring.cloud.client.hostname}:${spring.application.instance_id:${random.value}}
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://localhost:8761/eureka