乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      微服務框架Finagle介紹 Part1: Future, Service, Filter

       WindySky 2017-07-17

      原文地址:http:///blog/2016/03/19/finagle1/

      微服務架構可能是時下最熱的一種架構模式了. 這篇系列里, 我想介紹一些常用的微服務框架. 通過學習這些框架, 我們將會了解實現微服務的過程中會遇到哪些問題, 以及這些微服務框架是如何幫助我們解決這些問題的. 所以這是一篇關于微服務實踐的系列, 我不會討論太多概念性的東西. 系列末尾我會給出一些微服務架構相關的鏈接, 感興趣的可以參考.

      微服務不同于單一架構應用, 是典型的分布式場景, 各服務之間通過IPC進行通信. 實現微服務的過程中, 我們需要解決以下問題:
      1. 服務注冊和服務發(fā)現.
      2. 根據應用選擇合適的通信協(xié)議和數據協(xié)議. 例如可以選用thrift, protocol buffer或REST.
      3. 服務負載均衡. 一個服務一般會部署多個實例. 如果使壓力均勻分布是需要考慮的問題.
      4. 服務路由與限流.
      5. 容錯處理. 相對于單機應用, 分布式環(huán)境下錯誤發(fā)生的概率會大大提高, 服務宕機, 網絡不可用的情況時常發(fā)生.
      6. 服務監(jiān)控. 各服務實例的性能指標, 例如請求響應時間, 請求并發(fā)數量, 以及服務實例的部署數量等.
      7. 事務一致性. 一般來說這個問題需要我們結合業(yè)務自己處理, 框架不會給我們太多幫助.

      好的微服務框架應該能幫助我們解決上面的全部或者大部分問題. 這里我選擇JVM上比較熱門的三個微服務框架: Finagle, spring Cloud(NetflixOSS), Dubbox. 我會從實例入手, 介紹這些框架的使用方式, 特點和適用場景.

      首先來看Finagle. Finagle是Twitter在2011年開源的一款RPC框架, 在國外使用較多, 例如Pinterest, Nest, Tumblr, 感興趣的可以Google. Finagle有著較為豐富的生態(tài)圈, 例如可以使用Finch很方便的實現REST, 使用Finagle OAuth2實現OAuth認證, 使用zipkin實現服務監(jiān)控. Finagle使用Scala開發(fā), 官方宣稱同時支持scalaJava語言.

      學習Finagle的使用之前, 首先要了解Finagle中的三個核心概念: Future, Service, Filter.

      1. Future

      Finagle使用的Future是com.twitter.util.Future. 由于Future非常實用, 從Scala2.10開始被加入到官方庫scala.concureent.Future. Java8中也引入了一個類似的接口java.util.concurrent.CompletableFuture. Future是對異步操作的抽象, 你可以將Future理解為一個容器, 這個容器包含一個異步操作. 一個Future容器可能處于三個狀態(tài)中的一種: 異步操作還沒有完成, 操作已經完成了并包含了成功結果, 操作失敗并包含了異常結果. Future一種很常用的用法是可以注冊成功或失敗的回調函數, 例如下面的Java代碼:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      
      responseFuture.onSuccess(func(response -> {
          System.out.println(String.format("response status: %s, response string: %s",
                  response.status().toString(), response.contentString()));
          return BoxedUnit.UNIT;
      }));
      responseFuture.onFailure(func(e -> {
          System.out.println("error: " + e.toString());
          return BoxedUnit.UNIT;
      }));
      

      我在responseFuture上注冊了一個成功的回調函數和失敗的回調函數, 當Future對應的操作完成時, 會簡單的打印出結果或異常信息. Future另外一個十分強大的用法是組合.例如下面的Java代碼:

      1
      2
      3
      4
      5
      
      Future<User> authenticatedUser = User.authenticate(email, password)
       
      Future<Seq<Tweet>> lookupTweets = authenticatedUser.flatMap(user -> Tweet.findAllByUser(user))
      
      //#1
      

      這段代碼首先根據email和password獲取user對象, 然后獲取user對應的所有微博. 我解釋下這段代碼的執(zhí)行邏輯. 首先調用User.authenticate(email, password)方法進行用戶認證, 返回的對象是Future, 代表這是一個異步操作. 注意我們拿到的是Future, 這個時候我們還沒有真正的拿到user對象. 接下來flatMap方法就派上用場了. 在上面代碼中, flatMap函數簽名應該是這樣的:

      1
      2
      3
      4
      5
      
      //Java8中并沒有這個函數, 這里只是用來解釋概念.
      //Java8中CompletableFuture的thenCompose方法類似于flatMap
      Future<Seq<Tweet>> flatMap(Function<User, Future<Seq<Tweet>>) {
        //...
      }
      

      簡單來說, flatMap的作用是將Future<A>轉換成Future<B>, 在這個例子里, 是將Future<User>轉換成Future<Seq<Tweet>>. 通過flatMap這種方式, 我們的代碼寫起來很像是同步執(zhí)行的, 但是實際上Future中的操作是由一個叫做Scheduler的組件去執(zhí)行的, 你可以將Scheduler理解為一個ExecutorService, 即我們的代碼是由其他線程異步執(zhí)行的. 上面的代碼中, 當代碼執(zhí)行到#1位置的時候, 其實認證用戶和獲取微博這兩個操作可能并沒有真正被執(zhí)行.

      Future與flatMap的概念都來源于函數式編程. 在Haskell中, flatMap叫做綁定(bind), 而Future可以近似看作Monad(單子). 對函數式編程中的Monad感興趣的朋友可以參考我之前的文章.

      Future還有其他一些很有用的方法, 例如從異常中恢復的rescue方法, 連接多個Future的join方法等, 這里就不展開了. Future在Finagle中無處不在, Finagle的設計哲理之一就是能異步的盡量異步, 大部分操作都不會阻塞. 例如下面我們要說的Service和Filter, 返回的結果都是Future. 如果你之前主要使用Spring或者Servlet這種技術, 可能剛學習Finagle的時候覺得有些難以理解. 這很正常, 在后面的文章我會詳細介紹如何使用Future編程, 你會發(fā)現其實這種異步編程習慣與之前相比沒有太大的不同.只是ThreadLocal在這種環(huán)境下失效了, 不過好在我們有替代品 :)

      2. Service

      Service是Finagle中的核心概念. Service可以被理解為接收一個Request參數, 返回一個Future對象的函數. 如果定義為Java的抽象類, 原型如下:

      1
      2
      3
      4
      5
      6
      
      //Service在Finagle中是用Scala代碼定義的, 這里只是用來解釋概念.
      public abstract class Service<Request, Response> {
      
          public abstract Future<Response> apply(Request r);
      
      }
      

      如果用Spring MVC類比, Finagle的Service就類似于Controller的方法, 可以用來處理客戶端的請求. 例如要在Finagle中實現一個Echo服務器, 代碼如下:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      
      public class Server extends Service<Request, Response> {
      
          @Override
          public Future<Response> apply(Request request) {
              Response response = Response.apply(Version.Http11$.MODULE$, Status.Ok());
              response.setContentString(request.getContentString());
              return Future.value(response);
          }
      
          public static void main(String[] args) throws Exception {
              Server service = new Server();
      
              ListeningServer server = Http.server().
                      withLabel("echo-server").
                      serve(new InetSocketAddress(8081), service);
      
              Await.result(server);
          }
      }
      

      注意Service的返回值是Future, 代表操作可以是異步完成的.

      3. Filter

      Finagle Filter類似于Servlet Filter, 可以對Service的請求和響應進行過濾. 不過Finagle Filter使用類型參數明確定義了 輸入輸出的參數類型, Finagle Filter如果定義為Java的抽象類, 原型如下:

      1
      2
      3
      4
      5
      6
      
      //Filter在Finagle中是用Scala代碼定義的, 這里只是用來解釋概念.
      public abstract class Filter<ReqIn, RepOut, ReqOut, RepIn> {
      
           public abstract Future<RepOut> apply(ReqIn request, Service<ReqOut, RepIn> service);
      
      }
      

      對于ReqIn, RepOut, ReqOut, RepIn這四個類型參數的定義, 可以參考下圖. 

      ReqIn和ReqOut分別是Filter的入參和出參, 而RepIn和RepOut則是Service的入參和出參. 我們來看看Filter在代碼中的實際用法:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      
      val baseService = new Service[HttpRequest, HttpResponse] {
        def apply(request: HttpRequest) =
          Future(new DefaultHttpResponse(HTTP_1_1, OK))
      }
       
      val authorize = new RequireAuthorization()
      val handleExceptions = new HandleExceptions(...)
       
      val decoratedService: Service[HttpRequest, HttpResponse] =
        handleExceptions andThen authorize andThen baseService
      

      我們定義了一個Service對象baseService, 兩個Filter對象authorize和handleExceptions. 通過filter的andThen方法, 我們能夠很簡單的將Filter和Service組裝到一起, 這有點類似于在web.xml中定義了一個Servlet, 以及兩個Filter來攔截針對Servlet的請求. 不過毫無疑問Finagle這種使用方式更加直觀, 并且不容易出錯.

      現在我們已經了解了Finagle的基本概念, 下一篇我將結合實例介紹如何使用Finagle進行開發(fā).


        本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發(fā)現有害或侵權內容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多