golang rpc的两种使用和测试是否可用

go的rpc可以使用http的方式,也可以使用tcp的,这里两种一起使用,如果服务挂了,我们可以通过http来测试服务是否正常。

server.go

package main
 
import (
        "net/rpc"
        "net/http"
        "log"
        "net"
        // "time"
)
 
 
type Args struct {
        A, B int
}
 
type Arith int
 
func (t *Arith) Multiply(args *Args, reply *([]string)) error {
        *reply = append(*reply, "test")
        return nil
}
 
func main() {
        newServer := rpc.NewServer()
        newServer.Register(new(Arith))
 
        l, e := net.Listen("tcp", "127.0.0.1:1234") // any available address
        if e != nil {
                log.Fatalf("net.Listen tcp :0: %v", e)
        }
 
        go newServer.Accept(l)
     newServer.HandleHTTP("/foo", "/bar")
        http.ListenAndServe(":8080",newServer)      
}

 

go newServer.Accept(l)的内部:go server.ServeConn(conn)func (server *Server) Accept(lis net.Listener) {

	for {
		conn, err := lis.Accept()
		if err != nil {
			log.Print("rpc.Serve: accept:", err.Error())
			return
		}
		go server.ServeConn(conn)
	}
}

 

因为rpc的Server类实现了ServHTTP方法,所以可以当作net handle来使用。并且限制了请求的http的method为connect,后面会使用curl来测试,两个相同的地方就是调用了server.ServeConn(conn)

代码如下:

func (server *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	if req.Method != "CONNECT" {
		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
		w.WriteHeader(http.StatusMethodNotAllowed)
		io.WriteString(w, "405 must CONNECT\n")
		return
	}
	conn, _, err := w.(http.Hijacker).Hijack()
	if err != nil {
		log.Print("rpc hijacking ", req.RemoteAddr, ": ", err.Error())
		return
	}
	io.WriteString(conn, "HTTP/1.0 "+connected+"\n\n")
	server.ServeConn(conn)
} 


client.go
package main

import(
         "net/rpc"
        "net/http"
        "log"
        "net"
        "fmt"
        // "io/ioutil"
)
type Args struct {
        A, B int
}
func main(){
        // 使用tcp的方式来调用rpc
        address, err := net.ResolveTCPAddr("tcp", "127.0.0.1:1234")
        if err != nil {
                panic(err)
        }
        conn, _ := net.DialTCP("tcp", nil, address)
        defer conn.Close()
 
        client := rpc.NewClient(conn)
        defer client.Close()
 
        args := &Args{7,8}
        reply := make([]string, 10)
        err = client.Call("Arith.Multiply", args, &reply)
        if err != nil {
                log.Fatal("arith error:", err)
        }
        log.Println("rpc:",reply)
        // 使用http的方式来调用rpc
        cli,err:=rpc.DialHTTP("tcp","localhost:8080/bar")
        if err!=nil{
                fmt.Println(err)
        }
        err = cli.Call("Arith.Multiply", args, &reply)
        if err != nil {
                log.Fatal("arith error:", err)
        }
        log.Println("http:",reply)
        //使用http request请求,看服务是否异常,rpc服务会通过response的status返回
        req,err:=http.NewRequest("CONNECT","http://127.0.0.1:8080/bar",nil)
        if err!=nil{
                fmt.Println(err)
        }
        httpclient := &http.Client{}
        rspo,err:=httpclient.Do(req)
        if err!=nil{
                fmt.Println(err)
        }
        var by []byte
        // by=make([]byte,1024)加上这句程序会阻塞
        fmt.Println("status:",rspo.Status)
        n,_:=rspo.Body.Read(by)
        fmt.Println("http:",string(by),"n:",n)   
        fmt.Println("end")
}

 

输出结果:两种调用rpc都输出了结果,使用http request只返回了response的status,body中是没有数据的。

2016/10/28 14:16:05 rpc: [test]
2016/10/28 14:16:05 http: [test]
status: 200 Connected to Go RPC
http:  n: 0
end

使用curl命令测试:

[baizhi@localhost ex]$ curl localhost:8080/bar
405 must CONNECT
[baizhi@localhost ex]$ curl -I -X CONNECT localhost:8080/bar
HTTP/1.0 200 Connected to Go RPC  

 

 

 

  

 

posted @ 2016-10-28 14:24  ZJJ2DSN  阅读(758)  评论(0编辑  收藏  举报