SpringCloud之Gateway原理解析(二)--调用过程

本文参考了https://www.jianshu.com/p/9b813f6ca4c2 作者很牛啊

我们第一个关注的类就是DispatcherHandler,这个类提供的handle()方法,封装了我们之后所有的handlerMappings

这个DispatcherHandler有点想SpringMVC的DispatchServlet,里面也是封装了请求和对应的处理方法的关系

public class DispatcherHandler implements WebHandler, ApplicationContextAware {
    @Nullable
    private List<HandlerMapping> handlerMappings;
    @Nullable
    private List<HandlerAdapter> handlerAdapters;
    @Nullable
    private List<HandlerResultHandler> resultHandlers;

还记得上一节我们的Route最后封装到了Flux里,这时在处理请求的时候就会把这些route取出来

public Mono<Void> handle(ServerWebExchange exchange) {

  if (logger.isDebugEnabled()) {

   ServerHttpRequest request = exchange.getRequest();

   logger.debug("Processing " + request.getMethodValue() + " request for [" + request.getURI() + "]");

  }

  if (this.handlerMappings == null) {

   return Mono.error(HANDLER_NOT_FOUND_EXCEPTION);

  }

  return Flux.fromIterable(this.handlerMappings)

    .concatMap(mapping -> mapping.getHandler(exchange))

    .next()

    .switchIfEmpty(Mono.error(HANDLER_NOT_FOUND_EXCEPTION))

    .flatMap(handler -> invokeHandler(exchange, handler))

    .flatMap(result -> handleResult(exchange, result));

 }

之后就到了FilteringWebHandler类,他的handler方法封装了过滤器进去

public Mono<Void> handle(ServerWebExchange exchange) {

  //h获取到当前访问的路由对象

  Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);

  //获取当前已经存在的 过滤器 也就是配置的默认过滤器

  List<GatewayFilter> gatewayFilters = route.getFilters();

 //获取全局过滤器

  List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);

  combined.addAll(gatewayFilters);

  //按order排序

  AnnotationAwareOrderComparator.sort(combined);

  logger.debug("Sorted gatewayFilterFactories: "+ combined);

  return new DefaultGatewayFilterChain(combined).filter(exchange);

 }

  从这里开始就是调用各个handler的过程了,这其中有几个很重要的filter

  RouteToRequestUrlFilter

@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");\

  // http://localhost:8804/cydOrganization/getOrgTreeList

  URI uri = exchange.getRequest().getURI();

  boolean encoded = containsEncodedParts(uri);

  // lb://BASE-API-WEB

  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());

  }

  // lb://BASE-API-WEB:8804/cydOrganization/getOrgTreeList

  URI requestUrl = UriComponentsBuilder.fromUri(uri)

    .uri(routeUri)

    .build(encoded)

    .toUri();

  exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);

  return chain.filter(exchange);

 }

最后他将url拼装成了我们需要的,能够做服务发现的url,这时他就会进入LoadBalancerClientFilter 同样我标注url的变化

public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

  // lb://BASE-API-WEB:8804/cydOrganization/getOrgTreeList 刚才我们封装完毕的url

  URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);

  String schemePrefix = exchange.getAttribute(GATEWAY_SCHEME_PREFIX_ATTR);

  if (url == null || (!"lb".equals(url.getScheme()) && !"lb".equals(schemePrefix))) {

   return chain.filter(exchange);

  }

  //preserve the original url

  addOriginalRequestUrl(exchange, url);

  log.trace("LoadBalancerClientFilter url before: " + url);

  // RibbonServer{serviceId='BASE-API-WEB', server=192.168.47.1:12993, secure=false, metadata={}}

  final ServiceInstance instance = loadBalancer.choose(url.getHost());

  if (instance == null) {

   throw new NotFoundException("Unable to find instance for " + url.getHost());

  }

  // http://localhost:8804/cydOrganization/getOrgTreeList

  URI uri = exchange.getRequest().getURI();

  // if the `lb:<scheme>` mechanism was used, use `<scheme>` as the default,

  // if the loadbalancer doesn't provide one.

  String overrideScheme = null;

  if (schemePrefix != null) {

   overrideScheme = url.getScheme();

  }

  // http://192.168.47.1:12993/cydOrganization/getOrgTreeList 到这时 这个地址已经是正确的访问地址了。

  URI requestUrl = loadBalancer.reconstructURI(new DelegatingServiceInstance(instance, overrideScheme), uri);

  log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);

  exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);

  return chain.filter(exchange);

 }

  最后进入NettyRoutingFilter 这个filter真正做请求的发送,他使用HttpClient进行请求的发送。

  

public class NettyRoutingFilter implements GlobalFilter, Ordered {

 private final HttpClient httpClient;

 private final ObjectProvider<List<HttpHeadersFilter>> headersFilters;

 public NettyRoutingFilter(HttpClient httpClient,

   ObjectProvider<List<HttpHeadersFilter>> headersFilters) {

  this.httpClient = httpClient;

  this.headersFilters = headersFilters;

 }

 @Override

 public int getOrder() {

  return Ordered.LOWEST_PRECEDENCE;

 }

 @Override

 public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { 

// http://192.168.47.1:12993/cydOrganization/getOrgTreeList 我们刚才处理好的url

  URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);

  String scheme = requestUrl.getScheme(); 

  //必须是 http 或者 https 和没有被路由

  if (isAlreadyRouted(exchange) || (!"http".equals(scheme) && !"https".equals(scheme))) {

   return chain.filter(exchange);

  }

 // 设置为已经路由,防止请求重复路由

  setAlreadyRouted(exchange);

  ServerHttpRequest request = exchange.getRequest();

  final HttpMethod method = HttpMethod.valueOf(request.getMethod().toString());

  final String url = requestUrl.toString();

  HttpHeaders filtered = filterRequest(this.headersFilters.getIfAvailable(),

    exchange);

  final DefaultHttpHeaders httpHeaders = new DefaultHttpHeaders();

  filtered.forEach(httpHeaders::set);

  String transferEncoding = request.getHeaders().getFirst(HttpHeaders.TRANSFER_ENCODING);

  boolean chunkedTransfer = "chunked".equalsIgnoreCase(transferEncoding);

  boolean preserveHost = exchange.getAttributeOrDefault(PRESERVE_HOST_HEADER_ATTRIBUTE, false);

 //到这里发送http请求

  return this.httpClient.request(method, url, req -> {

   final HttpClientRequest proxyRequest = req.options(NettyPipeline.SendOptions::flushOnEach)

     .headers(httpHeaders)

     .chunkedTransfer(chunkedTransfer)

     .failOnServerError(false)

     .failOnClientError(false);

   if (preserveHost) {

    String host = request.getHeaders().getFirst(HttpHeaders.HOST);

    proxyRequest.header(HttpHeaders.HOST, host);

   }

   return proxyRequest.sendHeaders() //I shouldn't need this

     .send(request.getBody().map(dataBuffer ->

       ((NettyDataBuffer)dataBuffer).getNativeBuffer()));

  }).doOnNext(res -> { //接受请求返回结果

   ServerHttpResponse response = exchange.getResponse();

   // put headers and status so filters can modify the response

   HttpHeaders headers = new HttpHeaders();

   res.responseHeaders().forEach(entry -> headers.add(entry.getKey(), entry.getValue()));

// 这里可能导致空指针  是我用的版本的bug  SR2版本已经解决 

   exchange.getAttributes().put("original_response_content_type", headers.getContentType());

   HttpHeaders filteredResponseHeaders = HttpHeadersFilter.filter(

     this.headersFilters.getIfAvailable(), headers, exchange, Type.RESPONSE);

   response.getHeaders().putAll(filteredResponseHeaders);

   HttpStatus status = HttpStatus.resolve(res.status().code());

   if (status != null) {

    response.setStatusCode(status);

   } else if (response instanceof AbstractServerHttpResponse) {

    // https://jira.spring.io/browse/SPR-16748

    ((AbstractServerHttpResponse) response).setStatusCodeValue(res.status().code());

   } else {

    throw new IllegalStateException("Unable to set status code on response: " +res.status().code()+", "+response.getClass());

   }

   // Defer committing the response until all route filters have run

   // Put client response as ServerWebExchange attribute and write response later NettyWriteResponseFilter

   exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res);

  }).then(chain.filter(exchange));

 }

}

 

posted on 2021-02-22 15:02  MaXianZhe  阅读(501)  评论(0编辑  收藏  举报

导航