1. Basic introduction

Gateway development generally refers to: unified application traffic entry, responsible for forwarding requests to specified services;

Spring-cloud-gateway: a gateway developed based on Spring5.0, Spring Boot 2.0, Project Reactor and other technologies, aims to provide a simple and effective unified API route management method for microservice architecture;

1.1 General Gateway Functions

The following is the basic functional structure of the gateway, starting from these points;

1.2 Introduction to Unique Attributes

About SpringCloud:

  1. Based on Spring Framework 5, Project Reactor and Spring Boot 2.0;

  2. Integrated Hystrix circuit breaker;

  3. Integrate Spring Cloud discoveryClient (eurake and Ribbon can be integrated to achieve load balancing);

  4. Predicates and filters are easy to write for specific routes.

  5. It has some advanced gateway functions: dynamic routing, traffic limiting, and path rewriting.

Predicate.

Predicate for Java8, which can be used to match anything in an Http request, such as headers or a parameter. The input type of predicate is a ServerWebExchange;

Route

A processing unit consisting of a jump URI, a group of predicate, and a group of filters;

Filter

Intercepting and modifying requests;

2. Getting started

2.1 Code Configuration

Taking interface login authentication as an example, we implement a simple gateway requirement.

Brief description of requirements:

Interfaces such as /login /send_code that do not require authentication are configured.

Authentication is required for other interfaces.

Note: The header contains a user_token, indicating login

Core implementation class: AuthGatewayFilterFactory

@Component
public class AuthGatewayFilterFactory extends AbstractGatewayFilterFactory<AuthGatewayFilterFactory.Config> {

    private Logger logger = LoggerFactory.getLogger(AuthGatewayFilterFactory.class);

    /** * User login status token */
    private static final String USER_TOKEN = "user_token";

    public AuthGatewayFilterFactory(a){
        super(Config.class);
        logger.info("AuthGatewayFilterFactory init");
    }

    @Override
    public List<String> shortcutFieldOrder(a) {
        return Collections.singletonList("ignoreUrlListStr");
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            // Verify whether the login URL is not required
            String path = request.getPath().toString();
            logger.info("AuthGatewayFilterFactory.apply path:{}",path);


            String ignoreUrlListStr = config.ignoreUrlListStr;
            logger.info("AuthGatewayFilterFactory.apply ignoreUrlListStr={}",ignoreUrlListStr);

            boolean ignoreOk = Arrays.asList(ignoreUrlListStr.split("\ |")).contains(path);
            if(ignoreOk){
                return chain.filter(exchange);
            }

            // Verify whether to log in
            HttpHeaders headers = request.getHeaders();
            String userToken = headers.getFirst(USER_TOKEN);
            if(StringUtils.isEmpty(userToken)){
                // No login message is displayed
                ServerHttpResponse response = exchange.getResponse();
                response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
                response.setStatusCode(HttpStatus.UNAUTHORIZED);

                Map<String, Object> bodyMap = new HashMap<>();
                bodyMap.put("code", -1000003);
                bodyMap.put("message"."Not logged in");

                byte[] responseByteArray = JSON.toJSONBytes(bodyMap);
                DataBuffer responseBuffer = response.bufferFactory().allocateBuffer(responseByteArray.length).write(responseByteArray);
                return response.writeWith(Mono.just(responseBuffer));
            }
            logger.info("AuthGatewayFilterFactory.apply user-token={}",userToken);
            return chain.filter(exchange);
        };
    }

    public static class Config {
        private String ignoreUrlListStr;

        public String getIgnoreUrlListStr(a) {
            return ignoreUrlListStr;
        }

        public void setIgnoreUrlListStr(String ignoreUrlListStr) {
            this.ignoreUrlListStr = ignoreUrlListStr; }}}Copy the code

Application. The properties configuration

# Gateway configuration -- Login - free authentication configuration
spring.cloud.gateway.routes[0].id = login_auth
spring.cloud.gateway.routes[0].uri = https://www.baidu.com
spring.cloud.gateway.routes[0].predicates[0] = Path=/**
spring.cloud.gateway.routes[0].filters[0] = Auth=/login|/send_code
Copy the code

The configuration is explained as follows: Define a route: Name: login authentication

Jump URL: Baidu address assertion: intercept all requests

Filters: intercept everything except /login and /send_code;

2.2 Operating Effect

Non-exempt login

curl –location –request GET ‘localhost:80/eat/apple’

{
    "code": - 1000003.."message": "Not logged in"
}
Copy the code

Non-exempt login

curl –location –request GET ‘localhost:80/eat/apple’ \

–header ‘user_token: 12138’

NOT FOUND
Copy the code

Exempted from inspection interface

curl –location –request GET ‘localhost:80/login’

Not Found
Copy the code

3. The integration of Apollo

3.1 Preparing the Environment

First, prepare the Apollo environment, see apollo-SH project;

3.2 Project Configuration

pom.xml

<properties>
        <java.version>1.8</java.version>
        <lombok.version>1.18.10</lombok.version>
        <fastjson.version>1.2.78</fastjson.version>
        <spring-cloud-version>2.1.0. RELEASE</spring-cloud-version>
        <apollo-client.version>1.9.1</apollo-client.version>
</properties>

<dependency>
    <groupId>com.ctrip.framework.apollo</groupId>
    <artifactId>apollo-client</artifactId>
    <version>${apollo-client.version}</version>
</dependency>
Copy the code

application.yml

# Apollo start configuration

app:
  id: yiyi-gateway
apollo:
  bootstrap:
    namespaces: application
    enabled: true
  meta: http://172.16.146.231:9001

ENV: DEV
Copy the code

Note: At this point, we can move the gateway configuration from application.yml to Apollo;

Fix Apollo change configuration project out of sync

/** * Apollo refresh gateway configuration synchronization problem resolved */
@Component
public class GatewayPropertiesRefresher implements ApplicationContextAware.ApplicationEventPublisherAware {
    private static final Logger logger = LoggerFactory.getLogger(GatewayPropertiesRefresher.class);

    private ApplicationContext applicationContext;

    private ApplicationEventPublisher publisher;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }


    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }

    @ApolloConfigChangeListener
    public void onChange(ConfigChangeEvent changeEvent) {
        this.applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
        logger.info("GatewayPropertiesRefresher.onChange apollo GatewayProperties refreshed"); }}Copy the code

4. Integration of eureka

 <properties>
     <java.version>1.8</java.version>
     <lombok.version>1.18.10</lombok.version>
     <fastjson.version>1.2.78</fastjson.version>
     <spring-cloud-version>2.1.0. RELEASE</spring-cloud-version>
     <apollo-client.version>1.9.1</apollo-client.version>
 </properties>        

 <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
      <version>${spring-cloud-version}</version>
 </dependency>
Copy the code

5. Integrate the sentinel

5.1 Preparing the Environment

See also: Github-Sentinel Rapid Launch Project;

5.2 Project Configuration

pom.xml

<! -- Alibaba traffic guard -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
    <version>2.1.0. RELEASE</version>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    <version>2.1.0. RELEASE</version>
</dependency>
Copy the code

application.yml

spring:  
  cloud:
    # Sentinel current limiting configuration
    sentinel:
      transport:
        dashboard: yiyi.cn:18085
        port: 18085
      # service startup establishes heartbeat connection directly
      eager: true
Copy the code

Run the check

Note: Refer to the sentinel official documentation to run the entire test script

see

Spring-cloud-gateway management HTTP API

SpringCloud Gateway (most complete ever) – Crazy Maker Community – Blog Park

Github – Annotated version of spring-cloud-gateway source code