Spring Cloud builds a microservices architecture (v) Service Gateway

Source: Internet
Author: User
Tags types of filters

With the introduction of several core components from the previous spring cloud, we have been able to build a short (imperfect) microservices architecture. As shown in the following example:


We implemented service registries and service registration and discovery using the Eureka in spring cloud Netflix, while service consumption and balanced workloads across the ribbon or feign through the spring cloud Config enables the application of multi-environment external configuration and version management. To make the service cluster more robust, use the hystrix-break mechanism to avoid the spread of failures caused by individual service anomalies in the microservices architecture.

In this architecture, our service cluster includes: Internal Services service A and service B, they are registered with the subscription service to Eureka Server, and the open service is an external service that is exposed to the service callers through a balanced load. In this paper, we focus on the external services of this piece, the implementation is reasonable, or whether there is a better way to achieve it?

Let's start with some of the things that this architecture needs to do and the shortcomings that exist:

    • First, it destroys the service stateless feature. In order to ensure the security of the external services, we need to implement the access control of the service, and the Open service control mechanism will run through and pollute the entire open services business logic, this will bring the most direct problem is that the service cluster of the rest API stateless features. From the point of view of specific development and testing, in addition to considering the actual business logic in the work, additional control processing of interface access is required.
    • Second, the existing interfaces cannot be reused directly. When we need to access the interface in a certain cluster, we have to implement the permission control by adding the check logic on the original interface, or adding a proxy call, and cannot reuse the original interface directly.

In the face of similar problems, how can we solve them? Here is the topic: Service Gateway!

In order to solve these problems, we need to take permission control such things out of our service unit, and the most suitable for these logic is in the forefront of external access to the place, we need a more powerful load balancer, which is the future of this article: Service Gateway.

A service gateway is an integral part of the microservices architecture. In addition to the service Routing and load balancing function, the service gateway provides the rest API to the external system, and it also has the functions of privilege control. The Zuul in Spring Cloud Netflix is a role that provides front-door protection for microservices architectures, while migrating permissions control of these heavier non-business logic content to the service routing plane, enabling service cluster principals to be more reusable and testability-oriented.

Let's take a look at examples to use Zuul to serve as a way to function.

Preparatory work

Before using Zuul, we built a service registry, and two simple services, such as: I built a service-a, a service-b. Then start Eureka-server and the two services. By visiting Eureka-server, we can see that service-a and Service-b are already registered with the service center.

Alt

If you are not yet familiar with how to build a service center and registration services, read the spring Cloud Build microservices Architecture (a) service registration and discovery.

If you do not want to prepare yourself, you can get the sample code here: http://git.oschina.net/didispace/SpringBoot-Learning

Getting Started with Zuul
    • The introduction of dependency Spring-cloud-starter-zuul, Spring-cloud-starter-eureka, if not by specifying Serviceid way, eureka Dependence is not needed, but in order to transparency of the service cluster details, Or use Serviceid to avoid the direct reference URL.
123456789 <dependency> <groupid>org.springframework.cloud </GROUPID> < Artifactid>spring-cloud-starter-zuul</ARTIFACTID> </DEPENDENCY>  DEPENDENCY> <groupid> Org.springframework.cloud</GROUPID> span class= "tag" ><artifactid>spring-cloud-starter-eureka</ARTIFACTID> </dependency
    • Apply main class using @EnableZuulProxy annotations to open Zuul
123456789 @EnableZuulProxy @SpringCloudApplication public class application { public static void main(string[] args) { /c14>new Springapplicationbuilder (Application.class). Web (True). Run (args); }

Here with the @SpringCloudApplication annotations, not mentioned before, through the source we see, it integrates @SpringBootApplication ,, @EnableDiscoveryClient @EnableCircuitBreaker , the main purpose or simplify the configuration. The specific role of these notes is not detailed here, the previous article has been introduced.

    • application.propertiesThe basic information for the Zuul app is configured in, such as: app name, service port, and so on.
12 spring.application.name=api-gatewayserver.port=5555
Zuul Configuration

After the completion of the above work, Zuul can already run, but how to make it for our microservices Cluster service, but also need our separate configuration, the following detailed introduction of some common configuration content.

Service Routing

Through the function of service routing, when we provide service externally, we only need to expose the caller to our service by exposing the call address configured in Zuul, without needing to know the host information of the specific service provided.

Two mapping methods are available in Zuul:

    • With direct URL mapping, we can configure the following:
123 # routes to URLzuul.routes.api-a-url.path=/api-a-url/**zuul.routes.api-a-url.url= http://localhost:2222/

The configuration, defined, all the accesses to Zuul are /api-a-url/** mapped to the above, that is, http://localhost:2222/ when we visit http://localhost:5555/api-a-url/add?a=1&b=2 , Zuul will route the request to: http://localhost:2222/add?a=1&b=2 up.

Where the Api-a-url part of the configuration attribute Zuul.routes.api-a-url.path is the name of the route and can be arbitrarily defined, but the path and URL of a set of mappings should be the same, as is the case with Serviceid.

    • URL mapping is not particularly friendly for Zuul, Zuul needs to know all of our service addresses in order to complete all the mapping configurations. In fact, when we implement the MicroServices architecture, the relationship between the service name and the service instance address already exists in Eureka Server, so we just need to register Zuul to Eureka Server to discover other services, we can implement the mapping of the Serviceid. For example, we can configure the following:
12345678 Zuul.routes.api-a.path=/api-a/**zuul.routes.api-a.serviceid=service-a zuul.routes.api-b.path=/api-b/** Zuul.routes.api-b.serviceid=service-b eureka.client.serviceurl.defaultzone=http://localhost:1111/eureka/

For the two microservices service-a and service-b we implemented in the preparation, we defined two routes api-a and api-b to map separately. In addition, in order to let Zuul can find Service-a and Service-b, also joined the Eureka configuration.

Next, we start the Eureka-server, Service-a, Service-b, and the service gateways implemented here with Zuul, and in the Eureka-server control page, we can see that we have registered service-a, Service-b and Api-gateway

Alt

Try to access service-a and service-b through the service network interfacing, and access the following URL according to the configured mapping relationship

    • http://localhost:5555/api-a/add?a=1&b=2: Access to the Add service in service-a via Serviceid mapping
    • http://localhost:5555/api-b/add?a=1&b=2: Access to the Add service in service-b via Serviceid mapping
    • http://localhost:5555/api-a-url/add?a=1&b=2: Access to the Add service in service-a via URL mapping

It is recommended to use Serviceid mapping method, in addition to Zuul maintenance more friendly, Serviceid mapping mode also supports the circuit breaker, in the case of service failure, can effectively prevent the failure spread to the service gateway and affect the entire system of external services

Service filtering

After the service routing is completed, we also need some security measures to protect the client from accessing only the resources it should access. So we need to use Zuul filter to realize the security control of our external service.

Defining a filter in a service gateway requires only ZuulFilter four abstract functions that inherit the abstract class to implement its definition to intercept and filter requests.

As the following example, a Zuul filter is defined, which implements whether the request is checked for parameters before the request is routed, and if so, if there is accessToken no access denied, an error is returned 401 Unauthorized .

123456789101112131415161718192021222324252627282930313233343536373839 public class Accessfilter extends zuulfilter { private static Logger log = Loggerfactory.getlogger (Accessfilter.class); @OverridePublic String filtertype() { return "pre"; }@Overridepublic int Filterorder() { return 0; }@Overridepublic Boolean shouldfilter() { return true; }@OverridePublic Object run() { RequestContext CTX = Requestcontext.getcurrentcontext (); HttpServletRequest request = Ctx.getrequest (); Log.info (String.Format ("%s request to%s", Request.getmethod (), Request.getrequesturl (). ToString ()));Object Accesstoken = Request.getparameter ("Accesstoken");if (Accesstoken = = null) { Log.warn ("access token is empty");Ctx.setsendzuulresponse (false);Ctx.setresponsestatuscode (401);return null; }log.info ("access token OK");return null; } }

The implementation of a custom filter requires inheritance ZuulFilter , and the following four methods need to be overridden:

    • filterType: Returns a String representing the type of filter, with four different life cycle filter types defined in Zuul, as follows:
      • pre: Can be called before the request is routed
      • routing: Called when a request is routed
      • post: Called after the Routing and Error filters
      • error: Called when an error occurs while processing a request
    • filterOrder: Defines the order of execution of the filter by int value
    • shouldFilter: Returns a Boolean type to determine if the filter is to be executed, so the filter can be switched by this function. In the example above, we return true directly, so the filter is always in effect.
    • run: The specific logic of the filter. It is important to note that here we ctx.setSendZuulResponse(false) can further optimize our return by making Zuul filter the request, not routing it, and then by ctx.setResponseStatusCode(401) setting its return error code, for example, by ctx.setResponseBody(body) editing the returned body content.

After implementing a custom filter, you also need to instantiate the filter to take effect, we only need to add the following in the main class of the application:

1234567891011121314 @EnableZuulProxy @springcloudapplicationpublic class Application {public static void main (string[] args) {new Springapplicationbuilder (Application.class). Web (True). Run (args); @Beanpublic Accessfilter Accessfilter () {return new Accessfilter ();}}

After you start the service gateway, access:

    • http://localhost:5555/api-a/add?a=1&b=2: 401 Error returned
    • http://localhost:5555/api-a/add?a=1&b=2&accessToken=token: correctly routed to server-a and returns the calculated content

For some other types of filtering, this is not a one-off, according to the previous filterType life cycle introduction, you can refer to understand, and according to their own needs in different life cycle to implement different types of filters.

Alt

Finally, to summarize why the service gateway is an important part of the microservices architecture, is why we have to do it:

    • It not only realizes the routing function to block many service details, but also realizes the routing of Service level and balanced load.
    • The decoupling of interface privilege check and microservices business logic is realized. Through the Service Gateway filter, in each life cycle to verify the content of the request, the original service layer to do the check forward, to ensure the non-state of microservices, while reducing the micro-service testing difficulty, so that the service itself more focused on business logic processing.
    • Realize the circuit breaker, not because of the failure of the specific micro-service caused the blocking of the service gateway, can still serve the outside.

For a complete example of this article, refer to: chapter9-1-5

"Reprint Please specify source": http://blog.didispace.com/springcloud5/

Spring Cloud builds a microservices architecture (v) Service Gateway

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.