网关的主要作用是
1,隐藏真正的域名和端口号
2,用路径匹配的方式。
3,可以添加过滤器
新建一个Gateway的项目
pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud</artifactId>
<groupId>com.home</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>gateway</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-web</artifactId>-->
<!--</dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>
mybatis-spring-boot-starter
</artifactId>
</dependency>
<dependency>
<artifactId>common</artifactId>
<groupId>com.home</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--<dependency>-->
<!--<groupId>com.alibaba</groupId>-->
<!--<artifactId>druid-spring-boot-starter</artifactId>-->
<!--<version>1.1.9</version>-->
<!--</dependency>-->
<!--<dependency>-->
<!--<groupId>mysql</groupId>-->
<!--<artifactId>mysql-connector-java</artifactId>-->
<!--</dependency>-->
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-jdbc</artifactId>-->
<!--</dependency>-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
注意 不能引入spring boot starter web
否则要报错 因为cloud用的是webflux
yml
server:
port: 3579
spring:
application:
name: gateway
cloud:
gateway:
routes:
- id: pay01
uri: http://localhost:8001
predicates:
- Path=/pay/get/**
# datasource.type=com.alibaba.druid.pool.DruidDataSource
# spring.datasource.url = jdbc:mysql://127.0.0.1:3306/demo
# spring.datasource.username = root
# spring.datasource.password = 123456
# spring.datasource.driverClassName = com.mysql.jdbc.Driver
# datasource:
# type:
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
# 单机模式
defaultZone: http://localhost:7001/eureka
#集群模式
# defaultZone: http://eureka2.com:7002/eureka,http://eureka.com:7001/eureka
instance:
instance-id: gateway:3579
prefer-ip-address: true
# 这个是为了和服务端沟通的频率
# lease-renewal-interval-in-seconds: 1
# 这个是服务端的耐心
# lease-expiration-duration-in-seconds: 2
#eureka.instance.lease-renewal-interval-in-seconds # 续约更新时间间隔(默认30秒)
#eureka.instance.lease-expiration-duration-in-seconds # 续约到期时间(默认90秒)
# filters:
# # {} 是用来取值的
# - RewritePath=/api/(?<segment>.*), /$\{segment}
#
# - id: oms_route
# uri: lb://gulimall-oms
# predicates:
# - Path=/oms/**
# filters:
# - AddResponseHeader=heyijie,666
# - id: sms_route
# uri: lb://gulimall-sms
# predicates:
# - Path=/sms/**
# - id: ums_route
# uri: lb://gulimall-ums
# predicates:
# - Path=/ums/**, /api/ums/**
# filters:
# # {} 是用来取值的
# - RewritePath=/api/(?<segment>.*), /$\{segment}
#
# - id: wms_route
# uri: lb://gulimall-wms
# predicates:
# - Path=/wms/**
# - id: gulimall_search_route
# uri: lb://gulimall-search
# predicates:
# # 可能会有特殊字符转义 \{
# - Path=/api/search/**
# filters:
# - RewritePath=/api/(?<segment>.*), /$\{segment}
主要配置的一些参数就是 id ;唯一和数据库一样
uri 替代的主机地址和端口号
predicates 也就是匹配的路径。
也就是当别人用gateway
的主机和端口访问 http://localhost:3579/pay/get/1 就会访问到 http://localhost:8001/pay/get/1 主要就是这么个过程。这样配置后就生效了
我们还可以用java
的方式配置
package home.config;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Gate {
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("first", r -> r.path("/guoji").uri("https://news.baidu.com/"))
// .filters(f -> f.circuitBreaker(c -> c.name("myCircuitBreaker").fallbackUri("forward:/inCaseOfFailureUseThis"))
// .rewritePath("/consumingServiceEndpoint", "/backingServiceEndpoint")).uri("lb://backing-service:8088")
.build();
}
}
根据官网提供的demo
我们这样配置也是生效的,如果我们http://localhost:3579/guoji 就会访问到 http://news.baidu.com/guoji。
如何用gateway开启负载均衡
server:
port: 3579
spring:
application:
name: gateway
cloud:
gateway:
routes:
- id: pay01
uri: lb://pay-service
predicates:
- Path=/pay/get/**
discovery:
locator:
enabled: true
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
# 单机模式
defaultZone: http://localhost:7001/eureka
#集群模式
# defaultZone: http://eureka2.com:7002/eureka,http://eureka.com:7001/eureka
instance:
instance-id: gateway:3579
prefer-ip-address: true
# 这个是为了和服务端沟通的频率
# lease-renewal-interval-in-seconds: 1
# 这个是服务端的耐心
# lease-expiration-duration-in-seconds: 2
#eureka.instance.lease-renewal-interval-in-seconds # 续约更新时间间隔(默认30秒)
#eureka.instance.lease-expiration-duration-in-seconds # 续约到期时间(默认90秒)
主要是 uri: lb://pay-service 这个配置和
discovery:
locator:
enabled: true
开启这个功能,就ok了。
predicates 具体是什么?相当于sql的查询条件。
Loaded RoutePredicateFactory [After]
Loaded RoutePredicateFactory [Before]
Loaded RoutePredicateFactory [Between]
Loaded RoutePredicateFactory [Cookie]
Loaded RoutePredicateFactory [Header]
Loaded RoutePredicateFactory [Host]
Loaded RoutePredicateFactory [Method]
Loaded RoutePredicateFactory [Path]
Loaded RoutePredicateFactory [Query]
Loaded RoutePredicateFactory [ReadBodyPredicateFactory]
Loaded RoutePredicateFactory [RemoteAddr]
Loaded RoutePredicateFactory [Weight]
Loaded RoutePredicateFactory [CloudFoundryRouteService]
这个是启动时候的日志
官网配置的地址
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.2.RELEASE/reference/html/#the-cookie-route-predicate-factory
yml中修改predicates
spring:
application:
name: gateway
cloud:
gateway:
routes:
- id: pay01
uri: lb://pay-service
predicates:
- Path=/pay/get/**
# - Cookie=haha, come
- Header=shuxing, \d+
- Method=GET,POST
- After=2020-05-23T08:11:28.767+08:00[Asia/Shanghai]
discovery:
locator:
enabled: true
测试中curl的使用
curl http://localhost:3579/pay/get/1 --cookie “haha=come” 测试cookie
curl http://localhost:3579/pay/get/1 -H “shuxing:10” 测试Header
下面说说过滤器,和之前的filter差不多
我们写一个全局的过滤器
package home.config;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class GateFilter implements GlobalFilter,Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String name = exchange.getRequest().getQueryParams().getFirst("name");
if (name == null) {
System.out.println("非法用户");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);return exchange.getResponse().setComplete();
}
return chain.filter(
exchange
);
}
@Override
public int getOrder() {
return 0;
}
}
这个用了注解,不需要配置。可以做校验,也可以做日志的处理。