using armeria to write your rpc

41
Using Armeria to write your RPC koji lin

Upload: koji-lin

Post on 09-Jan-2017

566 views

Category:

Technology


4 download

TRANSCRIPT

Page 1: Using armeria to write your RPC

Using Armeria to write your RPC

koji lin

Page 2: Using armeria to write your RPC

Armeria

● 非同步 RPC library

● LINE 的開放原始碼專案

○ Trustin Lee

● Java 8 

● HTTP/1・2 

● Thrift/gRPC 

● 尤其適合在 Microservices 架構

Page 3: Using armeria to write your RPC

Synchronous? Asynchrnous?

● 在同步下,如果一個處理需要等待,thread 必須等

待完成才能繼續執行

● 同步處理在大量存取下不易 scale up

○ Concurrent requests 受限於 max threads 

○ CPU 花費成本在 contention & context switch 

○ 較快或優先程度較高的存取會被較慢的存取拖累

Page 4: Using armeria to write your RPC

Armeria is Asynchronous

● 建立於 Netty 之上

● Max concurrent requests >>> max threads

● 較慢的存取不會阻礙到其他存取

● 程式庫內部也非同步化

○ DNS 查詢

○ Connection pool

● 0.20.x reactive stream 化

Page 5: Using armeria to write your RPC

Why HTTP/2 ?

● 一個連線上可以同時來往多個 request / response

● 不需要一個存取就建一個連線

from https://www.nginx.com/blog/7-tips-for-faster-http2-performance/

Page 6: Using armeria to write your RPC

Why HTTP/2 ? (cont'd)

● 解決了 HTTP/1 的許多問題

○ Binary header compression

○ 更少的連線

● 比較容易從 HTTP/1 轉換

● 可以利用各種現存的工具

○ cURL,瀏覽器,Wireshark

Page 7: Using armeria to write your RPC

Netty 夠穩定嗎?

● HTTP/1

○ Twitter

○ Apple

● HTTP/2

○ gRPC

○ LINE internal use

Page 8: Using armeria to write your RPC

Thrift● 跨平台跟語言的服務開發框架

○ 透過 compiler 自動生成程式,支援 C++, Java,

Python, Ruby, Perl, C#, Go, Javascript ...等等

○ 支援各種傳輸格式/協定

● 原本是 Facebook 開發,現為 Apache Thrift 開源

● 定義好 service method 就可以快速開發 RPC

client 和 server

○ .thrift 本身就是良好的文件

● 比 text-based 格式更有效率

Page 9: Using armeria to write your RPC

Thrift hello world on Armeria

● 撰寫 .thrift 定義 service method1. namespace java idv.koji.example.service2. service HelloService {3. string hello(1:string name)4. }

Page 10: Using armeria to write your RPC

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. }

Page 11: Using armeria to write your RPC

● 利用 Armeria 建立 Server1. 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)

Page 12: Using armeria to write your RPC

● 利用 Armeria 建立 Client1. 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)

Page 13: Using armeria to write your RPC

● 跟 Swagger 類似

1. ServerBuilder sb = new ServerBuilder();2. sb.serviceAt("/foo/", THttpService.of(...))3. .serviceAt("/bar/", THttpService.of(...))4. .serviceUnder("/docs/", new 5. DocService());

文件產生器

Page 14: Using armeria to write your RPC

和 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"));

Page 15: Using armeria to write your RPC

靜態頁面

1. ServerBuilder sb = new ServerBuilder(); 2. sb.serviceUnder("/images/", 3. HttpFileService.forFileSystem(4. "/var/lib/www/images"));

Page 16: Using armeria to write your RPC

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

Page 17: Using armeria to write your RPC

HTTP Client

1. HttpClient httpClient = Clients.newClient(2. "none+http://example.com/", 3. HttpClient.class);4. AggregatedHttpMessage textResponse = 5. httpClient6. .get("/foo/bar.txt") // Publisher7. .aggregate() // CompletableFuture8. .join();

Page 18: Using armeria to write your RPC

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

Page 19: Using armeria to write your RPC

Metrics

● Dropwizard Metrics

● 使用 DropwizardMetricCollectingService decorate1. builder.serviceAt(2. "/hello", 3. THttpService.of(new HelloHandler())4. .decorate( 5. DropwizardMetricCollectingService 6. .newDecorator(metricRegistry, 7. "hello-service")));

Page 20: Using armeria to write your RPC

Zipkin 整合

● Twitter 的開放源碼專案

● 分散式服務追蹤系統,追蹤跨網路存取的一連串

API 呼叫過程

● 在存取產生時放入一些資訊在 request 中,送到後

台可視化

Page 21: Using armeria to write your RPC

Zipkin 整合 (cont’d)

1. Brave brave = new2. 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(HttpTracingService11. .decorator(brave));

Page 22: Using armeria to write your RPC

Circuit Breaker

● 有多個遠端呼叫的系統最怕超時的服務所造成的連

鎖反應

● http://martinfowler.com/bliki/CircuitBreaker.html

http://developers.linecorp.com/blog/ja/?p=3684

Page 23: Using armeria to write your RPC

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

Page 24: Using armeria to write your RPC

Circuit Breaker (cont’d)

● Circuit Breaker 開啟時會丟出 FailFastException

● 可以針對 host, method 等級去做設定

○ newPerMethodDecorator

○ newPerHostDecorator

○ newPerHostAndMethodDecorator

Page 25: Using armeria to write your RPC

gRPC support

● https://github.com/line/armeria/pull/2471. 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();

Page 26: Using armeria to write your RPC

● 理應可以支援 HTTP/1,但現在沒有 HTTP/1 client

● 尚未支援文件產生器 DocService

● 尚未支援 json 格式

○ 類似 gRPC gateway

gRPC support (cont’d)

Page 27: Using armeria to write your RPC

Retrofit with armeria client

● https://github.com/line/armeria/pull/2971. 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);

Page 28: Using armeria to write your RPC

Armeria 之於應用程式開發者

● 良好的抽象設計

○ 一樣的方式模式建立 http/thrift client 和 server

● 方便的 decorator 模式

○ 預設已提供 logging, metrics, tracing, circuit

breaker…

○ 依需求可以用同模式實作各種功能 例如: ACL,

rate-limiting...等等

Page 29: Using armeria to write your RPC

Is Armeria production ready?

Page 30: Using armeria to write your RPC
Page 31: Using armeria to write your RPC

Shop architecture using armeria

Page 32: Using armeria to write your RPC

● 內部與外部都從 thrift socket client/server 實作切

換到 armeria

○ 內部都是 HTTP/2

○ 外部則 HTTP/2 & HTTP/1 都有

● 與 Spring MVC 共存

● Circuit breaker

● Metrics + Zipkin tracing

Page 33: Using armeria to write your RPC

# of backend requests

Page 34: Using armeria to write your RPC
Page 35: Using armeria to write your RPC
Page 36: Using armeria to write your RPC
Page 37: Using armeria to write your RPC
Page 38: Using armeria to write your RPC

但是...

● 非同步化不只是更換框架/程式庫就完成

○ 非同步化的程式不易撰寫跟維護

○ 我們使用 Dagger Producers 去實作非同步的相依

流程

● server/client 都使用 armeria,記得不要使用 client

的 future#get 之類的阻塞方法

○ event loop 下造成同 thread 等待跑在同個 thread

下的 task, 造成永遠阻塞

Page 39: Using armeria to write your RPC

但是... (cont’d)

● 非同步出錯時,exception 的 stack trace 資訊不足

Page 40: Using armeria to write your RPC

更多資訊

● http://line.github.io/armeria/

● https://github.com/line/armeria

● 歡迎直接到 issue 提出建議跟需求

Page 41: Using armeria to write your RPC

Q&A