@@ -36,8 +36,11 @@ func init() {
36
36
RegistChannel ("http" , newHttpChannel )
37
37
}
38
38
39
+ // hstate is a pipe for readloop goroutine to communicate with request goroutine
39
40
type hstate struct {
41
+ // request goroutine will read data from it
40
42
reader net.Conn
43
+ // readloop goroutine will write data to it
41
44
writer net.Conn
42
45
}
43
46
@@ -60,20 +63,30 @@ type httpChannel struct {
60
63
pool * connPool
61
64
}
62
65
63
- // newHttpChannel is create rpc.Channel by ChannelConfig
66
+ // newHttpChannel is used to create rpc.Channel according to ChannelConfig
64
67
func newHttpChannel (config ChannelConfig ) (rpc.Channel , error ) {
65
68
hc := & httpChannel {}
66
69
hc .pool = newConnPool (
67
70
config .Size ,
71
+ // dialFunc
68
72
func () (net.Conn , error ) {
69
73
local , remote := net .Pipe ()
70
74
localTcpConn := & fakeTcpConn {c : local }
71
75
remoteTcpConn := & fakeTcpConn {c : remote }
72
76
if err := acceptFunc (remoteTcpConn , config .Listener ); err != nil {
73
77
return nil , err
74
78
}
79
+ // the goroutine model is:
80
+ // request goroutine ---> localTcpConn ---> mosn
81
+ // ^ |
82
+ // | |
83
+ // | |
84
+ // hstate <-- readloop goroutine <------
75
85
return localTcpConn , nil
76
- }, func () interface {} {
86
+ },
87
+ // stateFunc
88
+ func () interface {} {
89
+ // hstate is a pipe for readloop goroutine to communicate with request goroutine
77
90
s := & hstate {}
78
91
s .reader , s .writer = net .Pipe ()
79
92
return s
@@ -84,25 +97,29 @@ func newHttpChannel(config ChannelConfig) (rpc.Channel, error) {
84
97
return hc , nil
85
98
}
86
99
87
- // Do is handle RPCRequest to RPCResponse
100
+ // Do is used to handle RPCRequest and return RPCResponse
88
101
func (h * httpChannel ) Do (req * rpc.RPCRequest ) (* rpc.RPCResponse , error ) {
102
+ // 1. context.WithTimeout
89
103
timeout := time .Duration (req .Timeout ) * time .Millisecond
90
104
ctx , cancel := context .WithTimeout (req .Ctx , timeout )
91
105
defer cancel ()
92
106
107
+ // 2. get a fake connection with mosn
108
+ // The pool will start a readloop gorountine,
109
+ // which aims to read data from mosn and then write data to the hstate.writer
93
110
conn , err := h .pool .Get (ctx )
94
111
if err != nil {
95
112
return nil , err
96
113
}
97
-
114
+ // 3. set deadline before write data to this connection
98
115
hstate := conn .state .(* hstate )
99
116
deadline , _ := ctx .Deadline ()
100
117
if err = conn .SetWriteDeadline (deadline ); err != nil {
101
118
hstate .close ()
102
119
h .pool .Put (conn , true )
103
120
return nil , common .Error (common .UnavailebleCode , err .Error ())
104
121
}
105
-
122
+ // 4. write data to this fake connection
106
123
httpReq := h .constructReq (req )
107
124
defer fasthttp .ReleaseRequest (httpReq )
108
125
@@ -112,6 +129,7 @@ func (h *httpChannel) Do(req *rpc.RPCRequest) (*rpc.RPCResponse, error) {
112
129
return nil , common .Error (common .UnavailebleCode , err .Error ())
113
130
}
114
131
132
+ // 5. read response data and parse it into fasthttp.Response
115
133
httpResp := & fasthttp.Response {}
116
134
hstate .reader .SetReadDeadline (deadline )
117
135
@@ -121,6 +139,8 @@ func (h *httpChannel) Do(req *rpc.RPCRequest) (*rpc.RPCResponse, error) {
121
139
return nil , common .Error (common .UnavailebleCode , err .Error ())
122
140
}
123
141
h .pool .Put (conn , false )
142
+
143
+ // 6. convert result to rpc.RPCResponse,which is the response of rpc invoker
124
144
body := httpResp .Body ()
125
145
if httpResp .StatusCode () != http .StatusOK {
126
146
return nil , common .Errorf (common .UnavailebleCode , "http response code %d, body: %s" , httpResp .StatusCode (), string (body ))
0 commit comments