Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Widebullet - Proxying RESTful APIs with JSON-RPC in Go

Widebullet - Proxying RESTful APIs with JSON-RPC in Go

5d74d743eabd2bf7d4d2f68b9d3c727d?s=128

Tatsuhiko Kubo

February 17, 2016
Tweet

Transcript

  1. Widebullet - Proxying RESTful APIs with JSON-RPC in Go Tatsuhiko

    Kubo@cubicdaiya Go 1.6 Release Party 2016/02/17
  2. @cubicdaiya / Tatsuhiko Kubo Principal Engineer, SRE @ Mercari, Inc.

    ngx_small_light, ngx_dynamic_upstream, nginx-build, slackboard,cachectl, gaurun, etc…
  3. nginxຊΛࣥච͠·ͨ͠ʢ2016/01/16ൃചʣ

  4. None
  5. https://www.mercari.com/ Mercari - Your Friendly Mobile Marketplace

  6. Agenda • Use cases Go @ • Widebullet - proxying

    RESTful APIs with JSON-RPC
  7. Use cases for Go @

  8. Use cases for Go @ • nginx-build - seamless nginx

    builder (github.com/cubicdaiya/nginx-build) • cachectl - page cache controller (github.com/cubicdaiya/cachectl) • Slackboard - proxying message to Slack (github.com/cubicdaiya/slackboard) • Gaurun - proxying push notification (github.com/mercari/gaurun) • fluent-agent-hydra - A Fluentd log agent (github.com/fujiwara/fuluent-agent-hydra)
  9. Use cases for Go @ • zabbix-cli - CLI tool

    for Zabbix • CLI tools and plugins for Mackerel • Widebullet - proxying multi API requests • etc… (e.g. internal CLIs and daemons…)
  10. Use cases for Go @ • zabbix-cli - CLI tool

    for Zabbix • CLI tools and plugins for Mackerel • Widebullet - proxying multi API requests • etc… (e.g. internal CLIs and daemons…)
  11. Widebullet - Proxying RESTful APIs with JSON-RPC in Go

  12. Overview of mercari API call - Before NFSDBSJ "1* Multimedia

    Corporate data center Traditional server Mobile Client Example: IAM Add-on Requester Workers HTTPS HTTP private network global network
  13. Overview of mercari API call - Now NFSDBSJ "1* Multimedia

    Corporate data center Traditional server Mobile Client Example: IAM Add-on Requester Workers HTTPS HTTP HTTP TVCTZT private network global network
  14. Overview of mercari API call - Now NFSDBSJ "1* Multimedia

    Corporate data center Traditional server Mobile Client Example: IAM Add-on Requester Workers HTTPS HTTP HTTP TVCTZT TVCTZT HTTP private network global network
  15. Overview of mercari API call - Now NFSDBSJ "1* Multimedia

    Corporate data center Traditional server Mobile Client Example: IAM Add-on Requester Workers HTTPS HTTP HTTP TVCTZT TVCTZT HTTP TVCTZT HTTP private network global network
  16. Overview of mercari API call - Now NFSDBSJ "1* Multimedia

    Corporate data center Traditional server Mobile Client Example: IAM Add-on Requester Workers HTTPS HTTP HTTP TVCTZT TVCTZT HTTP TVCTZT HTTP … private network global network
  17. Performance reduction due to API mismatch • mercari API is

    not always constructed optimally for every situation • some subsystem must call multiple APIs at once • Call APIs concurrently for high performance • BTW, some subsystem is powered by PHPʂ
  18. Call APIs concurrently in PHP • We tried with Guzzle

    ( internally curl_exec_multi) • succeed a bit optimization • But overhead is not negligible switched concurrent API call PHP wait API response consumed time graph
  19. Next step • Try to call multiple APIs with single

    request • Nice to have anyway • JSON-RPC is reasonable choice • But mercari API does not provides JSON-RPC • I tried to write the proxy server in Go • It’s the Widebullet.
  20. Widebullet • The proxy server between JSON-RPC and RESTful API

    server • Protocol • based JSON-RPC ( a little extended) • Configuration with TOML • Not published yetʂ
  21. Overview NFSDBSJ "1* TVCTZT JSON-RPC XJEFCVMMFU

  22. Start Widebullet $ wbt -c wbt.toml

  23. Configuration with TOML Port = "29300" LogLevel = "error" Timeout

    = 5 MaxIdleConnsPerHost = 100 DisableCompression = false [[Endpoints]] Name = "ep-1" Ep = “ep-1:30001" ProxySetHeaders = [ ["Host", "ep1.example.com"], ] [[Endpoints]] Name = "ep-2" Ep = “ep-2:30001" ProxySetHeaders = [ ["Host", "ep2.example.com"], ]
  24. JSON-RPC request example [ { “jsonrpc”: “2.0”, “ep”: “ep-1”, “method”:

    “/goods/get”, “params”: { “id”: 1234, “status”: “alive” } }, { “jsonrpc”: “2.0”, “ep”: “ep-2”, “method”: “/users/get”, “params”: { “id”: 5678 } } ]
  25. Convert to RESTful API requests GET http://ep-1/goods/get?id=1234&status=alive HTTP/1.1 GET http://ep-2/users/get?id=5678

    HTTP/1.1
  26. Sending HTTP requests concurrently // error handling is eliminated for

    simplicity func jsonRpc2Http(reqs *[]jsonrpc.Request) ([]jsonrpc.Response) { wg := new(sync.WaitGroup) resps := make([]jsonrpc.Response, len(reqs) for i, reqj := range *reqs { wg.Add(1) go func(i int, reqj jsonrpc.Request) { defer wg.Done() reqh := buildHttpRequest(&reqj) resp, _ := HttpClient.Do(reqh) defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) resps[i] = buildJsonRpcResponse(string(body), reqj.ID) }(i, reqj) } wg.Wait() return resps }
  27. Overview NFSDBSJ "1* TVCTZT JSON-RPC 8JEFCVMMFU REST [ { “jsonrpc”:

    “2.0”, “ep”: “ep-1”, “method”: “/goods/get”, “params”: { “id”: 1234, “status”: “alive” } }, { “jsonrpc”: “2.0”, “ep”: “ep-2”, “method”: “/users/get”, “params”: { “id”: 5678 } } ] GET http://ep-1/goods/get?id=1234&status=alive HTTP/1.1 GET http://ep-2/users/get?id=5678 HTTP/1.1
  28. Result PHP wait API response from widebullet consumed time graph

    introduced Widebullet
  29. We are hiring Go Engineer! https://www.mercari.com/jp/jobs/