1.rpc

1.1.服务端

  1. package main
  2. import (
  3. "net"
  4. "net/rpc"
  5. )
  6. type HelloService struct {}
  7. func (s *HelloService) Hello(request string,reply *string) error {
  8. *reply = "hello" + request
  9. return nil
  10. }
  11. func main() {
  12. _ := rpc.RegisterName("HelloService", &HelloService{})
  13. listener, err := net.Listen("tcp", ":8848")
  14. if err != nil {
  15. panic("监听端口失败")
  16. }
  17. conn, err := listener.Accept()
  18. if err != nil {
  19. panic("建立连接失败")
  20. }
  21. rpc.ServeConn(conn)
  22. }

其中Hello方法必须满足Go语言的RPC规则:方法只能有两个可序列化的参数,其中第二个参数是指针类型,并且返回一个error类型,同时必须是公开的方法
然后就可以将HelloService类型的对象注册为一个RPC服务:(TCP RPC服务)。
其中rpc.Register函数调用会将对象类型中所有满足RPC规则的对象方法注册为RPC函数,所有注册的方法会放在HelloService服务空间之下。然后我们建立一个唯一的TCP链接,并且通过rpc.ServeConn函数在该TCP链接上为对方提供RPC服务。

1.2.客户端

  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "net/rpc"
  6. )
  7. func main() {
  8. client, err := rpc.Dial("tcp", "localhost:8848")
  9. if err != nil {
  10. log.Fatalln("dialing:",err)
  11. }
  12. var reply string
  13. err = client.Call("HelloService.Hello", "world", &reply)
  14. if err != nil {
  15. log.Fatalln(err)
  16. }
  17. fmt.Println(reply)
  18. }

通过rpc.Dial拨号RPC服务,然后通过client.Call调用具体的RPC方法。在调用client.Call时,第一个参数是用点号链接的RPC服务名字和方法名字,第二和第三个参数分别我们定义RPC方法的两个参数

2.rpc支持json

  1. package main
  2. import (
  3. "net"
  4. "net/rpc"
  5. "net/rpc/jsonrpc"
  6. )
  7. type HelloService struct {}
  8. func (s *HelloService) Hello(request string,reply *string) error {
  9. *reply = "hello" + request
  10. return nil
  11. }
  12. func main() {
  13. rpc.RegisterName("HelloService",new(HelloService))
  14. listener, err := net.Listen("tcp", ":8090")
  15. if err != nil {
  16. panic("启动错误")
  17. }
  18. for {
  19. conn, err := listener.Accept()
  20. if err != nil {
  21. panic("接收")
  22. }
  23. go rpc.ServeCodec(jsonrpc.NewServerCodec(conn))
  24. }
  25. }

用rpc.ServeCodec函数替代了rpc.ServeConn函数,传入的参数是针对服务端的json编解码器。

  1. package main
  2. import (
  3. "fmt"
  4. "net"
  5. "net/rpc"
  6. "net/rpc/jsonrpc"
  7. )
  8. func main() {
  9. conn, err := net.Dial("tcp", ":1234")
  10. if err != nil {
  11. panic("连接错误")
  12. }
  13. client := rpc.NewClientWithCodec(jsonrpc.NewClientCodec(conn))
  14. var reply string
  15. err = client.Call("HelloService.Hello", "world", &reply)
  16. if err != nil {
  17. panic("调用错误")
  18. }
  19. fmt.Println(reply)
  20. }

3.基于http的rpc

  1. package main
  2. import (
  3. "io"
  4. "net/http"
  5. "net/rpc"
  6. "net/rpc/jsonrpc"
  7. )
  8. type HelloService struct {}
  9. func main() {
  10. rpc.RegisterName("HelloService",new(HelloService))
  11. http.HandleFunc("/jsonrpc", func(w http.ResponseWriter, r *http.Request) {
  12. var conn io.ReadWriteCloser = struct {
  13. io.Writer
  14. io.ReadCloser
  15. }{
  16. ReadCloser:r.Body,
  17. Writer:w,
  18. }
  19. rpc.ServeRequest(jsonrpc.NewServerCodec(conn))
  20. })
  21. http.ListenAndServe(":1234",nil)
  22. }