「Spring Cloud Gateway」を真似てGatewayを作成



この投稿には、公式ドキュメントのSpring Cloud Gatewayページの練習が含まれています.
(詳細については、下部リンク)を参照してください.
n/a.ターゲット
|使用
  • Building a Gateway構築ゲートウェイ
  • 準備物
  • 約15分
  • お気に入りのテキストエディタまたはIDE
  • JDK 1.8以上
  • Gradle 4またはMaven 3.2以上
  • 実践方法
  • 使用Spring Cloud Gateway最初から
  • 基本的な知識をスキップするには、次の手順に従います.
  • Spring Initializrパスソースをコピーまたはダウンロードして解凍
  • git clone https://github.com/spring-guides/gs-gateway.gitフォルダへ移動
  • 練習終了後gs-gateway/initialフォルダで結果を比較可能
  • Spring Initializerを使用したプロジェクトの作成

    単純ルーティングの作成
    1.最初のルーティングを追加
    1) SpringCloudGatewayApplication.java
    package com.meun2.scg.study;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.gateway.route.RouteLocator;
    import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
    import org.springframework.context.annotation.Bean;
    
    @SpringBootApplication
    public class SpringCloudGatewayApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(SpringCloudGatewayApplication.class, args);
    	}
    
    	@Bean
    	public RouteLocator myRoutes(RouteLocatorBuilder builder) {
    		return builder.routes().build();
    	}
    }
    
    @Bean
    public RouteLocator myRoutes(RouteLocatorBuilder builder) {
    	return builder.routes()
    			.route(p -> p
    					.path("/get")
    					.filters(f -> f.addRequestHeader("Hello", "World"))
    					.uri("http://httpbin.org:80"))
    			.build();
    }
    2)CURLによるデータ検証
    $ curl http://localhost:7070/get	
    端末に上記コマンドを入力して正常に動作している場合は、下記のようにクエリ結果値が表示されます.
    2.Circuit Breakerの追加
    1) build.gradle
    implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j'
    2) SpringCloudGatewayApplication.java
    @Bean
    public RouteLocator myRoutes(RouteLocatorBuilder builder) {
    	return builder.routes()
    			.route(p -> p
    					.path("/get")
    					.filters(f -> f.addRequestHeader("Hello", "World"))
    					.uri("http://httpbin.org:80"))
    			.route(p -> p
    					.host("*.circuitbreaker.com")
    					.filters(f -> f.circuitBreaker(config -> config.setName("mycmd")))
    					.uri("http://httpbin.org:80"))
    			.build();
    }
    3)CURLテストを行う
    $ curl --dump-header - --header 'Host: www.circuitbreaker.com' http://localhost:7070/delay/3

    3.FallBackの追加
    1) SpringCloudGatewayApplication.java
    package com.meun2.scg.study;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.gateway.route.RouteLocator;
    import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import reactor.core.publisher.Mono;
    
    @RestController
    @SpringBootApplication
    public class SpringCloudGatewayApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(SpringCloudGatewayApplication.class, args);
    	}
    
    	@Bean
    	public RouteLocator myRoutes(RouteLocatorBuilder builder) {
    		return builder.routes()
    				.route(p -> p
    						.path("/get")
    						.filters(f -> f.addRequestHeader("Hello", "World"))
    						.uri("http://httpbin.org:80"))
    				.route(p -> p
    						.host("*.circuitbreaker.com")
    						.filters(f -> f.circuitBreaker(config -> config
    								.setName("mycmd")
    								.setFallbackUri("forward:/fallback")))
    						.uri("http://httpbin.org:80"))
    				.build();
    	}
    
    	@RequestMapping("/fallback")
    	public Mono<String> fallback() {
    		return Mono.just("fallback");
    	}
    }
    3)CURLテストを行う
    $ curl --dump-header - --header 'Host: www.circuitbreaker.com' http://localhost:8080/delay/3
    
    HTTP/1.1 200 OK
    transfer-encoding: chunked
    Content-Type: text/plain;charset=UTF-8
    
    fallback
    4.分離HttpBin依存性
    1) SpringCloudGatewayApplication.java
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.cloud.gateway.route.Route;
    import org.springframework.cloud.gateway.route.RouteLocator;
    import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import reactor.core.publisher.Mono;
    
    @SpringBootApplication
    @RestController
    @EnableConfigurationProperties(UriConfiguration.class)
    public class SpringCloudGatewayApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(SpringCloudGatewayApplication.class, args);
    	}
    
    	@Bean
    	public RouteLocator myRoutes(RouteLocatorBuilder builder, UriConfiguration uriConfiguration) {
    		String httpUri = uriConfiguration.getHttpbin();
    		return builder.routes()
    				.route(p -> p
    						.path("/get")
    						.filters(f -> f.addRequestHeader("Hello", "World"))
    						.uri(httpUri))
    				.route(p -> p
    						.host("*.circuitbreaker.com")
    						.filters(f -> f
    								.circuitBreaker(config -> config
    										.setName("mycmd")
    										.setFallbackUri("forward:/fallback")))
    						.uri(httpUri))
    				.build();
    	}
    
    	@RequestMapping("/fallback")
    	public Mono<String> fallback() {
    		return Mono.just("fallback");
    	}
    }
    
    @ConfigurationProperties
    class UriConfiguration {
    	private String httpbin = "http://httpbin.org:80";
    
    	public String getHttpbin() {
    		return httpbin;
    	}
    
    	public void setHttpbin(String httpbin) {
    		this.httpbin = httpbin;
    	}
    }
    5.テストコードの作成
    1) SpringCloudGatewayApplication.java
    package com.meun2.scg.study;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
    import org.springframework.test.web.reactive.server.WebTestClient;
    
    import static com.github.tomakehurst.wiremock.client.WireMock.*;
    import static org.assertj.core.api.Assertions.*;
    
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {"httpbin=http://localhost:${wiremock.server.port}"})
    @AutoConfigureWireMock(port = 0)
    class SpringCloudGatewayApplicationTests {
    
    	@Autowired
    	private WebTestClient webClient;
    
    	@Test
    	void contextLoads() throws Exception {
    		// Stubs
    		stubFor(get(urlEqualTo("/get"))
    				.willReturn(aResponse()
    						.withBody("{\"headers\":{\"Hello\":\"World\"}}")
    						.withHeader("Content-Type", "application/json")));
    		stubFor(get(urlEqualTo("/delay/3"))
    				.willReturn(aResponse()
    						.withBody("no fallback")
    						.withFixedDelay(3000)));
    
    		webClient
    				.get().uri("/get")
    				.exchange()
    				.expectStatus().isOk()
    				.expectBody()
    				.jsonPath("$.headers.Hello").isEqualTo("World");
    
    		webClient
    				.get().uri("/delay/3")
    				.header("Host", "www.circuitbreaker.com")
    				.exchange()
    				.expectStatus().isOk()
    				.expectBody()
    				.consumeWith(
    						response -> assertThat(response.getResponseBody()).isEqualTo("fallback".getBytes()));
    	}
    
    }
    リファレンス
  • [Spring Cloud Gateway] Building a Gateway