@tenlee
2018-12-28T10:44:02.000000Z
字数 2732
阅读 2078
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-1spring.cloud.gateway.routes[0].uri=http://g.cnspring.cloud.gateway.routes[0].predicates[0]=Path=/demo/**spring.cloud.gateway.routes[0].filters[0]=StripPrefix=1spring.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,其源码如下:
@Overridepublic 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 schemeSpecificPartexchange.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);}
FilterFilter的迁移也比较简单,从原来的继承ZuulFilter改为实现接口
GlobalFilter或自定义Filter, Ordered.
RequestContext.getCurrentContext().set(...)通过exchange.getAttributes().put(...)实现RequestContext.getCurrentContext().getRouteHost()通过exchange.getAttribute(GATEWAY_ROUTE_ATTR)实现。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));});