[关闭]
@ironzhang 2015-12-27T03:15:01.000000Z 字数 3749 阅读 280

gorpc-应用篇

gorpc系列


最近读了go语言net/rpc包的源码,打算写一系列笔记,本文即为该系列的第一篇。

使用go语言的rpc包,我们需要关注三个部分:服务逻辑的实现、服务器的实现、客户端调用。

下面是一个服务逻辑的实现示例

  1. package service
  2. import (
  3. "fmt"
  4. "log"
  5. "math/rand"
  6. "time"
  7. )
  8. type Request struct {
  9. Query string
  10. }
  11. type Result struct {
  12. Title string
  13. }
  14. type Service struct {
  15. svr string
  16. }
  17. func New(svr string) *Service {
  18. return &Service{svr: svr}
  19. }
  20. func (s *Service) Query(req *Request, res *Result) error {
  21. d := randomDuration(500 * time.Millisecond)
  22. select {
  23. case <-time.After(d):
  24. res.Title = fmt.Sprintf("result for [%s] from %s", req.Query, s.svr)
  25. }
  26. log.Printf(res.Title)
  27. return nil
  28. }
  29. func randomDuration(d time.Duration) time.Duration {
  30. return time.Duration(rand.Int()) % d
  31. }

go的标准库支持三类RPC:TCP、HTTP、JSONRPC,其中TCP和HTTP的RPC实现都采用Gob来编码,区别在于一者以TPC作为底层传输协议,一者以HTTP为底层传输协议,而JSONRPC则采用JSON编码。

下面的示例中分别就这三种RPC的使用给出了示例。

服务端

  1. package main
  2. import (
  3. "flag"
  4. "log"
  5. "net"
  6. "net/http"
  7. "net/rpc"
  8. "net/rpc/jsonrpc"
  9. "time"
  10. "example/rpc/service"
  11. )
  12. var rpcAddr = flag.String("rpc-addr", "0.0.0.0:7200", "server address")
  13. var httprpcAddr = flag.String("http-rpc-addr", "0.0.0.0:7201", "server address")
  14. var jsonrpcAddr = flag.String("json-rpc-addr", "0.0.0.0:7202", "server address")
  15. func main() {
  16. flag.Parse()
  17. serveRPC(*rpcAddr)
  18. serveHTTPRPC(*httprpcAddr)
  19. serveJSONRPC(*jsonrpcAddr)
  20. for {
  21. time.Sleep(time.Minute)
  22. }
  23. }
  24. func serveRPC(addr string) error {
  25. l, err := net.Listen("tcp", addr)
  26. if err != nil {
  27. log.Fatalf("failed to listen on %s, %v", addr, err)
  28. return err
  29. }
  30. s := rpc.NewServer()
  31. if err = s.Register(service.New("rpc_backend")); err != nil {
  32. log.Fatalf("failed to register rpc service, %v", err)
  33. return err
  34. }
  35. log.Printf("serve rpc on %s", addr)
  36. go s.Accept(l)
  37. return nil
  38. }
  39. func serveHTTPRPC(addr string) error {
  40. l, err := net.Listen("tcp", addr)
  41. if err != nil {
  42. log.Fatalf("failed to listen on %s, %v", addr, err)
  43. return err
  44. }
  45. s := rpc.NewServer()
  46. if err = s.Register(service.New("httprpc_backend")); err != nil {
  47. log.Fatalf("failed to register rpc service, %v", err)
  48. return err
  49. }
  50. s.HandleHTTP(rpc.DefaultRPCPath, rpc.DefaultDebugPath)
  51. log.Printf("serve http rpc on %s", addr)
  52. go http.Serve(l, nil)
  53. return nil
  54. }
  55. func serveJSONRPC(addr string) error {
  56. l, err := net.Listen("tcp", addr)
  57. if err != nil {
  58. log.Fatalf("failed to listen on %s, %v", addr, err)
  59. return err
  60. }
  61. s := rpc.NewServer()
  62. if err = s.Register(service.New("jsonrpc_backend")); err != nil {
  63. log.Fatalf("failed to register rpc service, %v", err)
  64. return err
  65. }
  66. log.Printf("serve json rpc on %s", addr)
  67. go jsonServe(s, l)
  68. return nil
  69. }
  70. func jsonServe(s *rpc.Server, l net.Listener) {
  71. for {
  72. conn, err := l.Accept()
  73. if err != nil {
  74. log.Fatal("json serve: accept:", err.Error())
  75. }
  76. go s.ServeCodec(jsonrpc.NewServerCodec(conn))
  77. }
  78. }

客户端

  1. package main
  2. import (
  3. "flag"
  4. "log"
  5. "net/rpc"
  6. "net/rpc/jsonrpc"
  7. "example/rpc/service"
  8. )
  9. var rpcAddr = flag.String("rpc-addr", "0.0.0.0:7200", "server address")
  10. var httprpcAddr = flag.String("http-rpc-addr", "0.0.0.0:7201", "server address")
  11. var jsonrpcAddr = flag.String("json-rpc-addr", "0.0.0.0:7202", "server address")
  12. func main() {
  13. flag.Parse()
  14. callRPC(*rpcAddr)
  15. callHTTPRPC(*httprpcAddr)
  16. callJSONRPC(*jsonrpcAddr)
  17. }
  18. func callRPC(addr string) {
  19. client, err := rpc.Dial("tcp", addr)
  20. if err != nil {
  21. log.Fatalf("rpc dial error, %v", err)
  22. }
  23. defer client.Close()
  24. request := service.Request{Query: "ping www.google.com"}
  25. result := service.Result{}
  26. if err = client.Call("Service.Query", &request, &result); err != nil {
  27. log.Fatalf("failed to call Server.Search, %v", err)
  28. }
  29. log.Printf(result.Title)
  30. }
  31. func callHTTPRPC(addr string) {
  32. client, err := rpc.DialHTTP("tcp", addr)
  33. if err != nil {
  34. log.Fatalf("rpc dial http error, %v", err)
  35. }
  36. defer client.Close()
  37. request := service.Request{Query: "ping www.google.com"}
  38. result := service.Result{}
  39. if err = client.Call("Service.Query", &request, &result); err != nil {
  40. log.Fatalf("failed to call Server.Search, %v", err)
  41. }
  42. log.Printf(result.Title)
  43. }
  44. func callJSONRPC(addr string) {
  45. client, err := jsonrpc.Dial("tcp", addr)
  46. if err != nil {
  47. log.Fatalf("rpc dial http error, %v", err)
  48. }
  49. defer client.Close()
  50. request := service.Request{Query: "ping www.google.com"}
  51. result := service.Result{}
  52. if err = client.Call("Service.Query", &request, &result); err != nil {
  53. log.Fatalf("failed to call Server.Search, %v", err)
  54. }
  55. log.Printf(result.Title)
  56. }

应用篇就这样,下一篇是源码剖析-客户端篇

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注