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:
-
Based on Spring Framework 5, Project Reactor and Spring Boot 2.0;
-
Integrated Hystrix circuit breaker;
-
Integrate Spring Cloud discoveryClient (eurake and Ribbon can be integrated to achieve load balancing);
-
Predicates and filters are easy to write for specific routes.
-
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