What is an API gateway
API Gateway is the entrance of all requests, carrying all traffic, API Gateway is a portal, can also be said to be the only node into the system. This is much like the Facet pattern in the object-oriented design pattern. The API Gateway encapsulates the architecture of the internal system and provides apis to individual clients. It may also have other capabilities such as authorization, monitoring, load balancing, caching, request sharding and management, static response processing, and so on
The API Gateway is responsible for request forwarding, composition, and protocol transformation. All requests from clients are routed through the API Gateway and then routed to the corresponding microservice. The API Gateway will often process a request and aggregate the results of multiple services by invoking multiple microservices. It can convert between Web protocols and non-Web-friendly protocols used internally, such as HTTP and WebSocket.
The diagram shows that without the gateway, the client requests will directly fall into the back-end services and cannot be centrally managed.In the case of a gateway, all requests pass through the gateway and then are distributed to the corresponding service
2. Importance of API gateways
API gateways are important in microservice projects, providing a unified management and scheduling between services
Reference nginx official of a high quality blog, www.nginx.com/blog/buildi… , the example introduces a complex e-commerce system, which is designed according to the micro-service theory and has the following services:
- Shopping cart service: Number of items in a shopping cart
- Order service: Order history
- Catalog services: Basic product information, such as its name, image, and price
- Audit service: customer audit
- Inventory service: Low inventory warning
- Shipping service: Shipping options, terms and costs are extracted separately from the shipping provider’s API
- Recommendation service: Suggested items
In the absence of a gateway, the client invokes each service directly:Ideally, individual service invocations would work normally, but as the business grows and the calls between services become more complex, the system would look like this:If there is no unified management, it is certainly not reasonable, so the gateway can be introduced as a unified portal, as shown in the figure:
3. The role of API Gateway
Ok, after a brief introduction to the gateway, I want to talk about the functions of the gateway, which is also summarized in the Spring Cloud website:Of course, we can pick a few important introductions ourselves
- Dynamic routing
The gateway can perform route forwarding. If the service information changes, it only needs to change the gateway configuration. Therefore, the gateway has the function of Dynamic Routing, as shown in the figure:
- Request to monitor
Request monitoring can monitor requests across the system, logging request responses in detail, as shown in figure 2. Logs can be thrown into message queues, and if gateways are not used, logging request information needs to be done in individual services
- Certification authentication
Authentication authentication can authenticate each access request, reject illegal requests, protect back-end services, do not need to do authentication for each service, in the project often add OAuth2.0, JWT, Spring Security for permission verification
- Pressure test
For a system with a gateway, if you want to stress test a service, you can change the gateway configuration as shown in the figure. The test request is routed to the test service, and the test service will have a separate test database, so that the test request will not affect the formal service and database
What is Netflix Zuul?
Netflix Zuul is an API gateway middleware developed by Netflix. Zuul is a LOAD balancer based on JVM routing and server side. It provides routing, monitoring, elasticity, and security services. Zuul works with Eureka, Ribbon, Hystrix and other components to provide a unified API gateway
5. How Netflix Zuul works
referenceZuul website wikiThe core diagram of Zuul is actually a filter. Zuul is implemented based on servlets. When a request comes in, it goes to the Pre filter, and after the Pre filter is done, it goes to the routing filter, and it starts routing to the specific service, and the error is intercepted by the error filter
- Filter type:
- PRE FILTER: Perform this operation before routing filters. Capabilities can include requesting authentication, selecting the original server, and logging debugging information.
- ROUTE FILTER: Handles the process of routing requests to sources. This is where raw HTTP requests are built and sent using Apache HttpClient or Netflix Ribbon.
- POST FILTER: Executed after the request is routed to the FILTER. Capabilities can include adding standard HTTP headers to the response, collecting statistics and metrics, and transferring the response from the source stream to the client.
- ERR FILTER: An error FILTER is called when an error occurs in one of the other phases
6. Preparation of Zuul experimental environment
Environment Preparation:
- JDK 1.8
- SpringBoot2.2.3
- SpringCloud(Hoxton.SR6)
- Maven 3.2 +
- The development tools
- IntelliJ IDEA
- smartGit
To create a SpringBoot Initialize project, please refer to my previous blog: SpringBoot Series of Quick Project creation tutorials
Maven configuration:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
Copy the code
This blog is based on the spring-cloud-starter- Netflix – Eureka -client test, before the test to run eureka server, Eureka service provider, code please refer to the previous chapter blog
After the project is successfully created, add @enableZuulProxy to the startup class:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableZuulProxy
public class SpringcloudZuulApplication {
public static void main(String[] args) { SpringApplication.run(SpringcloudZuulApplication.class, args); }}Copy the code
7, Eureka, Zuul configuration
Eureka client configuration:
server:
port: 8082
This is the serviceId of the microservice registry
spring:
application:
name: zuul-api-gateway
eureka:
client:
Service registry URL
service-url:
defaultZone: http://localhost:8761/eureka/
Register-with-eureka and fetch-registry are both true
register-with-eureka: true
fetch-registry: true
instance:
status-page-url-path: http://localhost:8761/actuator/info
health-check-url-path: http://localhost:8761/actuator/health
prefer-ip-address: true
instance-id: zuul-api-gateway8082
Copy the code
Zuul Configuration routing rules:
zuul:
routes:
provider: # Route id, you can define it yourself
service-id: eureka-service-provider Service id(must be configured)
path: /provider/** The path mapped is the same as routes.provider
url: http://localhost:8083 The url to which the route is routed may not be configured
Copy the code
Zuul configuration access prefix: we need to add access prefix, eg: http://localhost:8082/api-gateway/provider/api/users/mojombo
zuul:
# configure prefix
prefix: /api-gateway
Copy the code
Zuul configure Header filtering:
zuul:
# configure filter sensitive request headers. Set this parameter to null
sensitive-headers: Cookie,Set-Cookie,Authorization
Copy the code
Zuul configure redirection to add Host:
zuul:
# redirection adds the host header
add-proxy-headers: true
Copy the code
Zuul timeout Settings:
zuul:
host:
Set connection timeout
connect-timeout-millis: 15000
Socker send timeout
socket-timeout-millis: 60000
Copy the code
Zuul all configuration reference, details refer to the official website:
zuul:
# configure prefix
prefix: /api-gateway
routes:
provider: # Route id, you can define it yourself
service-id: eureka-service-provider # service id
path: /provider/** The path mapped is the same as routes.provider
url: http://localhost:8083 # route to url
host:
Set connection timeout
connect-timeout-millis: 15000
Socker send timeout
socket-timeout-millis: 60000
Request URL encoding
decode-url: true
# query string encoding
force-original-query-string-encoding: false
# configure filter sensitive request headers. Set this parameter to null
sensitive-headers: Cookie,Set-Cookie,Authorization
# redirection adds the host header
add-proxy-headers: true
Copy the code
Visit: http://localhost:8082/api-gateway/provider/api/users/mojombo, to add a prefix, configuration of the path
Possible errors encountered, 504 errors:
After troubleshooting, the timeout setting needs to be added, because the call service timed out, resulting in error 504
zuul:
host:
connect-timeout-millis: 15000
socket-timeout-millis: 60000
Copy the code
With the configuration, the service was successfully invoked
8, Zuul custom filter
In the previous introduction, several filters were introduced. Now you customize the implementation of these four filters
Ps: Spring Cloud also provides examples of Zuul filters. For details, go to github: github.com/spring-clou…
Project Structure: Filter types reference org.springframework.cloud.net flix. Zuul. Filters. SupportFilterConstants. Java:Implement a pre-filter: intercept request, must bring token, otherwise throw prompt, etc
package com.example.springcloud.zuul.web.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.FORWARD_TO_KEY;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SERVICE_ID_KEY;
/** ** <pre> * API gateway prefilter * </pre> ** <pre> *@authorMazq * Modified Record * Modified by: Date: 2020/08/05 18:08 Modified content: * </pre> */
@Slf4j
//@Component
public class ZuulApiGatewayPreFilter extends ZuulFilter {
@Override
public String filterType(a) {
return PRE_TYPE;
}
@Override
public int filterOrder(a) {
return 0;
}
@Override
public boolean shouldFilter(a) {
return true;
}
@Override
public Object run(a) throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String accessToken = request.getParameter("token");
if (StringUtils.isEmpty(accessToken)) {
// Zuul filters the request without routing it
ctx.setSendZuulResponse(false);
// Set the error code returned
ctx.setResponseStatusCode(403);
ctx.setResponseBody("AccessToken is Invalid ");
return null;
}
log.info("accessToken: {}",accessToken);
// Otherwise, services continue
return null; }}Copy the code
Post filter, often used to print logs and other operations, code reference: www.baeldung.com/zuul-filter… To achieve the effect, after the route filter is executed, the post filter is executed to print logs:
package com.example.springcloud.zuul.web.filter;
import com.google.common.io.CharStreams;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.protocol.RequestContent;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.POST_TYPE;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
/ * * * < pre > * API Gateway rear-mounted filter * < / pre > < pre > * * *@authorMazq * Modified Record * Modified by: Date: 2020/08/06 10:05 Modified Content: * </pre> */
@Slf4j
//@Component
public class ZuulApiGatewayPostFilter extends ZuulFilter {
@Override
public String filterType(a) {
return POST_TYPE;
}
@Override
public int filterOrder(a) {
return 0;
}
@Override
public boolean shouldFilter(a) {
return true;
}
@Override
public Object run(a) throws ZuulException {
RequestContext context = RequestContext.getCurrentContext();
try (final InputStream responseDataStream = context.getResponseDataStream()) {
if(responseDataStream == null) {
log.warn("RESPONSE BODY: {}"."");
return null;
}
String responseData = CharStreams.toString(new InputStreamReader(responseDataStream, "UTF-8"));
log.info("RESPONSE BODY: {}", responseData);
context.setResponseBody(responseData);
}
catch (Exception e) {
throw new ZuulException(e, INTERNAL_SERVER_ERROR.value(), e.getMessage());
}
return null; }}Copy the code
Register the filter, load the filter into the Spring container, or add @Component to the filter class
package com.example.springcloud.zuul;
import com.example.springcloud.zuul.web.filter.ZuulApiGatewayErrFilter;
import com.example.springcloud.zuul.web.filter.ZuulApiGatewayPostFilter;
import com.example.springcloud.zuul.web.filter.ZuulApiGatewayPreFilter;
import com.example.springcloud.zuul.web.filter.ZuulApiGatewayRouteFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableZuulProxy
public class SpringcloudZuulApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudZuulApplication.class, args);
}
@Bean
public ZuulApiGatewayPreFilter zuulApiGatewayPreFilter(a){
return new ZuulApiGatewayPreFilter();
}
@Bean
public ZuulApiGatewayPostFilter zuulApiGatewayPostFilter(a){
return new ZuulApiGatewayPostFilter();
}
@Bean
public ZuulApiGatewayRouteFilter zuulApiGatewayRouteFilter(a){
return new ZuulApiGatewayRouteFilter();
}
@Bean
public ZuulApiGatewayErrFilter zuulApiGatewayErrFilter(a){
return newZuulApiGatewayErrFilter(); }}Copy the code
Access gateway:http://localhost:8082/api-gateway/provider/api/users/mojombo, not to bring a token http://localhost:8082/api-gateway/provider/api/users/mojombo?token=?, bring a token call success
9. View Zuul routing information
In addition, spring-boot-starter-actuator monitors routing information:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Copy the code
Spring – the boot – starter – physical configuration:
management:
endpoints:
web:
exposure:
# Enable monitoring of routes (info,health) by default
include: info,health,routes
Enable health check details
endpoint:
health:
show-details: always
Copy the code
Visit http://localhost:8082/actuator/routes for routing, details, SpringBoot2.2.3 version with physical prefix, the call is successful, returns the json data:
{
"/api-gateway/provider/**":"eureka-service-provider"."/api-gateway/eureka-service-provider/**":"eureka-service-provider"
}
Copy the code
For routing information details, access link: http://localhost:8082/actuator/routes/details
{
"/api-gateway/provider/**": {"id":"provider"."fullPath":"/api-gateway/provider/**"."location":"eureka-service-provider"."path":"/ * *"."prefix":"/api-gateway/provider"."retryable":false."customSensitiveHeaders":false."prefixStripped":true
},
"/api-gateway/eureka-service-provider/**": {"id":"eureka-service-provider"."fullPath":"/api-gateway/eureka-service-provider/**"."location":"eureka-service-provider"."path":"/ * *"."prefix":"/api-gateway/eureka-service-provider"."retryable":false."customSensitiveHeaders":false."prefixStripped":true}}Copy the code
This blog code sample download: code download
Spring Cloud: Spring Cloud: Spring Cloud: Spring Cloud…
Zuul Github Wiki: github.com/Netflix/zuu
Github Zuul filter example: github.com/spring-clou…
Reference for quality learning materials:
-
Nginx website for micro service gateway is introduced: www.nginx.com/blog/buildi…
-
SpringCloud Component Gateway Zuul(Hoxton version):juejin.cn/post/684790…
-
Fang Zhipeng bosses series Spring Cloud blog: www.fangzhipeng.com/spring-clou…
-
Eacdy.gitbooks. IO/Spring-clou…
-
Programmers DD bosses series Spring Cloud blog: blog.didispace.com/spring-clou…