Java | Spring Boot | API Gateway
Java Spring Boot
Routing
Spring Bootアプリケーションでは、HTTPリクエストをルーティングするために、@RestControllerや@Controllerアノテーションを使用してコントローラを定義する。これにより、異なるエンドポイントへのルーティングが可能となる。
@RestController
public class MyRouter {
@GetMapping("/service1")
public String handleService1() {
return "Service 1 Response";
}
@GetMapping("/service2")
public String handleService2() {
return "Service 2 Response";
}
}
Mavenで@RestController や @Controller アノテーションを使用するためには、pom.xml に以下の依存関係を追加する。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Gateway
Spring Cloud Gatewayを使用することで、APIゲートウェイを簡単に構築できる。
Spring Cloud Gatewayは、ルーティング、フィルタリング、リクエスト/レスポンスの変換などを行う。
- pom.xml に以下の依存関係を追加する。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
- application.yml または application.properties にGateway設定を追加する。
(application.ymlで設定する場合)
spring:
cloud:
gateway:
routes:
- id: service1
uri: http://localhost:8081
predicates:
- Path=/service1
- id: service2
uri: http://localhost:8082
predicates:
- Path=/service2
(application.propertiesで設定する場合)
# application.yml での設定を application.properties 形式に変換するには、
# YAMLの階層構造をドット表記で表現する。
# routes[0] と routes[1] はそれぞれのルートのインデックスを示している。
# predicates[0] は、各ルートの条件を示している。
spring.cloud.gateway.routes[0].id=service1
spring.cloud.gateway.routes[0].uri=http://localhost:8081
spring.cloud.gateway.routes[0].predicates[0]=Path=/service1
spring.cloud.gateway.routes[1].id=service2
spring.cloud.gateway.routes[1].uri=http://localhost:8082
spring.cloud.gateway.routes[1].predicates[0]=Path=/service2
/service1
へのリクエストは http://localhost:8081
に、
/service2
へのリクエストは http://localhost:8082
にルーティングされるようになる。
リクエストフィルタリング
リクエストフィルタリングは、クライアントからのリクエストがバックエンドサービスに到達する前に行われる処理。これにより、リクエストの内容を検査し、必要に応じて変更や制限を加えることができる。
目的 | 内容 |
---|---|
認証と認可 | リクエストが正当なものであるかどうかを確認する。例えば、APIキーやJWTトークンの検証を行うなど。 |
リクエストの変換 | リクエストパラメータやヘッダーの値を変更する。たとえば、特定のヘッダーを追加したり、値を変換したりする。 |
レート制限 | クライアントのリクエスト数を制限し、サービスの過負荷を防ぐ。 |
- application.yml または application.properties にGateway設定を追加する。
(application.ymlで設定する場合)
spring:
cloud:
gateway:
routes:
- id: my_route
uri: http://localhost:8081
predicates:
- Path=/service
filters:
- AddRequestHeader=X-Request-Foo, Bar
- RewritePath=/service, /
(application.propertiesで設定する場合)
spring.cloud.gateway.routes[0].id=my_route
spring.cloud.gateway.routes[0].uri=http://localhost:8081
spring.cloud.gateway.routes[0].predicates[0]=Path=/service
spring.cloud.gateway.routes[0].filters[0]=AddRequestHeader=X-Request-Foo, Bar
spring.cloud.gateway.routes[0].filters[1]=RewritePath=/service, /
/service へのリクエストが http://localhost:8081
に転送される際に、AddRequestHeaderフィルタによりX-Request-Foo
ヘッダーが追加され、RewritePatフィルタによりパスが /service
から /
にリライトするリライトされる。
レスポンスフィルタリング
レスポンスフィルタリングは、バックエンドサービスからのレスポンスがクライアントに返される前に行われる処理。これにより、レスポンスの内容を変更したり、特定のデータを除外したりすることができる。
目的 | 内容 |
---|---|
データの整形 | レスポンスデータの形式を変更することが可能。たとえば、JSONデータのフィールドを追加したり、削除したりできる。 |
エラーハンドリング | エラーレスポンスをカスタマイズし、クライアントに返す内容を明確にすることができる。 |
統計情報の追加 | レスポンスに処理時間やトラフィック情報などのメタデータを追加できる。 |
Spring Cloud Gatewayでは、AddResponseHeaderフィルタを使用してレスポンスヘッダーを追加することができる。
(application.ymlで設定する場合)
spring:
cloud:
gateway:
routes:
- id: my_route
uri: http://localhost:8081
predicates:
- Path=/service
filters:
- AddResponseHeader=X-Response-Foo, Bar
(application.propertiesで設定する場合)
spring.cloud.gateway.routes[0].id=my_route
spring.cloud.gateway.routes[0].uri=http://localhost:8081
spring.cloud.gateway.routes[0].predicates[0]=Path=/service
spring.cloud.gateway.routes[0].filters[0]=AddResponseHeader=X-Response-Foo, Bar
AddResponseHeaderフィルタによって、バックエンドのhttp://localhost:8081
からのレスポンスにX-Response-Foo: Bar
ヘッダーが追加される。
レスポンス内容の変換
レスポンス内容を変更するために、ModifyResponseBodyフィルタを使用することが可能。
このフィルタを使用すると、レスポンスのボディを特定の条件に基づいて変更することができる。
- 以下は、JSONレスポンスの特定のフィールドを変更する例。
(application.ymlで設定する場合)
spring:
cloud:
gateway:
routes:
- id: my_route
uri: http://localhost:8081
predicates:
- Path=/service
filters:
- ModifyResponseBody=Object
(application.propertiesで設定する場合)
spring.cloud.gateway.routes[0].id=my_route
spring.cloud.gateway.routes[0].uri=http://localhost:8081
spring.cloud.gateway.routes[0].predicates[0]=Path=/service
spring.cloud.gateway.routes[0].filters[0]=ModifyResponseBody=Object
ModifyResponseBodyフィルタを使用して、レスポンスボディをオブジェクトとして扱い、変更を加えることが可能。具体的な変換ロジックは、Javaでカスタムフィルタを作成することで実装できる。
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class CustomResponseFilter extends AbstractGatewayFilterFactory<CustomResponseFilter.Config> {
public CustomResponseFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
// レスポンスをフィルタリング
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
// レスポンスのボディを変更するロジック
exchange.getResponse().getHeaders().add("X-Custom-Header", "CustomValue");
}));
};
}
public static class Config {
// 任意の設定
}
}
このカスタムフィルタは、レスポンスヘッダーにX-Custom-Header
を追加する。
このカスタムフィルタを使用するために、Spring Cloud Gatewayのルート設定でこのカスタムフィルタを指定する。
(application.ymlで設定する場合)
spring:
cloud:
gateway:
routes:
- id: my_route
uri: http://localhost:8081
predicates:
- Path=/service
filters:
- name: CustomResponseFilter
(application.propertiesで設定する場合)
spring.cloud.gateway.routes[0].id=my_route
spring.cloud.gateway.routes[0].uri=http://localhost:8081
spring.cloud.gateway.routes[0].predicates[0]=Path=/service
spring.cloud.gateway.routes[0].filters[0].name=CustomResponseFilter
リクエストのパスとレスポンスのステータスコードをコンソールに表示するカスタムフィルタ
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
@Component
public class CustomFilter extends AbstractGatewayFilterFactory<CustomFilter.Config> {
public CustomFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
// リクエスト処理
System.out.println("Request Path: " + exchange.getRequest().getURI().getPath());
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
// レスポンス処理
System.out.println("Response Status Code: " + exchange.getResponse().getStatusCode());
}));
};
}
public static class Config {
// 任意の設定
}
}
このカスタムフィルタは、リクエストのパスとレスポンスのステータスコードをコンソールに表示する。
LoadBalancer
Spring Cloud LoadBalancerを使用することで、サービス間の負荷分散を実現できる。
これにより、複数のインスタンスにリクエストを分散させることが可能となる。
- pom.xml に以下の依存関係を追加する。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
- RestTemplateを使用して、サービスを呼び出す際にLoadBalancerを利用できるようになる。
@RestController
public class MyLoadBalancedService {
@Autowired
private RestTemplateBuilder restTemplateBuilder;
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return restTemplateBuilder.build();
}
@GetMapping("/callService")
public String callService() {
String response = restTemplate().getForObject("http://my-service/service-endpoint", String.class);
return response;
}
}
http://my-service/service-endpoint
へのリクエストが複数のインスタンスに負荷分散される。
Discussion