国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - Java教程 - 淺談Spring Cloud zuul http請求轉發原理

淺談Spring Cloud zuul http請求轉發原理

2021-05-27 11:30David_jim Java教程

這篇文章主要介紹了淺談Spring Cloud zuul http請求轉發原理,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

spring cloud 網關,依賴于netflix 下的zuul 組件

zuul 的流程是,自定義 了zuulservletfilter和zuulservlet兩種方式,讓開發者可以去實現,并調用

先來看下zuulservletfilter的實現片段

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@override
 public void dofilter(servletrequest servletrequest, servletresponse servletresponse, filterchain filterchain) throws ioexception, servletexception {
   try {
     init((httpservletrequest) servletrequest, (httpservletresponse) servletresponse);
     try {
       prerouting();
     } catch (zuulexception e) {
       error(e);
       postrouting();
       return;
     }
     
     // only forward onto to the chain if a zuul response is not being sent
     if (!requestcontext.getcurrentcontext().sendzuulresponse()) {
       filterchain.dofilter(servletrequest, servletresponse);
       return;
     }
     
     try {
       routing();
     } catch (zuulexception e) {
       error(e);
       postrouting();
       return;
     }
     try {
       postrouting();
     } catch (zuulexception e) {
       error(e);
       return;
     }
   } catch (throwable e) {
     error(new zuulexception(e, 500, "uncaught_exception_from_filter_" + e.getclass().getname()));
   } finally {
     requestcontext.getcurrentcontext().unset();
   }
 }

從上面的代碼可以看到,比較關心的是prerouting、routing,postrouting三個方法 ,這三個方法會調用 注冊為zuulfilter的子類,首先來看下這三個方法

prerouting: 是路由前會做一些內容

routing():開始路由事項

postrouting:路由結束,不管是否有錯誤都會經過該方法

那這三個方法是怎么和zuulfilter聯系在一起的呢?

先來分析下 prerouting:

?
1
2
3
void postrouting() throws zuulexception {
   zuulrunner.postroute();
 }

同時 zuulrunner再來調用

?
1
2
3
public void postroute() throws zuulexception {
  filterprocessor.getinstance().postroute();
}

最終調用 filterprocessor runfilters

?
1
2
3
4
5
6
7
8
9
public void preroute() throws zuulexception {
  try {
    runfilters("pre");
  } catch (zuulexception e) {
    throw e;
  } catch (throwable e) {
    throw new zuulexception(e, 500, "uncaught_exception_in_pre_filter_" + e.getclass().getname());
  }
}

看到了runfilters 是通過 filtertype(pre ,route ,post )來過濾出已經注冊的 zuulfilter:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public object runfilters(string stype) throws throwable {
   if (requestcontext.getcurrentcontext().debugrouting()) {
     debug.addroutingdebug("invoking {" + stype + "} type filters");
   }
   boolean bresult = false;
   //通過stype獲取 zuulfilter的列表
   list<zuulfilter> list = filterloader.getinstance().getfiltersbytype(stype);
   if (list != null) {
     for (int i = 0; i < list.size(); i++) {
       zuulfilter zuulfilter = list.get(i);
       object result = processzuulfilter(zuulfilter);
       if (result != null && result instanceof boolean) {
         bresult |= ((boolean) result);
       }
     }
   }
   return bresult;
 }

再來看下 zuulfilter的定義

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public abstract class zuulfilter implements izuulfilter, comparable<zuulfilter> {
 
  private final dynamicbooleanproperty filterdisabled =
      dynamicpropertyfactory.getinstance().getbooleanproperty(disablepropertyname(), false);
 
  /**
   * to classify a filter by type. standard types in zuul are "pre" for pre-routing filtering,
   * "route" for routing to an origin, "post" for post-routing filters, "error" for error handling.
   * we also support a "static" type for static responses see staticresponsefilter.
   * any filtertype made be created or added and run by calling filterprocessor.runfilters(type)
   *
   * @return a string representing that type
   */
  abstract public string filtertype();
 
  /**
   * filterorder() must also be defined for a filter. filters may have the same filterorder if precedence is not
   * important for a filter. filterorders do not need to be sequential.
   *
   * @return the int order of a filter
   */
  abstract public int filterorder();
 
  /**
   * by default zuulfilters are static; they don't carry state. this may be overridden by overriding the isstaticfilter() property to false
   *
   * @return true by default
   */
  public boolean isstaticfilter() {
    return true;
  }

只列出了一部分字段,但可以看到filtertype和filterorder兩個字段,這兩個分別是指定filter是什么類型,排序

這兩個決定了實現的zuulfilter會在什么階段被執行,按什么順序執行

當選擇好已經注冊的zuulfilter后,會調用zuulfilter的runfilter

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public zuulfilterresult runfilter() {
   zuulfilterresult zr = new zuulfilterresult();
   if (!isfilterdisabled()) {
     if (shouldfilter()) {
       tracer t = tracerfactory.instance().startmicrotracer("zuul::" + this.getclass().getsimplename());
       try {
         object res = run();
         zr = new zuulfilterresult(res, executionstatus.success);
       } catch (throwable e) {
         t.setname("zuul::" + this.getclass().getsimplename() + " failed");
         zr = new zuulfilterresult(executionstatus.failed);
         zr.setexception(e);
       } finally {
         t.stopandlog();
       }
     } else {
       zr = new zuulfilterresult(executionstatus.skipped);
     }
   }
   return zr;
 }

其中run 是一個zuulfilter的一個抽象方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public interface izuulfilter {
  /**
   * a "true" return from this method means that the run() method should be invoked
   *
   * @return true if the run() method should be invoked. false will not invoke the run() method
   */
  boolean shouldfilter();
 
  /**
   * if shouldfilter() is true, this method will be invoked. this method is the core method of a zuulfilter
   *
   * @return some arbitrary artifact may be returned. current implementation ignores it.
   */
  object run();

所以,實現zuulfilter的子類要重寫 run方法,我們來看下 其中一個階段的實現 predecorationfilter 這個類是spring cloud封裝的在使用zuul 作為轉發的代碼服務器時進行封裝的對象,目的是為了決定當前的要轉發的請求是按serviceid,http請求,還是forward來作轉發

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
@override
  public object run() {
    requestcontext ctx = requestcontext.getcurrentcontext();
    final string requesturi = this.urlpathhelper.getpathwithinapplication(ctx.getrequest());
    route route = this.routelocator.getmatchingroute(requesturi);
    if (route != null) {
      string location = route.getlocation();
      if (location != null) {
        ctx.put("requesturi", route.getpath());
        ctx.put("proxy", route.getid());
        if (!route.iscustomsensitiveheaders()) {
          this.proxyrequesthelper
              .addignoredheaders(this.properties.getsensitiveheaders().toarray(new string[0]));
        }
        else {
          this.proxyrequesthelper.addignoredheaders(route.getsensitiveheaders().toarray(new string[0]));
        }
 
        if (route.getretryable() != null) {
          ctx.put("retryable", route.getretryable());
        }
        // 如果配置的轉發地址是http開頭,會設置 routehost
        if (location.startswith("http:") || location.startswith("https:")) {
          ctx.setroutehost(geturl(location));
          ctx.addoriginresponseheader("x-zuul-service", location);
        }
         // 如果配置的轉發地址forward,則會設置forward.to
        else if (location.startswith("forward:")) {
          ctx.set("forward.to",
              stringutils.cleanpath(location.substring("forward:".length()) + route.getpath()));
          ctx.setroutehost(null);
          return null;
        }
        else {
           // 否則以serviceid進行轉發
          // set serviceid for use in filters.route.ribbonrequest
          ctx.set("serviceid", location);
          ctx.setroutehost(null);
          ctx.addoriginresponseheader("x-zuul-serviceid", location);
        }
        if (this.properties.isaddproxyheaders()) {
          addproxyheaders(ctx, route);
          string xforwardedfor = ctx.getrequest().getheader("x-forwarded-for");
          string remoteaddr = ctx.getrequest().getremoteaddr();
          if (xforwardedfor == null) {
            xforwardedfor = remoteaddr;
          }
          else if (!xforwardedfor.contains(remoteaddr)) { // prevent duplicates
            xforwardedfor += ", " + remoteaddr;
          }
          ctx.addzuulrequestheader("x-forwarded-for", xforwardedfor);
        }
        if (this.properties.isaddhostheader()) {
          ctx.addzuulrequestheader("host", tohostheader(ctx.getrequest()));
        }
      }
    }
    else {
      log.warn("no route found for uri: " + requesturi);
 
      string fallbackuri = requesturi;
      string fallbackprefix = this.dispatcherservletpath; // default fallback
                                // servlet is
                                // dispatcherservlet
 
      if (requestutils.iszuulservletrequest()) {
        // remove the zuul servletpath from the requesturi
        log.debug("zuulservletpath=" + this.properties.getservletpath());
        fallbackuri = fallbackuri.replacefirst(this.properties.getservletpath(), "");
        log.debug("replaced zuul servlet path:" + fallbackuri);
      }
      else {
        // remove the dispatcherservlet servletpath from the requesturi
        log.debug("dispatcherservletpath=" + this.dispatcherservletpath);
        fallbackuri = fallbackuri.replacefirst(this.dispatcherservletpath, "");
        log.debug("replaced dispatcherservlet servlet path:" + fallbackuri);
      }
      if (!fallbackuri.startswith("/")) {
        fallbackuri = "/" + fallbackuri;
      }
      string forwarduri = fallbackprefix + fallbackuri;
      forwarduri = forwarduri.replaceall("//", "/");
      ctx.set("forward.to", forwarduri);
    }
    return null;
  }

這個前置處理,是為了后面決定以哪種zuulfilter來處理當前的請求 ,如 simplehostroutingfilter,這個的filtertype是post ,當 ``predecorationfilter設置了requestcontext中的 routehost,如 simplehostroutingfilter中的判斷

?
1
2
3
4
5
@override
public boolean shouldfilter() {
  return requestcontext.getcurrentcontext().getroutehost() != null
      && requestcontext.getcurrentcontext().sendzuulresponse();
}

在 simplehostroutingfilter中的run中,真正實現地址轉發的內容,其實質是調用 httpclient進行請求

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@override
  public object run() {
    requestcontext context = requestcontext.getcurrentcontext();
    httpservletrequest request = context.getrequest();
    multivaluemap<string, string> headers = this.helper
        .buildzuulrequestheaders(request);
    multivaluemap<string, string> params = this.helper
        .buildzuulrequestqueryparams(request);
    string verb = getverb(request);
    inputstream requestentity = getrequestbody(request);
    if (request.getcontentlength() < 0) {
      context.setchunkedrequestbody();
    }
 
    string uri = this.helper.buildzuulrequesturi(request);
    this.helper.addignoredheaders();
 
    try {
      httpresponse response = forward(this.httpclient, verb, uri, request, headers,
          params, requestentity);
      setresponse(response);
    }
    catch (exception ex) {
      context.set(error_status_code, httpservletresponse.sc_internal_server_error);
      context.set("error.exception", ex);
    }
    return null;
  }

最后如果是成功能,會調用 注冊 為post的zuulfilter ,目前有兩個 senderrorfilter 和 sendresponsefilter 這兩個了,一個是處理錯誤,一個是處理成功的結果

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://www.jianshu.com/p/295e51bc1518

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 国产资源在线视频 | 国产精品久久久久久久一区探花 | 欧美日韩精品一区二区 | 久久久久久久国产精品 | 久久久综合网 | 国产亚洲精品美女久久久久久久久久 | 日日操日日操 | 亚洲男人的天堂视频 | 国产精品久久久久国产a级 最新国产视频 | 在线一级片 | 精品国产91乱码一区二区三区 | 一区二区不卡 | 亚洲第一视频网站 | 中文字幕av网| 久久久久久久久99精品 | 国产一级片| 欧美亚洲视频在线观看 | 97久久久 | 久久av网站 | 日韩电影免费观看 | 国产精品第一区 | 中文字幕第二页 | 国产一级特黄 | 91国产精品 | 天天夜操 | a欧美| 黄色成人在线 | 欧美大片免费 | 欧美一区永久视频免费观看 | 国产精品精品 | 久久中文字幕一区二区三区 | 伊人91| 国产在线一区二区三区 | 欧洲一区二区三区 | 亚洲免费美女视频 | 日韩不卡一区 | 欧洲精品视频在线观看 | 999精品视频 | 午夜激情视频在线观看 | 亚洲国产精品网站 | 欧美日韩精品免费 |