resources
https://pdos.csail.mit.edu/6.824/notes/crawler.go
https://pdos.csail.mit.edu/6.824/notes/l-rpc.txt
https://pdos.csail.mit.edu/6.824/notes/kv.go
RPC_concept
19 | 分布式通信之远程调用:我是你的千里眼(https://time.geekbang.org)
RPC_simple_example
http_RPC
package mainimport ("errors""fmt""net/http""net/rpc"
)type Args struct {A, B int
}type Quotient struct {Quo, Rem int
}type Arith intfunc (t *Arith) Multiply(args *Args, reply *int) error {*reply = args.A * args.Breturn nil
}func (t *Arith) Divide(args *Args, quo *Quotient) error {if args.B == 0 {return errors.New("divide by zero")}quo.Quo = args.A / args.Bquo.Rem = args.A % args.Breturn nil
}func main() {arith := new(Arith)rpc.Register(arith)rpc.HandleHTTP()err := http.ListenAndServe(":1234", nil)if err != nil {fmt.Println(err.Error())}
}
client
package mainimport ("fmt""log""net/rpc"
)type Args struct {A, B int
}type Quotient struct {Quo, Rem int
}func main() {serverAddress := "127.0.0.1"client, err := rpc.DialHTTP("tcp", serverAddress+":1234")if err != nil {log.Fatal("dialing:", err)}// Synchronous callargs := Args{17, 8}var reply interr = client.Call("Arith.Multiply", args, &reply)if err != nil {log.Fatal("arith error:", err)}fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply)var quot Quotienterr = client.Call("Arith.Divide", args, ")if err != nil {log.Fatal("arith error:", err)}fmt.Printf("Arith: %d/%d=%d remainder %d\n", args.A, args.B, quot.Quo, quot.Rem)
}
http_TCP
server
这个客户端代码和http的客户端代码对比,唯一的区别一个是DialHTTP,一个是Dial(tcp),其他处理一模一样。
package mainimport ("errors""fmt""net""net/rpc""os"
)type Args struct {A, B int
}type Quotient struct {Quo, Rem int
}type Arith intfunc (t *Arith) Multiply(args *Args, reply *int) error {*reply = args.A * args.Breturn nil
}func (t *Arith) Divide(args *Args, quo *Quotient) error {if args.B == 0 {return errors.New("divide by zero")}quo.Quo = args.A / args.Bquo.Rem = args.A % args.Breturn nil
}func main() {arith := new(Arith)rpc.Register(arith)tcpAddr, err := net.ResolveTCPAddr("tcp", ":1234")checkError(err)listener, err := net.ListenTCP("tcp", tcpAddr)checkError(err)for {conn, err := listener.Accept()if err != nil {continue}rpc.ServeConn(conn)}}func checkError(err error) {if err != nil {fmt.Println("Fatal error ", err.Error())os.Exit(1)}
}
client
package mainimport ("fmt""log""net/rpc"
)type Args struct {A, B int
}type Quotient struct {Quo, Rem int
}func main() {service := "127.0.0.1:1234"client, err := rpc.Dial("tcp", service)if err != nil {log.Fatal("dialing:", err)}// Synchronous callargs := Args{17, 8}var reply interr = client.Call("Arith.Multiply", args, &reply)if err != nil {log.Fatal("arith error:", err)}fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply)var quot Quotienterr = client.Call("Arith.Divide", args, ")if err != nil {log.Fatal("arith error:", err)}fmt.Printf("Arith: %d/%d=%d remainder %d\n", args.A, args.B, quot.Quo, quot.Rem)
}
crawler.go
crawler.go
感觉这个例子太晦涩。有点强行把几个原理在一个例子讲明