Why do you need a gateway?
We know that we want to enter a service itself, and it is obvious that we have no particularly good method. We directly enter the IP address + port number. We know that this approach is very bad. There is a big problem with this approach. First, it exposes the IP address of our physical machine. When others look at your IP address, they know where the service is deployed, allowing others to conduct attack operations very conveniently.
Second, we have so many services, do we have to call them one by one? Let's assume that we have done permission authentication, and each of our customers accesses service programs on different JVMs running on different machines. Each of our services needs a service authentication. Is this annoying? It is obviously very annoying.
Then we are facing these two and their general problems at this time, and we need a way to solve them. First of all, let’s look at the exposure of the IP address and the single-point problem caused by the IP address writing after death. Do I also need to dynamically maintain the list of services for such a service itself? I need to call this service itself, do I also need a load balancing thing?
There are also things about the IP address exposure. Do I need to be a proxy, like Nginx's reverse proxy, and there are also things that deploy public modules on this thing, such as permission verification for all portals. So we now need the Zuul API gateway. It solves the above problem. If you want to call a certain service, it will map you and map the IP address of your service into
If you enter the path, it matches it and it will access the service for you. It will have a request forwarding process. Like Nginx, the specific strength of the service machine instance, it will not directly access the IP, it will go to the Eureka registration center to get the service instance ID, that is, the service name. I used the client's load balancing ribbon to access one of the service instances again.
The API gateway is mainly used to solve the problem of external calls by the service itself, and to solve the problem of permission verification. You can integrate and call a series of filters here, such as integrating shiro, springsecurity and other things.
Zuul can load a dynamic filtering mechanism to achieve the following functions:
1. Verification and security: Identify verification requirements for various resources and reject requests that do not match the requirements.
2. Review and monitoring: Track meaningful data and statistical results at edge locations, thus bringing us accurate conclusions on production status.
3. Dynamic routing: Route requests to different backend clusters dynamically as needed.
4. Stress test: Gradually increase the load flow to the cluster to calculate the performance level.
5. Load allocation: Assign the corresponding capacity to each load type and deprecate requests that exceed the limit value.
6. Static response processing: Create partial responses directly at edge locations to prevent them from flowing into the internal cluster.
7. Multi-region elasticity: Request routing across AWS regions is designed to achieve diversified ELB usage and ensure that edge locations are as close as possible to users.
Next, go to a small demo
The first step is to build a new Zuul module under the original project and introduce dependencies. The code is as follows:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> <version>1.3.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> <version>1.3.5.RELEASE</version> </dependency>
Then type the @EnableZuulProxy annotation on the startup class, and the code is as follows:
server: port: 5000spring: application: name: api-getewayzuul: routes:#Identify the name of your service, which can be defined by yourself here. Generally speaking, convenience and specifications are the same as the name of your service hello-service:#The path of service mapping, through this path, you can access your service from the outside. The purpose is to avoid exposing your machine's IP and the service-oriented route, and choose an available one for you. #Here, zuul automatically depends on hystrix and ribbon, not for stand-alone path: /hello-service/**# This must be the name of the service in your Eureka registration center. Therefore, the serviceId is configured here because it is combined with eureka. If you use zuul alone, you must write the IP of your own machine. #such as url:http://localhost:8080/ This is not good enough to write the IP dead. If this IP fails and this is high availability, the service registration set will not be used. ServiceId: hello-serviceeureka:#Client:#Registration Center address service-url: defaultZone: http://localhost:8888/eureka/,http://localhost:8889/eureka/
Then start the registry center and two hello-service service providers in the previous article. Then we run it and take a look at its request forwarding function to see if it polls into the two services.
Enter localhost:5000/hello-service/hello, as follows:
Then refresh again:
You can see that zuul has made a request to distribute it. It is mapped to a specific machine based on your service name hello-servie. Isn't this the function of a reverse proxy?
zuul can also perform request filtering, so let's perform token verification to demonstrate. First, we need to create a new TokenFilter class to inherit the ZuulFilter class and implement its four interfaces. The code is as follows:
package hjc.zuul;import com.netflix.zuul.ZuulFilter;import com.netflix.zuul.context.RequestContext;import javax.servlet.http.HttpServletRequest;/** * Created by cong on 2018/5/18. */public class TokenFilter extends ZuulFilter { //Four types: pre,routing, error, post //pre: It is mainly used in the routing mapping stage to find the routing mapping table //routing: The specific routing forwarding filter is on the routing router. When forwarding the specific request, it will be called //error: Once the previous filter error occurs, the error filter will be called. //post: This filter will not be called after routing and error is completed. It is @Override public String filterType() { return "pre"; } //Customize the order of execution of filters. The larger the value, the later the execution. The smaller the value, the more it is executed, the more it is executed first. @Override public int filterOrder() { return 0; } //Control the filter to take effect or not. You can write a string of logic in it to control @Override public boolean shouldFilter() { return true; } //Execute filter logic @Override public Object run() { RequestContext context = RequestContext.getCurrentContext(); HttpServletRequest request = context.getRequest(); String token = request.getParameter("token"); if (token == null){ context.setSendZuulResponse(false); context.setResponseStatusCode(401); context.setResponseBody("unAuthrized"); return null; } return null; }}filterType: Returns a string representing the type of the filter. Four filter types with different life cycles are defined in zuul, as follows:
1. pre : It can be called before the request is routed. It is used to find the routing mapping table during the routing mapping stage.
2.route : is called during routing request. The specific routing forwarding filter will be called when routing the router's specific request forwarding.
3. error : Called when an error occurs while processing the request
4. post : The filter will not be called after routing and error is completed, which is in the last stage.
Here we declare the exception that occurs when the zuul filter executes a network request. The exception caught by try-catch cannot be directly thrown to the page in the filter. The exception thrown by the application can be returned to the page by using the context.set() method in the catch. as follows:
try{ business logic...}catch(Exception e){ RequestContext context = RequestContext.getCurrentContext(); context.set("error.status_code",401); context.set("error.exception",e); context.set("error.message","sfdfsdf");}Next, you need to add this filter to spring and let spring manage it. The code is as follows:
package hjc;import hjc.zuul.TokenFilter;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@EnableZuulProxypublic class ZuulApplication { public static void main(String[] args) { SpringApplication.run(ZuulApplication.class, args); } //Leave the filter to Spring Management @Bean public TokenFilter tokenFilter(){ return new TokenFilter(); }}Next, let's start the startup class and first access without tokens, as follows:
You can see that a message without permission is returned. Here I want to say that tokens are usually placed in the request header. Here we are not doing that for demonstration purposes.
Then take the token and visit it, as follows:
You can see that our request has been sent.
Here I will talk about what is the default route and delete the zuul configuration, as follows:
server: port: 5000spring: application: name: api-getewayeureka:#Client client:#Register center address service-url: defaultZone: http://localhost:8888/eureka/,http://localhost:8889/eureka/
Then, restart and continue access, as follows:
,
You can see that we can still continue to access. We have nothing to do, but we can still access it. That's because, by default, you are automatically declared with your service name hello-service.
So, if I don't want it to automatically declare it for me and I want to define it myself, then I can use zuu.ignored-services in the yml configuration file to filter it like filtering, as follows: "
zuul:#If ignored-services:* means that all default routes have expired. You have to match them one by one. No one will be so fucked, unless you encounter strange business ignore-services:
Let's talk about the mapping rules, for example
zuul: routes:#Identify the name of your service, you can define it yourself here. Generally speaking, convenience and specifications are the same as the name of your service hello-service:#Service mapped path, through this path, you can access your service from the outside. The purpose is to avoid exposing your machine's IP, and the service-oriented route is for you. #Here zuul automatically depends on hystrix and ribbon, not for stand-alone path: /hello-service/**#This must be the name of your Eureka registration center service, so the serviceId is configured here because it is combined with eureka. If you use zuul alone, you must write your machine's IP, #such as url:http://localhost:8080/ This is bad, it means writing the IP dead. If this IP fails and high availability, the service registration set will not be used serviceId: hello-servicezuul: routes: hello-service: path: /hello-service/ext/** serviceId: hello-service
The two zuul configuration mapping paths here have /hello-service/. You can see that /hello-service/** includes /hello-service/ext/**. Are there any conflicts when matching these two paths? How to deal with it? Who will match first?
Here is the order defined in yml to match. If it is a configuration file in the application.properties format, this order cannot be guaranteed. The configuration files in the yml format are in sequence, which can be guaranteed. Please note this here.
What if we want to define a matching rule? Then we need to define a bean in the startup class, which determines your route, as follows:
I won’t demonstrate it here. When you need it, go and search for information slowly.
There is also ignore-patterns: as follows:
zuul: routes:#Identify the name of your service, you can define it yourself here. Generally speaking, convenience and specifications are the same as the name of your service hello-service:#Service mapped path, through this path, you can access your service from the outside. The purpose is to avoid exposing your machine's IP, and the service-oriented route is for you. #Here zuul automatically depends on hystrix and ribbon, not for stand-alone path: /hello-service/**#This must be the name of your Eureka registration center service, so the serviceId is configured here because it is combined with eureka. If you use zuul alone, you must write your machine's IP, #such as url:http://localhost:8080/ This is bad, it means writing a dead IP. If this IP fails and high availability, the service registration set will not be used serviceId: hello-service ignored-patterns: /hello/**
ignore-patterns: indicates that the path of /hello/** is blocked. Even if you /hello-service/hello/** is not possible, you still block it. We can further refine this configuration. For example, if I don't want to route the /hello interface, then we can configure it as above
What if we also want to configure the prefix of a service? The code is as follows:
zuul: routes:#Identify the name of your service, you can define it yourself here. Generally speaking, convenience and specifications are the same as the name of your service hello-service:#Service mapped path, through this path, you can access your service from the outside. The purpose is to avoid exposing your machine's IP, and the service-oriented route is for you. #Here zuul automatically depends on hystrix and ribbon, not for stand-alone path: /hello-service/**#This must be the name of your Eureka registration center service, so the serviceId is configured here because it is combined with eureka. If you use zuul alone, you must write your machine's IP, #such as url:http://localhost:8080/ This is not good enough to write a dead IP. If this IP fails and high availability, the service registration set will not be used serviceId: hello-service prefix: /api/**
You can see that the services you visit must be prefixed with /api/, such as /api/hello-service/**
What should we do if we want to jump to my local area if we want to do a path access?
I hope that the user can automatically jump to this method when accessing /local. So at this time, we need to use Zuul's local jump, and the configuration method is as follows:
zuul: prefix: /api ignored-patterns: /**/hello/** routes: local: path: /hello-service/** url: forward:/local
Some of the commonly used ones, connecting to springsecurity or some third-party components, will obtain some of your cookie information. So Zuul Gateway has killed all your cookie information for security reasons, and there is no way to make cookies. It is killed by default.
Here Zuul provides zuul.sensitive-headers to make these cookies and headers for you, and do not filter these information. Control your sensitive information.
By default, sensitive header information cannot be passed through the API gateway. We can make it passable through the following configuration:
zuul: routes: hello-service: path: /hello-service/** serviceId: hello-service sensitive-headers: cookie, header and other things
It can also be used with some detailed configurations of Hystrix, as mentioned before. I won't talk about it here
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.