A lot of the resources on the web explain very clearly what an API gateway is and what it does, but I don’t think it’s friendly enough for a beginner. Zuul is a gateway for SpringCloud microservices.

For beginners, Zuul is a unified management of the API when the number of services is increased, and a certain type of API will call a certain type of service, in addition to the ability to request a filtering of the API. The next step is the other functions of Zuul, which are shown below:

This article focuses on route forwarding and filters.

1 How to introduce Zuul

Similarly, to build a Zuul module, there is no consumer in this example, so it is not the same as to build an empty parent module and then build a concrete child module. Then add a dependency to the POM file in Zuul:

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>
</dependencies>

The directory structure of the entire project so far looks like this:

Main boot classes and configuration files

Because there is no service consumption involved, just API processing, so the main startup class is relatively simple

@SpringBootApplication @EnableZuulProxy @EnableUrekAclient public class ZuulMain9401 {public static void @SpringBootApplication @EnableUrekAclient public class ZuulMain9401 {public static void main(String[] args) { SpringApplication.run(ZuulMain9401.class, args); }}

The configuration file is the same as the regular Eureka client

spring:
  application:
    name: zuul9401
server:
  port: 9401

eureka:
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://localhost:8001/eureka/
  instance:
    instance-id: zuul9401

3. Routing and forwarding

Routing and forwarding is mainly modified through the configuration file, to add content to the above configuration file, the following will describe the three ways of forwarding routing.

Set the service ID for registering Eureka

Adding the first wave of configuration files adds the following content to the existing configuration files.

zuul:
  routes:
    user-a:
      path: /api-a/**
      serviceId: eureka-provide

User-A is defined arbitrarily, Path is the path for external access, and ServiceID is the value of Spring.Application.Name in the microservice configuration file.

So the overall meaning of the configuration file added above is that when accessed externally/api-a/When the path is associated, it will be forwarded to the nameeureka-providThe provision of services.

Open Eureka Service Registry Eurekaserver8001, Service Provider EurekaProvide7001/2/3, API Gateway ZuulMain9401:

Then visit http://localhost:9401/api-a/e… , should be forwarded to the eureka/provide path in eureka-provide service.

To prevent confusion, post the code for the first project, as detailed in the first article in this series.

@SpringBootApplication
@RestController
@EnableEurekaClient
public class EurekaProvide7001 {

    @Value("${server.port}")
    int port;

    @GetMapping("/eureka/provide")
    public String getInfo() {
        return "hello, i am eureka provide, the provide service. My port: " + port;
    }

    @GetMapping("/eureka/delayProvide")
    public String delayGetInfo() throws InterruptedException {
        Thread.sleep(3000);
        return "hello, delay to do something";
    }
    public static void main(String[] args) {
        SpringApplication.run(EurekaProvide7001.class, args);
    }
}

You can see that the route was successfully forwarded

Set the URL

Add a second wave profile

zuul:
  routes:
#    user-a:
#      path: /api-a/**
#      serviceId: eureka-provide
    user-b:
      path: /api-b/**
      url: http://localhost:7101/

As above, which service the URL needs to be forwarded to

Edit Configurations Change the port and service name to simulate the new service. This is also illustrated in the first article.

Other services don’t have to shut down, continue to open new Provide7101, restart ZuulMain9401 services, visit http://localhost:9401/api-b/e… , can also see the successful forwarding

Set the service ID of the non-registered Eureka

As mentioned in the previous study of the Ribbon, we can use the Ribbon Settings to access services that are not registered in Eureka, and the API gateway can also use the Ribbon Settings to achieve the same effect.

Added a third wave profile

zuul: routes: # user-a: # path: /api-a/** # serviceId: eureka-provide # user-b: # path: /api-b/** # url: http://localhost:7101/ user-c: path: /api-c/** serviceID: provide-without-eureka # The ribbon: eureka: enabled: false provide-without-eureka: ribbon: ServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList listOfServers: localhost:7201, localhost:7202 ConnectTimeout: 1000 ReadTimeout: 3000 MaxTotalHttpConnections: 500 MaxConnectionsPerHost: 100

If you cancel
user-a[Bug MC-108201] – When accessing user-a, it cannot be forwarded. [Bug MC-108201] – When accessing user-a, it will report an error of 500
ribbon.eureka.enabled = falseBecause of the.

ServiceID is also the name of the micro service, and then the micro service is set, so the micro service name [provid-without-eureka]. Ribbon, the other properties are related properties, the most important one is listOfServers again, Indicates that this access and this service name will be assigned in the list of services.

For simple or with the same service, with the above method to modify the configuration files, modify the port number 7201, modified eureka. Client. Register. With. Eureka = false to simulate not registered into the service of eureka.

Then I copy the configuration and change the port number to 7202. There are two new services with ports 7201 and 7202.

Other services not shut, open ProvideWithoutEureka7201/2 services, restart ZuulMain9401 services, open at this time all of the services is as follows

Visit http://localhost:9401/api-c/e… , the service can still be forwarded successfully

4 View the routing status

By the way, simply to view the routing status, the first or need to increase the configuration file, is must increase

management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: ALWAYS

Then visit http://localhost:9401/actuato… , the normal situation will appear as follows

If you want a detailed information, so you just need to visit http://localhost:9401/actuato…

5 Fallback when forwarding the route

And Hystrix, Fallback can be used when the forwarding route finds that the service is not being served properly.

Create a new class MyFallbackProvider that implements the FallbackProvider interface

@Component public class MyFallbackProvider implements FallbackProvider { @Override public String getRoute() { // return "*" for all routes; } @Override public ClientHttpResponse fallbackResponse(String route, Throwable throwable) { return new ClientHttpResponse() { @Override public HttpStatus getStatusCode() throws IOException { return HttpStatus.OK; } @Override public int getRawStatusCode() throws IOException { return 200; } @Override public String getStatusText() throws IOException { return "OK"; } @Override public void close() {} @Override public void close() getBody() throws IOException {return new ByteArrayInputStream("something wrong, fallback now".getBytes()); } @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); return headers; }}; }}

Now to manually close ProvideWithoutEureka7201/2 service simulation service outage, to see if I can back

6 filters

The reason Zuul can do authentication, authorization, static resource handling, etc., is because of the filters described below, but mainly for the most basic filters, and maybe more on that later in the story.

Create Filters

First create the Filter package, and then create a filter class MyPreFilter that implements the ZuulFilter interface

Public class MyPreFilter extends ZuulFilter {@Override public String FilterType () {return FilterConstants.PRE_TYPE; } @Override public int filterOrder() {// Override public int filterOrder() {return 0; } @override public Boolean shouldFilter() {// ShouldFilter should return true; } @Override public Object run() throws ZuulException {// LogicalRequestContext currentContext = RequestContext.getCurrentContext(); HttpServletRequest request = currentContext.getRequest(); System.out.println("[ PreFilter" + " ]" + String.format("send %s request to %s",request.getMethod(),request.getRequestURL())); return null; }}

A set of constants is defined in the FilterConstants class, which are the following for filters

public static final String ERROR_TYPE = "error"; Public static final String POST_TYPE = "POST "; public static final String POST_TYPE =" POST "; Public static final String PRE_TYPE = "pre"; public static final String PRE_TYPE = "pre"; Public static final String ROUTE_TYPE = "route"; public static final String ROUTE_TYPE = "route"; // Process the target request

Also create a postrequest

public class MyPostFilter extends ZuulFilter { @Override public String filterType() { return FilterConstants.POST_TYPE; } @Override public int filterOrder() { return 0; } @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException { RequestContext currentContext = RequestContext.getCurrentContext(); HttpServletRequest request = currentContext.getRequest(); Println ("[PostFilter" + "]" + String. Format (" Send %s request to PostFilter" + "]") %s",request.getMethod(),request.getRequestURL())); return null; }}

Into the container

Create a new config package and create a class ZuulConfiguration under the package

@Configuration public class ZuulConfiguration { @Bean public MyPreFilter getZuulPreFilterBean() { return new MyPreFilter(); } @Bean public MyPostFilter getZuulPostFilterBean() { return new MyPostFilter(); }}

The directory structure of the Zuul module at this point is as follows

Note that the fallback in the previous section is invalid when the filter is turned on.

Restart the ZuulMain9401 service and clear the IDEA output console

If it is following the content of the previous section, then it should be forwarded at this point
Not registered with the Eureka serviceThe routing

Visit http://localhost:9401/api-c/e… To view the console output

It is not easy to create, if you have help, welcome thumb up, collection and share!

The following is a personal public number, interested can pay attention to, perhaps is your treasure public number oh, basic 2,3 days 1 more technical articles!!