Create a microservices application architecture with Spring Boot and Spring Cloud - Part 6 - Proxy service & API gateway

Introduction

This part of the tutorial is going to focus primarily on the proxy service that we're going to create that will also be the API gateway in which we can access both the General and Minnesota services through one domain instead of separate domains (ports in case).

Overview

The proxy/API gateway sits before the General and Minnesota services and will only serve as the API gateway for those services.  As we add more business domain services, then we would add them to the API gateway config.  The proxy also allows us to properly use Swagger due to some library limitations with other API gateway libraries.  Below is a general look at how the proxy/API gateway will work:

Tutorial

1.)  Create a new Spring Boot app called proxy_service. Make sure Gradle is used.

2.)  Open up the build.gradle file.

3.)  Remove the content that’s currently in the build.gradle file and then add the following to the file instead:

buildscript {
	ext {
		springBootVersion = '2.1.2.RELEASE'
	}
	repositories {
		mavenCentral()
	}
	dependencies {
		classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
	}
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

group = 'com.bryanlor'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
	mavenCentral()
	maven { url "https://repo.spring.io/milestone" }
}

ext['springCloudVersion'] = 'Greenwich.RC2'

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter'
	compile('org.springframework.cloud:spring-cloud-starter-config')
	compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
	compile('org.springframework.cloud:spring-cloud-starter-netflix-zuul')
	compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2'
	compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'
	compile('org.springframework.cloud:spring-cloud-starter-sleuth')
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

dependencyManagement {
	imports {
		mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
	}
}

4.)  Save the file.

5.)  Right click on the project and go to Gradle → Refresh Gradle Project.  You can also use the gradle commands in the command-line to build the project so that it pulls in the dependencies needed.

 

6.)  Open up ProxyServiceApplication.java and insert the following import statements:

import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

7.)  Then below @SpringBootApplication, add the following annotations and resolve any imports required for the annotation:

@EnableZuulProxy
​​​​​​​@EnableSwagger2

 

8.)  Create a new class called, ProxyApi, within the same package location as your ProxyServiceApplication class.

 

9.)  On the line before the class declaration, insert the following annotation:

@Configuration

 

10.)  In the body of the class, insert the following code:

	@Autowired
	ZuulProperties properties;
	
	@Primary
	@Bean
	public SwaggerResourcesProvider swaggerResourcesProvider() {
		return () -> {
			List<SwaggerResource> resources = new ArrayList<>();
			properties.getRoutes().values().stream()
					.forEach(route -> resources.add(createResource(route.getServiceId(), route.getId(), "2.0")));
			return resources;
		};
	}

	private SwaggerResource createResource(String name, String location, String version) {
		SwaggerResource swaggerResource = new SwaggerResource();
		swaggerResource.setName(name);
		swaggerResource.setLocation("/" + location + "/v2/api-docs");
		swaggerResource.setSwaggerVersion(version);
		return swaggerResource;
	}

Explanation

  • The above code will configure Swagger to go through each route for the different services, General and Minnesota, and produce API docs for them.  

 

11.)  Create a bootstrap.yml file in /src/main/resources/ if it doesn’t exist yet.

12.)  Open bootstrap.yml file and make sure it has the following properties:

spring:
 application:
   name: proxy-service
 cloud:
   config:
     uri: http://localhost:8088

13.)  Go back to the Config Server project.

14.)  Create a new file called, proxy-service.yml, in the following directory,  /src/main/resources/config/, in which we will be inserting some config properties for our proxy service(s).

15.)  Next, inside proxy-service.yml, insert the following properties:

server:
 port: 8060
eureka:
 client:
   serviceUrl:
     defaultZone: http://localhost:8061/eureka/
logging:
 pattern:
   console: "%d{yyyy-MM-dd HH:mm:ss} ${LOG_LEVEL_PATTERN:-%5p} %m%n"        
zuul:
 routes:
   general:
     path: /general/**
     serviceId: general-service
   mn:
     path: /mn/**
     serviceId: minnesota-service

Explanation

  • We set up our routes for Zuul (zuul.routes) so that we can proxy the requests to the correct services when the paths match.
    • For example, in order to hit the general-service, we would need to ensure that the path has /general/.

16.)  Now, start up Proxy microservice.

17.)  Go to the following URL and you should see the message that should be returned by the home method in the General microservice:

http://localhost:8060/general

 

18.)  Next, if you go to the following URL, http://localhost:8060/general/89, you should now see a greeting along with one specific to the Minnesota microservice.

 

19.)  Then, if you go to the following URL, http://localhost:8060/mn/greeting, you should see the greeting that was added on to the previous step’s greeting message.  The response from the Minnesota microservice is from the same endpoint, but it’s just that the method, greeting, in General microservice calls it directly and then appends it to it’s own string response whereas the URL /mn/greeting uses the API gateway to get us there directly to the Minnesota microservice.

 

20.)  Then, if you check Eureka, you'll notice that there will be a 3rd service listed and that is the proxy service:

 

21.)  Now to check out the API docs generated by Swagger, go to http://localhost:8060/swagger-ui.html and you should see something similar:

Code Repository

Grab the code at https://github.com/lorbs28/bl-proxy-service.


Next tutorial part...

Create a microservices application architecture with Spring Boot and Spring Cloud - Part 7 - Wrap-up