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

Ruby & Friends - Taking Go as an example

Ruby & Friends - Taking Go as an example

Presented at RubyConf TW 2014

Richard Lee

April 26, 2014
Tweet

More Decks by Richard Lee

Other Decks in Technology

Transcript

  1. ... In this talk, I'm going to present several ways

    to make such two-way communications between Ruby & Go language.
  2. Richard Lee • CTO @ Polydice, Inc • iCook.tw dev

    & ops • Open source lover • @dlackty everywhere
  3. Agenda 1. Why Go language? 2. Go with Ruby using

    asynchronous workers 3. Remote Procedure Code 4. Advanced tools
  4. Go Why choose another language when you have Ruby? 1.

    Static typing 2. Compiled language 3. Higher level concurrency abstraction (goroutines) 4. No object oriented design
  5. Use cases 1. Command line tools - Heroku's hk 2.

    System softwares - Docker 3. DevOps tools - ngrok / packer
  6. Heroku's CLI benchmark ## version $ time heroku version >/dev/null

    real 0m1.813s $ time hk version >/dev/null real 0m0.016s ## list $ time heroku apps >/dev/null real 0m3.830s $ time hk apps >/dev/null real 0m0.785s
  7. Async processing Use Redis or any message queue based processing.

    Resque / Sidekiq friends: • From Ruby to Go • go-workers • goworkers • go-sidekiq • From Go to Ruby • go-resque
  8. go-workers for Resque in action func myFunc(queue string, args ...interface{})

    error { fmt.Printf("From %s, %v", queue, args) return } func init() { goworker.Register("MyClass", myFunc) }
  9. Async processing (cont'd) • Pros: • Not fast enough but

    quite reliable • easy to scale out • Cons: • Async • Additional setup for queues
  10. Be careful about typing // Expecting (int, string) func myFunc(queue,

    args ...interface{}) error { id, ok := args[0].(int) if !ok { return errorInvalidParam } name, ok := args[1].(string) if !ok { return errorInvalidParam } doSomething(id, name) return nil }
  11. Compared to Ruby code class MyClass @queue = :myqueue def

    self.perform(i, str) doSomething(i, str) end end
  12. Performance boost • Benchmarked using matrix multiplication a = Matrix[...]

    b = Matrix[...] c = a * b puts a * b • 9x faster than Resque • 4x faster than Sidekiq
  13. Remote Procedure Calls Just like function invokation but remotely •

    Dynamically-typed • JSON-RPC • MsgPack-RPC • Statically format • Protobuf • Thrift
  14. Dynamically-typed Which means: 1. No need to predefine data format

    2. No generated codes for both client & server 3. Quite easy to migrate
  15. JSON-RPC Protocol Can be built on simple TCP connection or

    HTTP Request: {"method": "echo", "params": ["Hello JSON-RPC"], "id": 1} Response: {"result": "Hello JSON-RPC", "error": null, "id": 1}
  16. Client sock = TCPSocket.new "localhost", "5566" call = { method:"RPCMethods.Say",

    params:[{"text"=>"Hello, world!"}], id:rand(100) } sock.write JSON.dump call JSON.load sock.readline
  17. Server func (m *RPCMethods) Say(args Args, results *Results) error {

    results.Text = args.Text fmt.Println(results.Text) return nil // no error } func (m *RPCMethods) Ping(args Args, results *Results) error { results.Text = "Pong" fmt.Println(results.Text) return nil // no error }
  18. MsgPack 1. MsgPack is efficient binary serialization format 2. Quite

    similar to JSON but with binary type 3. Nice packages for most language
  19. Client code cli = MessagePack::RPC::Client.new("127.0.0.1", 5566) cli.timeout = 5 v

    = cli.call(:echo, "Ruby Conference Taiwan!") cli.close
  20. Statically-typed Which means: 1. Predefine format with special language (IDL)

    2. Usually with generated codes 3. Good when you have nice plan
  21. Protobuf 1. Widely used by Google 2. Built in with

    Golang 3. However, there's no official RPC mechanism
  22. Thrift 1. Open sourced by Facebook 2. Officially support a

    wide range of language 3. Have built in RPC mechanism
  23. Thrift IDL RpcService.thrift namespace go demo.rpc namespace ruby demo.rpc enum

    TweetType { TWEET, // 1 RETWEET // 2 } struct Tweet { 1: required i32 userId; 2: required string userName; 3: required string text; 4: optional Location loc; 5: optional TweetType tweetType = TweetType.TWEET }
  24. Thrift in aciton 1. Usually your first start from defining

    you service in IDL 2. Generate server / client code using thrift commands 3. Copy that to both side and integrate
  25. RPC v.s. HTTP / RESTful APIs • Persistent connection •

    Smaller in size • Easier to implement