Spring SpringCloud Gateway
前面已经做过性能比较了,Spring-Cloud-Gateway
确实比Zuul 1
性能更强,并且Spring
也不在支持Zuul 2
了。
以下是简单的迁移方案.
迁移Route
如果请求/demo/get
,想要转发到http://g.cn/real_context_path/get
.
-
Zuul
写法
zuul.routes.demo-1.path=/demo/**
zuul.routes.demo-1.url=http://g.cn/real_context_path
-
Spring Cloud Gateway
写法
spring.cloud.gateway.routes[0].id=demo-1
spring.cloud.gateway.routes[0].uri=http://g.cn
spring.cloud.gateway.routes[0].predicates[0]=Path=/demo/**
spring.cloud.gateway.routes[0].filters[0]=StripPrefix=1
spring.cloud.gateway.routes[0].filters[1]=PrefixPath=/real_context_path
这里使用了Path Route Predicate Factory, StripPrefix GatewayFilter Factory和PrefixPath GatewayFilter Factory
注意:如果uri
写成http://g.cn/real_context_path
是无效的,Spring Gateway只读取其中的Scheme
, Host
, Port
,其源码如下:
@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());
}
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);
}
迁移Filter
Filter
的迁移也比较简单,从原来的继承ZuulFilter
改为实现接口
GlobalFilter
或自定义Filter, Ordered
.
-
RequestContext.getCurrentContext().set(...)
通过exchange.getAttributes().put(...)
实现 - 获取Route,
RequestContext.getCurrentContext().getRouteHost()
通过exchange.getAttribute(GATEWAY_ROUTE_ATTR)
实现。 - Zuul 的
Post Filter
通过
exchange.then(Mono.fromRunnable(() -> {
ServerHttpResponse response = exchange.getResponse();
LOGGER.info(response.getStatusCode());
}));
实现。
- 修改
Request
ServerHttpRequest.Builder builder = exchange.getRequest().mutate()
.header(Constants.HEADER_REQUEST_URI, exchange.getRequest().getURI().getPath());
ServerWebExchange newExchange = exchange.mutate().request(builder.build()).build();
return chain.filter(newExchange);
- 修改
Response
JsonObject result = new JsonObject();
return Mono.defer(() -> {
setResponseStatus(exchange, HttpStatus.UNAUTHORIZED);
final ServerHttpResponse response = exchange.getResponse();
byte[] bytes = new byte[0];
try {
bytes = objectMapper.writeValueAsBytes(result);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
response.getHeaders().set("Content-Type", "application/json");
return response.writeWith(Flux.just(buffer));
});
网友评论