文章目录
- 一、介绍
- 1.1 简介
- 1.2 Gateway加入后的架构
- 1.3 核心概念
- 二、入门案例
- 2.1 父工程pom.xml
- 2.2 服务提供者
- 2.2.1 pom.xml
- 2.2.2 application.yml
- 2.2.3 User.java
- 2.2.4 UserMapper.java
- 2.2.5 UserService
- 2.2.6 UserServiceImpl.java
- 2.2.7 UserController.java
- 2.2.8 UserServiceApplication.java
- 2.3 注册中心
- 2.3.1 pom.xml
- 2.3.2 application.yml
- 2.3.3 EurekaServerApplication.java
- 2.4 网关服务
- 2.4.1 pom.xml
- 2.4.2 application.yml
- 2.4.3 GatewayServerApplication.java
- 2.5 功能
- 2.5 测试结果
- 2.6 面向服务
- 2.7 路由前缀
- 2.7.1 介绍
- 2.7.2 添加前缀
- 2.7.3 去除前缀
- 2.8 过滤器
- 2.8.1 配置默认过滤器
- 2.8.2 分类
- 2.8.3 生命周期
- 2.8.4 使用场景
- 2.9 自定义过滤器
- 2.9.1 自定义过滤器
- 2.9.2 自定义局部过滤器
- 2.9.2.1 过滤器
- 2.9.2.2 过滤器 配置文件
- 2.9.3 自定义全局过滤器
- 2.9.3.1 过滤器
- 2.9.3.2 测试结果
- 2.10 总结和其他
- 2.10.1 负载均衡
- 2.10.2 Gateway跨域配置
- 2.10.3 Gateway高可用
- 2.10.4 与Feign的区别
一、介绍
1.1 简介
- Spring Cloud Gateway是Spring官网基于Spring 5.0、 Spring Boot 2.0、Project Reactor等技术开发的网关服务。
- Spring Cloud Gateway基于Filter链提供网关基本功能:安全、监控/埋点、限流等。
- Spring Cloud Gateway为微服务架构提供简单、有效且统一的API路由管理方式。
- Spring Cloud Gateway是替代Netflix Zuul的一套解决方案。
1.2 Gateway加入后的架构
无论是来自客户端(pc、移动端)的请求,还是服务内部的调用。一切对服务的请求都可以经过网关,然后由网关来实现 鉴权、动态路由等等操作。此时Gateway(网关)就是我们服务的统一入口。
1.3 核心概念
- 路由(route):由一个ID、一个目的URL(真实的服务地址)、一组断言工厂、一组Filter组成;如果路由断言为真,说明URL和配置路由匹配。
- 断言(Predicate):Spring Cloud Gateway中的断言函数输入类型是Spring 5.0框架中的 ServerWebExchange。Spring Cloud Gateway的断言函数允许开发者去定义 匹配来自于HTTP Request中的任何信息,比如请求头和参数。
- 过滤器(Filter):一个标准的Spring WebFilter。Spring Cloud Gateway中的Filter分为两种类型,分别是Gateway Filter(局部过滤器) 和 Global Filter(全局过滤器)。过滤器Filter将会对请求和响应进行修改处理
二、入门案例
2.1 父工程pom.xml
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kaikeba</groupId>
<artifactId>springcloud-gateway</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>gateway-server</module>
<module>eureka-server</module>
<module>user-service</module>
</modules>
<!-- springboot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.18.RELEASE</version>
<relativePath/>
</parent>
<properties>
<java.version>1.8</java.version>
<springcloud.version>Greenwich.SR1</springcloud.version>
<tk.mybatis.version>2.1.5</tk.mybatis.version>
<mysql.connector.version>8.0.25</mysql.connector.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- spring cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${springcloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- tk-mybatis -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>${tk.mybatis.version}</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.2 服务提供者
使用user-service当作服务提供者
2.2.1 pom.xml
<?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>springcloud-gateway</artifactId>
<groupId>com.kaikeba</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>user-service</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
</project>
2.2.2 application.yml
server:
port: ${port:10000}
spring:
application:
name: user-service # 服务名
datasource: # 数据源
username: root
password: root
url: jdbc:mysql://localhost:3306/springcloud
driver-class-name: com.mysql.cj.jdbc.Driver
eureka:
client:
service-url:
defaultZone: http://localhost:8080/eureka # 注册中心地址
instance:
ip-address: 127.0.0.1 # 显示的ip
prefer-ip-address: true # 以ip的形式被调用
lease-expiration-duration-in-seconds: 90 # 服务失效时间:默认90s
lease-renewal-interval-in-seconds: 30 # 服务续约的时间间隔
2.2.3 User.java
package com.kaikeba.entity;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.persistence.*;
import java.util.Date;
@Data
@Accessors(chain = true)
@Table(name = "tb_user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "user_name")
private String username;
private String password;
private String name;
private Integer age;
private Integer sex;
private Date birthday;
private Date created;
private Date updated;
private String note;
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
", birthday=" + birthday +
", created=" + created +
", updated=" + updated +
", note='" + note + '\'' +
'}';
}
}
2.2.4 UserMapper.java
package com.kaikeba.mapper;
import com.kaikeba.entity.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends tk.mybatis.mapper.common.Mapper<User> {
}
2.2.5 UserService
package com.kaikeba.service;
import com.kaikeba.entity.User;
public interface UserService {
/**
* 根据主键查询
*/
User findById(Integer userId);
}
2.2.6 UserServiceImpl.java
package com.kaikeba.service.impl;
import com.kaikeba.entity.User;
import com.kaikeba.mapper.UserMapper;
import com.kaikeba.service.UserService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Override
public User findById(Integer userId) {
return userMapper.selectByPrimaryKey(userId);
}
}
2.2.7 UserController.java
package com.kaikeba.controller;
import com.kaikeba.entity.User;
import com.kaikeba.service.UserService;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping("/user")
public class UserController {
@Resource
private UserService userService;
@RequestMapping("/{userId}")
public String searchByUserId(@PathVariable Integer userId) {
User user = userService.findById(userId);
return user.toString();
}
}
2.2.8 UserServiceApplication.java
package com.kaikeba;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableEurekaClient
@SpringBootApplication
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class);
}
}
2.3 注册中心
2.3.1 pom.xml
<?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>springcloud-gateway</artifactId>
<groupId>com.kaikeba</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka-server</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
2.3.2 application.yml
server:
port: 8080
spring:
application:
name: eureka-server
eureka:
client:
service-url:
defaultZone: http://localhost:8080/wureka # 服务注册的端口
register-with-eureka: false # b不注册自己
server:
enable-self-preservation: false # 关闭自我保护
eviction-interval-timer-in-ms: 6000 #失效服务扫描时间间隔
2.3.3 EurekaServerApplication.java
package com.kaikeba;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class);
}
}
2.4 网关服务
2.4.1 pom.xml
<?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>springcloud-gateway</artifactId>
<groupId>com.kaikeba</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>gateway-server</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>
</dependencies>
</project>
2.4.2 application.yml
server:
port: 9090
spring:
application:
name: gateway-server
cloud:
gateway:
routes:
- id: user-service-route #路由id,随便写
uri: http://127.0.0.1:10000 # 代理的微服务地址,真实的微服务地址
# 路由断言:配置映射路径
predicates:
- Path= /user/**
eureka:
client:
service-url:
defaultZone: http://localhost:8080/eureka
instance:
prefer-ip-address: true
2.4.3 GatewayServerApplication.java
package com.kaikeba;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient // 开启eureka注册发现功能
@SpringBootApplication
public class GatewayServerApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayServerApplication.class);
}
}
2.5 功能
我们的现在的案例实现的功能就是将地址:http://localhost:9090/ 的所有带有"/user"路径的请求,全部代理到 http://127.0.0.1:10000 这个地址;
2.5 测试结果
user-service自己的查询结果:
通过网关服务访问的接口:
2.6 面向服务
我们上面的示例中,网关配的代理服务的地址我们是写死的 http://127.0.0.1:10000 ;如果同一个服务有多个实例的话,这样做显然不合理。 比较合理的方式应该是根据服务的名称,去Eureka注册中心查找 服务对应的所有实例列表,然后进行动态路由!
所以,我们的配置文件可以改造成如下:
server:
port: 9090
spring:
application:
name: gateway-server
cloud:
gateway:
routes:
- id: user-service-route #路由id,随便写
#uri: http://127.0.0.1:10000 # 代理的微服务地址,真实的微服务地址
uri: lb://user-service
# 路由断言:配置映射路径
predicates:
- Path= /user/**
eureka:
client:
service-url:
defaultZone: http://localhost:8080/eureka
instance:
prefer-ip-address: true
其中,uri: lb://user-service的意思是,网关将会使用LoadBalancerClient 把 user-service 通过eureka解析为实际的主机和端口,来进行ribbon负载均衡(动态路由代理);
测试结果,同样是可行的:
2.7 路由前缀
2.7.1 介绍
当客户端的请求地址与微服务的服务地址不一致的时候,我们可以通过配置路径过滤器来实现路径前缀的添加和去除;
提供服务的地址:http://localhost:10000/user/{id}
- 添加前缀:就是对请求地址添加前缀路径之后,再作为代理的服务地址;
如:http://127.0.0.1:10010/8 --> http://127.0.0.1:9091/user/8
添加前缀路径 /user - 去除前缀:将请求地址中路径去除一些前缀路径之后再作为代理的服务地址;如:
- http://127.0.0.1:10010/api/user/8 --> http://127.0.0.1:9091/user/8
- 去除前缀路径/api
2.7.2 添加前缀
在网关gateway中通过 - PrefixPath 添加前缀,如下,是添加 /user 前缀;
spring:
cloud:
gateway:
routes:
filters:
- PrefixPath=/user # 添加前缀
完整的yml配置:
server:
port: 9090
spring:
application:
name: gateway-server
cloud:
gateway:
routes:
- id: user-service-route #路由id,随便写
# uri: http://127.0.0.1:10000 # 代理的微服务地址,真实的微服务地址
uri: lb://user-service
# 路由断言:配置映射路径
predicates:
- Path= /**
filters:
- PrefixPath=/user # 添加前缀
eureka:
client:
service-url:
defaultZone: http://localhost:8080/eureka
instance:
prefer-ip-address: true
测试结果:
通过 PrefixPath=/xxx 来指定了路由要添加的前缀。 也就是:
- PrefixPath=/user http://localhost:10010/8 --> http://localhost:9091/user/8
- PrefixPath=/user/abc http://localhost:10010/8 --> http://localhost:9091/user/abc/8
2.7.3 去除前缀
在网关gateway中通过 - StripPrefix 添加前缀,如下,是添加 /user 前缀;
spring:
cloud:
gateway:
routes:
filters:
- StripPrefix=1 # 去除前缀:1 表示去除一个前缀,2表示去除两个,以此类推
完整的yml配置:
server:
port: 9090
spring:
application:
name: gateway-server
cloud:
gateway:
routes:
- id: user-service-route #路由id,随便写
# uri: http://127.0.0.1:10000 # 代理的微服务地址,真实的微服务地址
uri: lb://user-service
# 路由断言:配置映射路径
predicates:
- Path=/api/user/**
filters:
- StripPrefix=1 # 去除前缀:1 表示去除一个前缀,2表示去除两个,以此类推
eureka:
client:
service-url:
defaultZone: http://localhost:8080/eureka
instance:
prefer-ip-address: true
测试结果:
2.8 过滤器
Gateway作为网关的其中一个重要功能,就是实现请求的鉴权。而这个动作往往是通过网关提供的过滤器来实现的。前面的 路由前缀 的功能也是使用过滤器实现的。
Gateway常见的过滤器有几十个,常见的有以下几个:
过滤器名称 | 说明 |
ddRequestHeader | 为匹配到的请求添加Header |
AddRequestParameters | 为匹配上的请求路由添加参数 |
AddResponseHeader | 为从网关返回的响应添加Header |
AddResponseHeader | 为对从网关返回的响应添加Header |
其他的不列举,详细的说明参考官网
2.8.1 配置默认过滤器
server:
port: 9090
spring:
application:
name: gateway-server
cloud:
gateway:
routes:
- id: user-service-route #路由id,随便写
# uri: http://127.0.0.1:10000 # 代理的微服务地址,真实的微服务地址
uri: lb://user-service
# 路由断言:配置映射路径
predicates:
#- Path= /user/**
#- Path= /**
- Path=/api/user/**
filters:
# - PrefixPath=/user # 添加前缀
- StripPrefix=1 # 去除前缀:1 表示去除一个前缀,2表示去除两个,以此类推
#- MyParam=name
eureka:
client:
service-url:
defaultZone: http://localhost:8080/eureka
instance:
prefer-ip-address: true
再访问 http://localhost:9090/api/user/2 的话;就可以从其响应中查看到如下信息:
2.8.2 分类
- 局部过滤器:通过 spring.cloud.gateway.routes.filters 配置在具体路由下,只作用在当前路由上;如果配置spring.cloud.gateway.default-filters 上会对所有路由生效也算是全局的过滤器;但是这些过滤器 的
实现上都是要实现GatewayFilterFactory接口。 - 全局过滤器:不需要在配置文件中配置,作用在所有的路由上;实现 GlobalFilter 接口即可。
2.8.3 生命周期
Spring Cloud Gateway 的 Filter 的生命周期也类似Spring MVC的拦截器有两个:“pre” 和 “post”。“pre”和 “post”分别会在请求被执行前调用和被执行后调用
2.8.4 使用场景
- 请求鉴权:一般 GatewayFilterChain 执行filter方法前,如果发现没有访问权限,直接就返回空。
- 异常处理:一般 GatewayFilterChain 执行filter方法后,记录异常并返回。
- 服务调用时长统计: GatewayFilterChain 执行filter方法前后根据时间统计。
2.9 自定义过滤器
需求:将http://localhost:10010/api/user/8?name=lxs中的参数name值获取并返回;
ps:并且参数名是可变的,也就是不一定每次都是name;需要可以通过配置过滤器的时候做到配置参数名。
2.9.1 自定义过滤器
- 通过配置文件,配置要返回的值的参数名;
- 实现对应配置的过滤器;
- 自定义局部过滤器要实现GatewayFilterFactory接口,或继承其子类,并且在配置文件中进行配置;
- 全局过滤器要实现GlobalFilter接口,不用配置;
2.9.2 自定义局部过滤器
2.9.2.1 过滤器
package com.kaikeba.filter;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
/**
* 参数过滤器
*/
@Component
public class MyParamGatewayFilterFactory extends AbstractGatewayFilterFactory<MyParamGatewayFilterFactory.ConfigParam> {
public MyParamGatewayFilterFactory() {
super(ConfigParam.class);
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("param");
}
@Override
public GatewayFilter apply(ConfigParam config) {
return ((exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
if(request.getQueryParams().containsKey(config.param)) {
request.getQueryParams().get(config.param).forEach((str) -> {
System.out.printf("------ 局部过滤器获得参数 " + config.param + " = " + str);
});
}
return chain.filter(exchange); // 执行请求,在这个方法之前是前置过虑器,之后是后置过滤器
});
}
/**
* 读取过滤器配置的参数
*/
public static class ConfigParam{
// 获取配置在application.yml配置文件中的过滤器参数
private String param;
public String getParam() {
return param;
}
public void setParam(String param) {
this.param = param;
}
}
}
2.9.2.2 过滤器 配置文件
我们看到所有的过滤器都是“过滤器名+GatewayFilterFactory”,配置的时候配置 “- 过滤器名”;所以我们的配置就是 ”- MyParam = 参数名“
server:
port: 9090
spring:
application:
name: gateway-server
cloud:
gateway:
routes:
- id: user-service-route #路由id,随便写
# uri: http://127.0.0.1:10000 # 代理的微服务地址,真实的微服务地址
uri: lb://user-service
# 路由断言:配置映射路径
predicates:
- Path=/api/user/**
filters:
- StripPrefix=1 # 去除前缀:1 表示去除一个前缀,2表示去除两个,以此类推
- MyParam=name
# 默认过滤器,对所有路由都生效
default-filters:
- AddResponseHeader=X-Response-Foo, Bar
- AddResponseHeader=abc-myname,lxs
eureka:
client:
service-url:
defaultZone: http://localhost:8080/eureka
instance:
prefer-ip-address: true
测试结果:
2.9.3 自定义全局过滤器
需求:编写全局过滤器,在过滤器中检查请求中是否携带token请求头。如果token请求头存在则放行;如果token
为空或者不存在则设置返回的状态码为:未授权也不再执行下去。
2.9.3.1 过滤器
除了要实现GlobalFilter接口外,还要实现Order接口,这个接口的作用是定义过滤器的优先级,getOrder() 的返回值越小,优先级越高。
package com.kaikeba.filter;
import io.netty.util.internal.StringUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
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;
import java.lang.annotation.Annotation;
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 全局过虑器,
String token = exchange.getRequest().getHeaders().getFirst("token");
if(StringUtils.isBlank(token)) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete(); // 直接让过滤器链结束
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
// 值越小,优先级越高
return 1;
}
}
2.9.3.2 测试结果
没有token请求头,返回401错误:
添加token参数,请求成功:
2.10 总结和其他
2.10.1 负载均衡
Gateway中默认集成了Ribbon负载均衡和Hystrix熔断机制,而且自动配置有默认值;如熔断时间只有1s;当然,我们也可以显式的手动配置,下面是常用的配置项:
Hystris熔断:
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000 #服务降级超时时间,默认1S
Ribbon负载均衡:
ribbon:
ConnectTimeout: 1000 # 连接超时时长
ReadTimeout: 2000 # 数据通信超时时长
MaxAutoRetries: 0 # 当前服务器的重试次数
MaxAutoRetriesNextServer: 0 # 重试多少次服务的所有实例(当前实例也会再试一次)
2.10.2 Gateway跨域配置
- 跨域:如果发送请求时访问的地址与服务所在的服务器的域名、ip、或端口不一致,就叫做跨域请求;当存在跨域问题时,若不解决,就会是服务出现错误。常见的如前端访问后台服务;现在的前后端分离的开发则必然会涉及到跨域问题。
- 一般来说,网关都是微服务的统一入口,所以在调用的时候,必然会存在跨域问题;如我们的案例中 http://localhost:9090 跳转访问 http://localhost:20000 其中端口不同,所以也算是跨域请求。
- 若在访问Spring Cloud Gateway网关服务的时候出现跨域问题,可以在网管服务中通过配置解决,设置课通过的跨域请求:配置如下:
spring:
cloud:
globalcors: # 表示进行跨域配置
corsConfigurations:
'[/**]':
#allowedOrigins: * # * 表示允许全部的访强求通过
allowedOrigins:
- "http://docs.spring.io" # 允许来自于这个网址的请求进行跨域请求
allowedMethods:
- GET # 允许GET类型的请求通过
我们上面的这段配置的意思是:允许来自 http://docs.spring.io 的 GET 类型的请求通过。
allowedOrigins:指定允许访问的服务器地址,配成 ip:port 也是可以的(如:http://localhost:10000 );
2.10.3 Gateway高可用
- 启动多个Gateway服务注册到注册中心,形成集群,若是服务内访问Gateway,自动负载均衡;
- 外部访问是,客户端(PC端、移动端)无法通过Eureka进行负载均衡,此时需要通过其他的服务网关对Gateway进行代理(比如Nginx等)。
2.10.4 与Feign的区别
- Gateway作文整个应用的流量入口,接受所有的请求(pc、移动端等),并且将不同的请求转发至不同的微服务模块,起作用可以当做一个微服务内部的nginx;
- Gateway大部分情况下手机up们还自拍鉴权和服务端的流量控制;
- Feign是将当前微服务的部分服务接口暴露出来,主要用于微服务之间的服务调用。