Spring Cloud Starter Series Six: Implementing API Gateway Services with Zuul

Source: Internet
Author: User

Through the previous sharing, we learned about several core facilities of the microservices architecture, through which we can build a simple microservices architecture system. For example, through spring Cloud Eureka to build a highly available service registry and realize the registration and discovery of services;

Load balance through the Spring cloud ribbon or feign, and fault-tolerant protection with spring cloud Hystrix to avoid a failure spread. After the microservices are set up, we will certainly provide the external system with some unified RESTful API service interfaces to invoke,

But when the external system calls our RESTful API, how do we determine what service it needs to provide specifically? This involves the maintenance of a routing rule and a list of service instances.

This introduces us to today's protagonist--spring Cloud Zuul, which is an API Gateway component based on the Netflix Zuul implementation. It can solve two major problems:

    1. Is the maintenance of the routing rules and Service instances we mentioned above
    2. For some checks (such as login checksum) redundancy problem. According to our practice, it is necessary to include these checks in each service, but this can lead to code redundancy and maintenance is cumbersome, with spring Cloud Zuul This Gateway service, we can put these common checks into the Gateway unified maintenance.

OK, let's see how we can implement this Gateway service next.

First, build the gateway, configure the routing

Here we still need to use the Hello-service and Feign-consumer services to the front. We used Feign-consumer as a service consumer, but don't forget that in the Eureka system, each service is both a service provider and a service consumer, so Feign-consumer is also a service provider, and http://localhost : 9001/feign-consumer and other interfaces are the services it provides.

Next we build a gateway service with the following code structure:

  

Code implementation steps:

  1. New MAVEN Project Api-gateway
  2. Modify the Pom file
    <Projectxmlns= "http://maven.apache.org/POM/4.0.0"Xmlns:xsi= "Http://www.w3.org/2001/XMLSchema-instance"xsi:schemalocation= "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  <modelversion>4.0.0</modelversion>  <groupId>Com.sam</groupId>  <Artifactid>Api-gateway</Artifactid>  <version>0.0.1-snapshot</version>    <Parent>        <groupId>Org.springframework.boot</groupId>        <Artifactid>Spring-boot-starter-parent</Artifactid>        <version>1.5.1.RELEASE</version>    </Parent>    <Properties>        <javaversion>1.8</javaversion>    </Properties>    <!--version Management with Dependencymanagement -    <dependencymanagement>        <Dependencies>            <Dependency>                <groupId>Org.springframework.cloud</groupId>                <Artifactid>Spring-cloud-dependencies</Artifactid>                <version>Camden.sr6</version>                <type>Pom</type>                <Scope>Import</Scope>            </Dependency>        </Dependencies>    </dependencymanagement>    <Dependencies>        <!--By introducing Zuul dependency, it relies on Spring-boot-starter-actuator/spring-boot-starter-hystrix/spring-boot-starter-ribbon -        <Dependency>            <groupId>Org.springframework.cloud</groupId>            <Artifactid>Spring-cloud-starter-zuul</Artifactid>        </Dependency>    </Dependencies>    </Project>
  3. new Startup class
     /**   * @EnableZuulProxy Open Zuul API Gateway Service Feature *  */ @ Enablezuulproxy@springcloudapplication  public  class   Gatewayapp { static  void   main (string[] args) {Spring Application.Run (Gatewayapp.  class     
  4. new application.properties
     server.port=5555spring.application.name  = Api-gateway# increase the routing rule configuration # through zuul.routes.  <route>.path and Zuul.routes.<route>.url configuration,<route> is the name of the route, can be arbitrarily specified, However, the route name for a set of paths and URLs is the same as the   #如下面的例子: all accesses that meet/api-a/** rules are routed to the//localhost:9001 address # In other words, when we visit Http://localhost:5555/api-a/hello, the API Gateway service will route the # request to http ://localhost   :9001/hello provided on the MicroServices interface  zuul.routes.api-a.path=/api-a/**zuul.routes.api-a.url=   http://localhost : 9001zuul.routes.api-b.path=/api-b/** Zuul.routes.api-b.url=http://localhost : 9090  

     

  5. Test, start Eureka, Hello-service, Feign-consumer, and this new Api-gateway service, and then visit http://localhost:5555/api-a/feign-consumer

    Successful access to Feign-consumer's service interface--feign-consonsumer.

The above steps to achieve the traditional configuration of the route , this configuration has a big drawback, is the need to manually in the Application.properties file routing rules configuration, when the service is a lot of time, the maintenance workload will be very large. To reduce maintenance costs, there is another route-service-oriented routing.

Second, service-oriented routing

Spring Cloud Zuul and Eureka, we can make way for the path is not to map the specific URL, but a specific service, and the URL of the service to the Eureka Service discovery mechanism for automatic maintenance, such routing is service-oriented routing. The specific code is configured as follows:

  1. Modify the Pom file to introduce Eureka dependencies
    <!--Introducing Eureka Dependencies -        <Dependency>            <groupId>Org.springframework.cloud</groupId>            <Artifactid>Spring-cloud-starter-eureka</Artifactid>        </Dependency>
  2. Modifying the Application.properties configuration file
    server.port=5555spring.application.name=api-gatewayzuul.routes.api-a.path=/api-a/** #这里用serviceId代替url, replace IP with service name + Port number zuul.routes.api-a. serviceId=hello-service

    Eureka.client.service-url.defaultzone=http://localhost:1111/eureka

    Note: zuul.routes.api-a. URL=hello-service can also implement functionality, but it does not perform normal load balancing and fault-tolerant protection.

  3. Test, Access Http://localhost:5555/api-a/hello

    The access was successful.

Iii. default rules for service routing

In service-oriented routing, because the <route> name is random, it is not possible:

Zuul.routes.hello-service.path=/hello-service/**zuul.routes.hello-service.serviceid=hello-service

<route> name is the name of the service, in fact, in the actual application, we are often named. If there is such a rule, then the Zuul can help us to implement such a function by default, further eliminating the hassle of configuration.

Let's do an experiment and change the configuration file to:

Server.port=5555spring.application.name=api-gatewayeureka.client.service-url.defaultzone=http://localhost:1111/eureka

Then page access validation

The access was successful.

But because by default, the services on Eureka are routed by Zuul creating default mappings, so that the services we don't want to open are also accessed externally, This time you can configure Zuul.ignored-services to configure rules that do not require automatic routing creation. When zuul.ignored-services=*, all services do not automatically create routing rules, which need to be routed through the previous configuration.

================ Gorgeous split-line ===================

So much has been said around a problem: routing rules and Service instance maintenance problems, then how to solve the second problem (verifying redundancy)?

Iv. Request filtering

In order to implement the verification of the client request in API Gateway, we can intercept and filter the request through the filter, the implementation method is relatively simple, only need to inherit Zuulfilter abstract class and implement its four methods on the line.

Modify Api-gateway:

  1. New Filter Class
    /*** Inherit Zuulfilter and implement its 4 interfaces * * For request filtering **/ Public classAccessfilterextendszuulfilter {Logger Logger= Loggerfactory.getlogger (accessfilter.class); /** Shouldfilter Determines if the filter needs to be executed * * This returns true directly, indicating that the filter will take effect for all requests. * We can use this function to specify the effective range of the filter in practice .*/@Override Public BooleanShouldfilter () {return true; }    /** Filter Specific Logic * * Here we pass Ctx.setsendzuulresponse (false) Let Zuul come over the request, do not route it * and then through Ctx.setresponsestatuscode (401) Set the return error code **/@Override PublicObject Run () {RequestContext context=Requestcontext.getcurrentcontext (); HttpServletRequest Request=context.getrequest (); Object Accesstoken= Request.getparameter ("Accesstoken"); Logger.info ("Send {} request to {}", Request.getmethod (), Request.getrequesturl (). toString ()); if(Accesstoken = =NULL) {Context.setsendzuulresponse (false); Context.setresponsestatuscode (60s); }                return NULL; }    /*FilterType return Filter type * He determines which life cycle the filter executes in the request.     This is defined as the pre, and the delegate executes before the request is routed. * * PRE: Filter * route: Process request, route * Post: Filter * ERROR executed after request processing is completed: Filter executed when error occurs*/@Override PublicString FilterType () {return"Pre"; }            /** Filterorder Returns the execution order of the filter * * When a request has multiple filters at one stage, it needs to be executed one time based on the return value of the method **/@Override Public intFilterorder () {return0; }}
  2. Modifying the Startup class
    /***/@EnableZuulProxy @springcloudapplicationpublicclass  Gatewayapp {    //Append Bean is implementation    @Bean public    accessfilter Accessfilter () {        return new Accessfilter ();    }          Public Static void Main (string[] args) {        springapplication.run (Gatewayapp. class , args);}    }
  3. Test
      1. ) Access Http://localhost:5555/hello-service/hello, Access failed
      2. ) Access Http://localhost:5555/hello-service/helloaccesstoken=token, normal access

The modified code structure:

V. Expansion and extension

In fact, when the routing function is really running, his route map and request forwarding are done by several different filters.

Route mapping is done primarily through pre-type filters that match the request path to the configured routing rules to find the destination address that needs to be forwarded.

The part of the request forwarding is done by the route type filter, which forwards the routing address obtained by the pre-type filter.

Therefore, the filter can be said to be Zuul implementation of the API gateway function of the most core components, each incoming Zuul HTTP request will go through a series of filter processing chain to get the request response and return to the client.

Spring Cloud Starter Series Six: Implementing API Gateway Services with Zuul

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.