【Microservice】Gateway Service Gateway

Spring Cloud Gateway is a brand new project of Spring Cloud. The project is a gateway developed based on reactive programming and event flow technologies such as Spring 5.0, Spring Boot 2.0 and Project Reactor. It aims to provide a simple and effective unity for microservice architecture. API routing management method.

Why do you need a gateway

Gateway is the gatekeeper of our services, the unified entry for all microservices.

The core functional characteristics of the gateway :

  • request routing
  • Access control
  • Limiting

Architecture diagram:

insert image description here

Permission control : The gateway, as the entrance to the microservice, needs to verify whether the user is eligible to request, and if not, intercept it.

Routing and load balancing : All requests must go through the gateway first, but the gateway does not process business, but forwards the request to a microservice according to certain rules. This process is called routing. Of course, when there are multiple target services for routing, load balancing is also required.

Current limit : When the request traffic is too high, the gateway will release the request according to the speed that the downstream microservice can accept to avoid excessive service pressure.

There are two types of gateway implementations in SpringCloud:

  • gateway
  • zuul

Zuul is a Servlet-based implementation and belongs to blocking programming. SpringCloudGateway is based on WebFlux provided in Spring5, which belongs to the implementation of reactive programming and has better performance.

gateway quick start

Next, we will demonstrate the basic routing function of the gateway. The basic steps are as follows:

  1. Create SpringBoot project gateway, introduce gateway dependencies
  2. Write a startup class
  3. Write basic configuration and routing rules
  4. Start the gateway service for testing

Create a gateway service and introduce dependencies

Create the service:

insert image description here

Import dependencies:

<!--网关-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

Write a startup class

package cn.itcast.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GatewayApplication {
    
    

	public static void main(String[] args) {
    
    
		SpringApplication.run(GatewayApplication.class, args);
	}
}

Write basic configuration and routing rules

Create an application.yml file with the following content:

server:
  port: 10010 # 网关端口
spring:
  application:
    name: gateway # 服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos地址
    gateway:
      routes: # 网关路由配置
        - id: user-service # 路由id,自定义,只要唯一即可
          # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
          uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
          predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
            - Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求

We will Pathproxy all requests that meet the rules to the address specified by the uriparameter .

In this example, we proxy the requests /user/**starting with , lb://userserviceand lb is load balancing, and pull the service list according to the service name to achieve load balancing.

restart test

Restart the gateway, when accessing http://localhost:10010/user/1, the /user/**rules are met, the request is forwarded to uri: http://userservice/user/1, and the result is obtained:

insert image description here

Flowchart of Gateway Routing

The entire visit process is as follows:

insert image description here

Summarize:

Gateway construction steps:

  1. Create a project, introduce nacos service discovery and gateway dependencies

  2. Configure application.yml, including basic service information, nacos address, routing

Routing configuration includes:

  1. Route id: the unique identifier of the route

  2. Routing target (uri): the target address of the route, http stands for fixed address, lb stands for load balancing based on service name

  3. Routing assertions (predicates): rules for judging routing,

  4. Routing filters (filters): processing requests or responses

Next we discuss the details of route assertions and route filters

assertion factory

The assertion rules we write in the configuration file are just strings, which are read and processed by the Predicate Factory and turned into conditions for routing judgment

For example, Path=/user/** is matched according to the path. This rule is defined by

org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactoryclass to handle, there are more than a dozen assertion factories like this in SpringCloudGateway:

name illustrate Example
After is a request after a certain point in time - After=2037-01-20T17:42:47.789-07:00[America/Denver]
Before is a request before a certain point in time - Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai]
Between is a request before a certain point in time - Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver]
Cookie The request must contain certain cookies - Cookie=chocolate, ch.p
Header The request must contain certain headers - Header=X-Request-Id, \d+
Host The request must be to access a certain host (domain name) - Host=.somehost.org,.anotherhost.org
Method The request method must be the specified method - Method=GET,POST
Path The request path must conform to the specified rules - Path=/red/{segment},/blue/**
Query Request parameters must contain the specified parameters - Query=name, Jack or - Query=name
RemoteAddr The requester's ip must be in the specified range - RemoteAddr=192.168.1.1/24
Weight Weight handling

filter factory

GatewayFilter is a filter provided in the gateway, which can process requests entering the gateway and responses returned by microservices:

insert image description here

Types of Route Filters

Spring provides 31 different route filter factories. E.g:

name illustrate
AddRequestHeader Add a request header to the current request
RemoveRequestHeader remove a request header from the request
AddResponseHeader Add a response header to the response result
RemoveResponseHeader Removes a response header from the response result
RequestRateLimiter Limit requested traffic

request header filter

Let's take AddRequestHeader as an example to explain.

Requirement : Add a request header to all requests to userservice: Truth=itcast is freaking awesome!

Just modify the application.yml file of the gateway service and add route filtering:

spring:
  cloud:
    gateway:
      routes:
      - id: user-service 
        uri: lb://userservice 
        predicates: 
        - Path=/user/** 
        filters: # 过滤器
        - AddRequestHeader=Truth, Itcast is freaking awesome! # 添加请求头

The current filter is written under the userservice route, so it is only valid for requests to access userservice.

default filter

If you want to take effect for all routes, you can write the filter factory under default. The format is as follows:

spring:
  cloud:
    gateway:
      routes:
      - id: user-service 
        uri: lb://userservice 
        predicates: 
        - Path=/user/**
      default-filters: # 默认过滤项
      - AddRequestHeader=Truth, Itcast is freaking awesome! 

Summarize

What does a filter do?

  • Process the routed request or response, such as adding request headers

  • The filter configured under the route only takes effect on the request of the current route

What is the role of defaultFilters?

  • A filter that applies to all routes

global filter

For the filters we mentioned earlier, the gateway provides 31 types, but the role of each filter is fixed. If we want to intercept requests and do our own business logic, there is no way to achieve it.

global filter action

The role of the global filter is to process all requests and microservice responses entering the gateway, just like the GatewayFilter. The difference is that GatewayFilter is defined by configuration, and the processing logic is fixed; while the logic of GlobalFilter needs to be implemented by writing its own code.

It is defined by implementing the GlobalFilter interface.

public interface GlobalFilter {
    
    
    /**
     *  处理当前请求,有必要的话通过{@link GatewayFilterChain}将请求交给下一个过滤器处理
     *
     * @param exchange 请求上下文,里面可以获取Request、Response等信息
     * @param chain 用来把请求委托给下一个过滤器 
     * @return {@code Mono<Void>} 返回标示当前过滤器业务结束
     */
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}

Write custom logic in the filter to achieve the following functions:

  • Login status judgment
  • permission check
  • Request current limit, etc.

custom global filter

Requirements: Define global filters, intercept requests, and determine whether the parameters of the request meet the following conditions:

  • Whether there is authorization in the parameter,

  • Whether the value of the authorization parameter is admin

Release if both are satisfied, otherwise intercept

accomplish:

Define a filter in gateway:

package cn.itcast.gateway.filters;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter {
    
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
    
        // 1.获取请求参数
        MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
        // 2.获取authorization参数
        String auth = params.getFirst("authorization");
        // 3.校验
        if ("admin".equals(auth)) {
    
    
            // 放行
            return chain.filter(exchange);
        }
        // 4.拦截
        // 4.1.禁止访问,设置状态码
        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
        // 4.2.结束处理
        return exchange.getResponse().setComplete();
    }
}

filter execution order

Requests entering the gateway will encounter three types of filters: the current route filter, DefaultFilter, GlobalFilter

After requesting a route, the current route filter, DefaultFilter and GlobalFilter will be combined into a filter chain (collection), and each filter will be executed in turn after sorting:

insert image description here

What are the sorting rules?

  • Each filter must specify an order value of type int. The smaller the order value, the higher the priority and the higher the execution order .
  • GlobalFilter specifies the order value by implementing the Ordered interface, or adding the @Order annotation, which is specified by ourselves
  • The order of route filters and defaultFilters is specified by Spring, and the default is to increase from 1 in the order of declaration.
  • When the order value of the filter is the same, it will be executed in the order of defaultFilter > Route Filter > GlobalFilter.

For details, you can view the source code:

org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters()The method is to load the defaultFilters first, then load the filters of a route, and then merge.

org.springframework.cloud.gateway.handler.FilteringWebHandler#handle()The method will load the global filter, merge it with the previous filter and sort it according to the order, and organize the filter chain

cross domain problem

What is a cross-domain problem

Cross-domain: Inconsistent domain names are cross-domain, including:

  • Different domain names: www.taobao.com and www.taobao.org and www.jd.com and miaosha.jd.com

  • Same domain name, different ports: localhost:8080 and localhost:8081

Cross-domain problem: The browser prohibits the originator of the request from making a cross-domain ajax request with the server, and the request is intercepted by the browser

Solution: CORS, this should be learned before, so I won't repeat it here.

For those who don't know, you can check https://www.ruanyifeng.com/blog/2016/04/cors.html

Simulate cross-domain problems

Put the webpage with cross-domain problem into a web server such as tomcat or nginx, start and access it.

The following error can be seen in the browser console:

insert image description here

Access localhost:10010 from localhost:8090, the port is different, it is obviously a cross-domain request.

Solve cross-domain problems

In the application.yml file of the gateway service, add the following configuration:

spring:
  cloud:
    gateway:
      # 。。。
      globalcors: # 全局的跨域处理
        add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
        corsConfigurations:
          '[/**]':
            allowedOrigins: # 允许哪些网站的跨域请求 
              - "http://localhost:8090"
            allowedMethods: # 允许的跨域ajax的请求方式
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*" # 允许在请求中携带的头信息
            allowCredentials: true # 是否允许携带cookie
            maxAge: 360000 # 这次跨域检测的有效期

Guess you like

Origin blog.csdn.net/zyb18507175502/article/details/126690559