Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Using armeria to write your RPC

1,256 views

Published on

Using armeria to write your RPC

Published in: Technology

Using armeria to write your RPC

  1. 1. Using Armeria to write your RPC koji lin
  2. 2. Armeria ● 非同步 RPC library ● LINE 的開放原始碼專案 ○ Trustin Lee ● Java 8  ● HTTP/1・2  ● Thrift/gRPC  ● 尤其適合在 Microservices 架構
  3. 3. Synchronous? Asynchrnous? ● 在同步下,如果一個處理需要等待,thread 必須等 待完成才能繼續執行 ● 同步處理在大量存取下不易 scale up ○ Concurrent requests 受限於 max threads  ○ CPU 花費成本在 contention & context switch  ○ 較快或優先程度較高的存取會被較慢的存取拖累
  4. 4. Armeria is Asynchronous ● 建立於 Netty 之上 ● Max concurrent requests >>> max threads ● 較慢的存取不會阻礙到其他存取 ● 程式庫內部也非同步化 ○ DNS 查詢 ○ Connection pool ● 0.20.x reactive stream 化
  5. 5. Why HTTP/2 ? ● 一個連線上可以同時來往多個 request / response ● 不需要一個存取就建一個連線 from https://www.nginx.com/blog/7-tips-for-faster-http2-performance/
  6. 6. Why HTTP/2 ? (cont'd) ● 解決了 HTTP/1 的許多問題 ○ Binary header compression ○ 更少的連線 ● 比較容易從 HTTP/1 轉換 ● 可以利用各種現存的工具 ○ cURL,瀏覽器,Wireshark
  7. 7. Netty 夠穩定嗎? ● HTTP/1 ○ Twitter ○ Apple ● HTTP/2 ○ gRPC ○ LINE internal use
  8. 8. Thrift ● 跨平台跟語言的服務開發框架 ○ 透過 compiler 自動生成程式,支援 C++, Java, Python, Ruby, Perl, C#, Go, Javascript ...等等 ○ 支援各種傳輸格式/協定 ● 原本是 Facebook 開發,現為 Apache Thrift 開源 ● 定義好 service method 就可以快速開發 RPC client 和 server ○ .thrift 本身就是良好的文件 ● 比 text-based 格式更有效率
  9. 9. Thrift hello world on Armeria ● 撰寫 .thrift 定義 service method 1. namespace java idv.koji.example.service 2. service HelloService { 3. string hello(1:string name) 4. }
  10. 10. Thrift hello world on Armeria (cont’d) ● 使用 thrift compiler 產生好 client/server 溝通部分 ● 實作邏輯 1. public class Foo implements HelloService.AsyncIface { 2. public void hello(String name, AsyncMethodCallback cb) { 3. cb.onComplete(name + ", hello world!"); 4. } 5. }
  11. 11. ● 利用 Armeria 建立 Server 1. ServerBuilder sb = new ServerBuilder(); 2. sb.port(8080, SessionProtocol.HTTP); 3. sb.serviceAt( 4. "/hello", 5. ThriftService.of(fooHandler, 6. SerializationFormat.THRIFT_BINARY) 7. .decorate(LoggingService::new)); 8. sb.build().start(); Thrift hello world on Armeria (cont’d)
  12. 12. ● 利用 Armeria 建立 Client 1. HelloService.Iface helloService = 2. Clients.newClient( 3. "tbinary+http://127.0.0.1:8080/hello", 4. HelloService.AsyncIface.class); 5. 6. helloService.hello("Armeria", 7. new AsyncMethodCallback<String>() { 8. ... 9. }); Thrift hello world on Armeria (cont’d)
  13. 13. ● 跟 Swagger 類似 1. ServerBuilder sb = new ServerBuilder(); 2. sb.serviceAt("/foo/", THttpService.of(...)) 3. .serviceAt("/bar/", THttpService.of(...)) 4. .serviceUnder("/docs/", new 5. DocService()); 文件產生器
  14. 14. 和 legacy webapp 共存 ● 將 legacy 的程式透過 Tomcat Servlet Engine 執行 ● Tomcat 不需綁定 port,還可以透過 armeria 得到 HTTP/2 的好處 1. ServerBuilder sb = new ServerBuilder(); 2. sb.serviceUnder("/legacy/", 3. TomcatService.forFileSystem( 4. "/var/example.war"));
  15. 15. 靜態頁面 1. ServerBuilder sb = new ServerBuilder(); 2. sb.serviceUnder("/images/", 3. HttpFileService.forFileSystem( 4. "/var/lib/www/images"));
  16. 16. HTTP Server 1. ServerBuilder sb = new ServerBuilder(); 2. sb.port(8080, SessionProtocol.HTTP); 3. builder.serviceAt("/http", 4. new AbstractHttpService() { 5. @Override protected void 6. doPost(ServiceRequestContext ctx, 7. HttpRequest req, 8. HttpResponseWriter res)... { 9. res.respond(HttpStatus.OK, 10. MediaType.PLAIN_TEXT_UTF_8, 11. "test"); 12. } 13. }).build().start();
  17. 17. HTTP Client 1. HttpClient httpClient = Clients.newClient( 2. "none+http://example.com/", 3. HttpClient.class); 4. AggregatedHttpMessage textResponse = 5. httpClient 6. .get("/foo/bar.txt") // Publisher 7. .aggregate() // CompletableFuture 8. .join();
  18. 18. Client side load balancing ● Armeria 使用單一 HTTP/2 連線,所以在某些狀況 如 L4 下,需要自己的 LB 機制 1. EndpointGroupRegistry.register( 2. "myGroup", 3. new StaticEndpointGroup( 4. Endpoint.of("1.2.3.4", 8080), ...), 5. EndpointSelectionStrategy. 6. WEIGHTED_ROUND_ROBIN); 7. Clients.newClient( 8. "none+http://group:myGroup/foo/bar", 9. SimpleHttpClient.class);
  19. 19. Metrics ● Dropwizard Metrics ● 使用 DropwizardMetricCollectingService decorate 1. builder.serviceAt( 2. "/hello", 3. THttpService.of(new HelloHandler()) 4. .decorate( 5. DropwizardMetricCollectingService 6. .newDecorator(metricRegistry, 7. "hello-service")));
  20. 20. Zipkin 整合 ● Twitter 的開放源碼專案 ● 分散式服務追蹤系統,追蹤跨網路存取的一連串 API 呼叫過程 ● 在存取產生時放入一些資訊在 request 中,送到後 台可視化
  21. 21. Zipkin 整合 (cont’d) 1. Brave brave = new 2. Brave.Builder("HelloService") 3. .spanCollector( 4. new ScribeSpanCollector("127.0.0.1", 5. 9410)) 6. .traceSampler(Sampler.create(1f)) 7. .build(); 8. server.serviceAt("/hello", 9. ThriftService.of(new HelloService()) 10. .decorate(HttpTracingService 11. .decorator(brave));
  22. 22. Circuit Breaker ● 有多個遠端呼叫的系統最怕超時的服務所造成的連 鎖反應 ● http://martinfowler.com/bliki/CircuitBreaker.html http://developers.linecorp.com/blog/ja/?p=3684
  23. 23. Circuit Breaker (cont’d) 1. decorator = 2. CircuitBreakerClient.newDecorator( 3. new CircuitBreakerBuilder("hello") 4. .failureRateThreshold(0.1).build()); 5. 6. new ClientBuilder("tbinary+http://...") 7. .decorator(ThriftCall.class, 8. ThriftReply.class, 9. decorator) 10. .build(HelloService.Iface.class);
  24. 24. Circuit Breaker (cont’d) ● Circuit Breaker 開啟時會丟出 FailFastException ● 可以針對 host, method 等級去做設定 ○ newPerMethodDecorator ○ newPerHostDecorator ○ newPerHostAndMethodDecorator
  25. 25. gRPC support ● https://github.com/line/armeria/pull/247 1. ServerBuilder sb = new ServerBuilder(); 2. sb.port(8080, SessionProtocol.HTTP); 3. GrpcService grpcService = new 4. GrpcServiceBuilder() 5. .addService(new HiService()) 6. .build(); 7. sb.serviceUnder("/", grpcService); 8. sb.build().start();
  26. 26. ● 理應可以支援 HTTP/1,但現在沒有 HTTP/1 client ● 尚未支援文件產生器 DocService ● 尚未支援 json 格式 ○ 類似 gRPC gateway gRPC support (cont’d)
  27. 27. Retrofit with armeria client ● https://github.com/line/armeria/pull/297 1. HttpClient httpClient = 2. Clients.newClient(ClientFactory.DEFAULT, 3. "none+http://localhost:8080", 4. HttpClient.class); 5. Retrofit retrofit = 6. ArmeriaRetrofit.builder(httpClient) 7. .addConverterFactory(...) 8. .build(); 9. MyApi api = retrofit.create(MyApi.class);
  28. 28. Armeria 之於應用程式開發者 ● 良好的抽象設計 ○ 一樣的方式模式建立 http/thrift client 和 server ● 方便的 decorator 模式 ○ 預設已提供 logging, metrics, tracing, circuit breaker… ○ 依需求可以用同模式實作各種功能 例如: ACL, rate-limiting...等等
  29. 29. Is Armeria production ready?
  30. 30. Shop architecture using armeria
  31. 31. ● 內部與外部都從 thrift socket client/server 實作切 換到 armeria ○ 內部都是 HTTP/2 ○ 外部則 HTTP/2 & HTTP/1 都有 ● 與 Spring MVC 共存 ● Circuit breaker ● Metrics + Zipkin tracing
  32. 32. # of backend requests
  33. 33. 但是... ● 非同步化不只是更換框架/程式庫就完成 ○ 非同步化的程式不易撰寫跟維護 ○ 我們使用 Dagger Producers 去實作非同步的相依 流程 ● server/client 都使用 armeria,記得不要使用 client 的 future#get 之類的阻塞方法 ○ event loop 下造成同 thread 等待跑在同個 thread 下的 task, 造成永遠阻塞
  34. 34. 但是... (cont’d) ● 非同步出錯時,exception 的 stack trace 資訊不足
  35. 35. 更多資訊 ● http://line.github.io/armeria/ ● https://github.com/line/armeria ● 歡迎直接到 issue 提出建議跟需求
  36. 36. Q&A

×