网站首页 > 技术教程 正文
什么是网关?
随着微服务架构的普及,单体应用被拆分成多个服务,需要一个统一的访问入口。
搭建网关
两种方法:
- github上拉一个
- springcloud为用户准备好了网关的依赖,我们只需要在自己的springboot工程中引入网关依赖,就拥有了网关。
网关依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
启动类 Application.java
@SpringBootApplication
@EnableDiscoveryClient
@EnableEurekaClient
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
配置文件 application.yml
server:
port: 10000
spring:
application:
name: my-gateway
cloud:
gateway:
httpclient:
pool:
max-idle-time: 2000
discovery:
locator:
enabled: true
lowerCaseServiceId: true
filters:
- StripPrefix=1
eureka:
client:
registry-fetch-interval-seconds: 10
fetch-registry: true
registry-with-eureka: true
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
lease-expiration-duration-in-seconds: 10
lease-renewal-interval-in-seconds: 3
prefer-ip-address: true
metadata-map:
version: release
这样一个spring cloud gateway就创建好了。
网关设计
下图为网关内部架构设计,可以看到网关由一个netty-server,一个netty-client,多个route组成。
网关的核心:
● Route(路由):网关配置的基本组成模块,和Zuul网关的路由配置模块类似。一个Route模块由一个ID、一个目标URI、一组断言和一组过滤器组成。如果断言为真,则路由匹配,目标URI会被访问。
● Predicate(断言):Predicate来自Java 8的接口,它可以用来匹配来自HTTP请求的任何内容,例如headers或参数。接口包含多种默认方法,并将Predicate组合成复杂的逻辑(与、或、非),可以用于接口参数校验、路由转发判断等。
● Filter(过滤器):和Zuul的过滤器在概念上类似,可以使用Filter拦截和修改请求,实现对上游的响应,进行二次处理,实现横切与应用无关的功能,如安全、访问超时设置、限流等功能。
网关配置route的方式有两种,一个是配置文件,另一个是通过代码实现。
下面用一个静态路由做例子,
配置文件:
spring:
cloud:
gateway:
routes:
- id: my_route
uri: http://localhost:9011/
predicates:
- Path= /eureka-client2/**
filters:
- StripPrefix=1
代码:
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("my_route", r -> r.path("/eureka-client2/**")
.filters(f -> f.stripPrefix(1))
.uri("http://localhost:9011/"))
.build();
}
分别实现并展示,结果相同。
工作原理
自定义filter
网关自身提供了多个filter,可以通过配置文件进行装配,上面用到的- StripPrefix=1就是filter。
StripPrefixGatewayFilterFactory.java
public class StripPrefixGatewayFilterFactory
extends AbstractGatewayFilterFactory<StripPrefixGatewayFilterFactory.Config> {
...
@Override
public GatewayFilter apply(Config config) { // apply方法写filter逻辑
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange,
GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
addOriginalRequestUrl(exchange, request.getURI());
String path = request.getURI().getRawPath();
String newPath = "/"
+ Arrays.stream(StringUtils.tokenizeToStringArray(path, "/"))
.skip(config.parts).collect(Collectors.joining("/"));
newPath += (newPath.length() > 1 && path.endsWith("/") ? "/" : "");
ServerHttpRequest newRequest = request.mutate().path(newPath).build();
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR,
newRequest.getURI());
return chain.filter(exchange.mutate().request(newRequest).build());
}
@Override
public String toString() {
return filterToStringCreator(StripPrefixGatewayFilterFactory.this)
.append("parts", config.getParts()).toString();
}
};
}
...
}
通过工厂模式实现的过滤器是需要在配置文件中手动装配的,这种过滤器可以根据自己的需要在不同的routes上自由装配。
spring:
cloud:
gateway:
routes:
- id: my_route
uri: http://localhost:9011/
predicates:
- Path= /eureka-client2/**
filters:
- StripPrefix=1
还有一种实现过滤器的方式是实现GlobalFilter接口,这个方式不需要添加配置,所有routes都生效。
拿网关自带的filter举例子,RouteToRequestUrlFilter.java
public class RouteToRequestUrlFilter implements GlobalFilter, Ordered {
...
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
if (route == null) {
return chain.filter(exchange);
}
log.trace("RouteToRequestUrlFilter start");
URI uri = exchange.getRequest().getURI();
boolean encoded = containsEncodedParts(uri);
URI routeUri = route.getUri();
if (hasAnotherScheme(routeUri)) {
// this is a special url, save scheme to special attribute
// replace routeUri with schemeSpecificPart
exchange.getAttributes().put(GATEWAY_SCHEME_PREFIX_ATTR,
routeUri.getScheme());
routeUri = URI.create(routeUri.getSchemeSpecificPart());
}
if ("lb".equalsIgnoreCase(routeUri.getScheme()) && routeUri.getHost() == null) {
// Load balanced URIs should always have a host. If the host is null it is
// most
// likely because the host name was invalid (for example included an
// underscore)
throw new IllegalStateException("Invalid host: " + routeUri.toString());
}
URI mergedUrl = UriComponentsBuilder.fromUri(uri)
// .uri(routeUri)
.scheme(routeUri.getScheme()).host(routeUri.getHost())
.port(routeUri.getPort()).build(encoded).toUri();
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, mergedUrl);
return chain.filter(exchange);
}
...
}
我们可以通过断点,查看一条route有哪些filter,GatewayFilterChain对象里包含了filter信息。
- 上一篇: 如何动态刷新配置?
- 下一篇: SpringCloud:Feign的原理是什么?
猜你喜欢
- 2025-01-20 SpringCloud:Feign的原理是什么?
- 2025-01-20 如何动态刷新配置?
- 2025-01-20 SpringCloud之Nacos
你 发表评论:
欢迎- 最近发表
-
- Win11学院:如何在Windows 11上使用WSL安装Ubuntu
- linux移植(Linux移植freemodbus)
- 独家解读:Win10预览版9879为何无法识别硬盘
- 基于Linux系统的本地Yum源搭建与配置(ISO方式、RPM方式)
- Docker镜像瘦身(docker 减小镜像大小)
- 在linux上安装ollama(linux安装locale)
- 渗透测试系统Kali推出Docker镜像(kali linux渗透测试技术详解pdf)
- Linux环境中部署Harbor私有镜像仓库
- linux之间传文件命令之Rsync傻瓜式教程
- 解决ollama在linux中安装或升级时,通过国内镜像缩短安装时长
- 标签列表
-
- 下划线是什么 (87)
- 精美网站 (58)
- qq登录界面 (90)
- nginx 命令 (82)
- nginx .http (73)
- nginx lua (70)
- nginx 重定向 (68)
- Nginx超时 (65)
- nginx 监控 (57)
- odbc (59)
- rar密码破解工具 (62)
- annotation (71)
- 红黑树 (57)
- 智力题 (62)
- php空间申请 (61)
- 按键精灵 注册码 (69)
- 软件测试报告 (59)
- ntcreatefile (64)
- 闪动文字 (56)
- guid (66)
- abap (63)
- mpeg 2 (65)
- column (63)
- dreamweaver教程 (57)
- excel行列转换 (56)
本文暂时没有评论,来添加一个吧(●'◡'●)