- Building Microservices with Go
- Nic Jackson
- 534字
- 2021-07-15 17:28:06
JSON-RPC over HTTP
In this last example, we will look at the net/rpc/jsonrpc package that provides a built-in codec for serializing and deserializing to the JSON-RPC standard. We will also look at how we can send these responses over HTTP, whilst you may ask why not just use REST, and to some extent I will agree with you, it is an interesting example to be able to see how we can extend the standard framework.
The StartServer method contains nothing we have not seen before it is the standard rpc server setup, the main difference is line 42 where instead of starting the RPC server we are starting an http server and passing the listener to it along with a handler:
rpc_http_json/server/server.go
33 func StartServer() {
34 helloWorld := new(HelloWorldHandler)
35 rpc.Register(helloWorld)
36
37 l, err := net.Listen("tcp", fmt.Sprintf(":%v", port))
38 if err != nil {
39 log.Fatal(fmt.Sprintf("Unable to listen on given port: %s", err))
40 }
41
42 http.Serve(l, http.HandlerFunc(httpHandler))
43 }
The handler we are passing to the server is where the magic happens:
45 func httpHandler(w http.ResponseWriter, r *http.Request) {
46 serverCodec := jsonrpc.NewServerCodec(&HttpConn{in: r.Body, out: w})
47 err := rpc.ServeRequest(serverCodec)
48 if err != nil {
49 log.Printf("Error while serving JSON request: %v", err)
50 http.Error(w, "Error while serving JSON request, details have been logged.", 500)
51 return
52 }
53 }
In line 46, we are calling the jsonrpc.NewServerCodec function and passing to it a type that implements io.ReadWriteCloser. The NewServerCodec method returns a type that implements rpc.ClientCodec, which has the following methods:
type ClientCodec interface {
// WriteRequest must be safe for concurrent use by multiple goroutines.
WriteRequest(*Request, interface{}) error
ReadResponseHeader(*Response) error
ReadResponseBody(interface{}) error
Close() error
}
A ClientCodec type implements the writing of RPC request and reading RPC responses. To write a request to the connection a client calls the WriteRequest method. To read the response, the client must call ReadResponseHeader and ReadResponseBody as a pair. Once the body has been read, it is the client's responsibility to call the Close method to close the connection. If a nil interface is passed to ReadResponseBody then the body of the response should be read and then discarded:
17 type HttpConn struct {
18 in io.Reader
19 out io.Writer
20 }
21
22 func (c *HttpConn) Read(p []byte) (n int, err error) { return c.in.Read(p) }
23 func (c *HttpConn) Write(d []byte) (n int, err error) { return c.out.Write(d) }
24 func (c *HttpConn) Close() error { return nil }
The NewServerCodec method requires that we pass it a type that implements the ReadWriteCloser interface. As we do not have such a type passed to us as parameters in the httpHandler method we have defined our own type, HttpConn, which encapsulates the http.Request body, which implements io.Reader, and the ResponseWriter method, that implements io.Writer. We can then write our own methods that proxy the calls to the reader and writer creating a type that has the correct interface.
And that is it for our short intro to RPC with the standard libraries; we will see when we look at some frameworks more in depth in Chapter 3, Introducing Docker, how these can be used to build a production microservice.
- Learning Single:page Web Application Development
- 零基礎搭建量化投資系統:以Python為工具
- Visual Basic程序開發(學習筆記)
- INSTANT FreeMarker Starter
- 數據庫系統原理及MySQL應用教程
- 從程序員到架構師:大數據量、緩存、高并發、微服務、多團隊協同等核心場景實戰
- 樂高機器人設計技巧:EV3結構設計與編程指導
- Designing Hyper-V Solutions
- Mastering Unity Shaders and Effects
- Full-Stack React Projects
- Python算法從菜鳥到達人
- Learning Hunk
- Getting Started with Gulp
- Microsoft Dynamics AX 2012 R3 Financial Management
- C#開發案例精粹