├── README.md ├── client ├── client.go ├── selector.go └── xclient.go ├── demo ├── client │ └── client.go └── server │ └── server.go ├── network ├── codec │ ├── bytebuf.go │ ├── bytebuf_util.go │ ├── header_codec.go │ ├── message_codec.go │ └── payload_codec.go ├── protocol │ └── message.go └── transport │ ├── net │ ├── net_client.go │ └── net_server.go │ ├── trans_client.go │ ├── trans_handler.go │ └── trans_server.go ├── registry ├── nacos_registry.go ├── registry.go └── zookeeper_registry.go └── server ├── handler.go ├── server.go └── service.go /README.md: -------------------------------------------------------------------------------- 1 | # xRPC-Go 2 | 3 | [xRPC](https://github.com/yj8023xx/xrpc) has been implemented in Go, providing a lightweight, high-throughput, low-latency RPC framework. 4 | 5 | 6 | 7 | ## Example 8 | 9 | **Client** 10 | 11 | ```go 12 | type Args struct { 13 | Name string 14 | } 15 | 16 | func main() { 17 | r, _ := registry.NewRegistry("zookeeper://127.0.0.1:2181") 18 | xClient := client.NewXClient("HelloService", r, client.RoundRobin, codec.Json) 19 | args := &Args{Name: "World"} 20 | var reply string 21 | err := xClient.Call("Hello", args, &reply) 22 | if err != nil { 23 | 24 | } 25 | fmt.Printf("reply: %s\n", reply) 26 | } 27 | ``` 28 | 29 | **Server** 30 | 31 | ```go 32 | type Args struct { 33 | Name string 34 | } 35 | 36 | type HelloService struct{} 37 | 38 | func (h *HelloService) Hello(args *Args, reply *string) error { 39 | *reply = "Hello " + args.Name 40 | return nil 41 | } 42 | 43 | func main() { 44 | s, _ := server.NewServer("8090", "zookeeper://127.0.0.1:2181") 45 | s.AddService("HelloService", new(HelloService)) 46 | s.Start() 47 | } 48 | ``` 49 | -------------------------------------------------------------------------------- /client/client.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "sync" 5 | "time" 6 | "xrpc/network/transport" 7 | _net "xrpc/network/transport/net" 8 | ) 9 | 10 | type Client interface { 11 | CreateTransport(uri string) (transport.Transport, error) 12 | Close() error 13 | } 14 | 15 | type client struct { 16 | mu sync.Mutex 17 | transportMap map[string]transport.Transport 18 | transClient transport.TransClient 19 | } 20 | 21 | func (c *client) Close() error { 22 | return c.transClient.Close() 23 | } 24 | 25 | func newClient() Client { 26 | return &client{ 27 | mu: sync.Mutex{}, 28 | transportMap: make(map[string]transport.Transport), 29 | transClient: _net.NewNetClient(), 30 | } 31 | } 32 | 33 | func (c *client) CreateTransport(uri string) (transport.Transport, error) { 34 | c.mu.Lock() 35 | defer c.mu.Unlock() 36 | if c.transportMap[uri] == nil { 37 | var err error 38 | c.transportMap[uri], err = c.transClient.CreateTransport(uri, time.Second) 39 | if err != nil { 40 | return nil, err 41 | } 42 | } 43 | return c.transportMap[uri], nil 44 | } 45 | 46 | var c = newClient() 47 | -------------------------------------------------------------------------------- /client/selector.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "github.com/bytedance/gopkg/lang/fastrand" 5 | "xrpc/network/transport" 6 | ) 7 | 8 | const ( 9 | Random = iota 10 | RoundRobin 11 | ) 12 | 13 | type Selector interface { 14 | Select() transport.Transport 15 | Update([]transport.Transport) 16 | } 17 | 18 | type RandomSelector struct { 19 | transports []transport.Transport 20 | } 21 | 22 | func (s *RandomSelector) Select() transport.Transport { 23 | if len(s.transports) == 0 { 24 | return nil 25 | } 26 | i := fastrand.Intn(len(s.transports)) 27 | return s.transports[i] 28 | } 29 | 30 | func (s *RandomSelector) Update(transports []transport.Transport) { 31 | s.transports = transports 32 | } 33 | 34 | func newRandomSelector(transports []transport.Transport) Selector { 35 | return &RandomSelector{ 36 | transports: transports, 37 | } 38 | } 39 | 40 | type RoundRobinSelector struct { 41 | transports []transport.Transport 42 | i int 43 | } 44 | 45 | func (s *RoundRobinSelector) Select() transport.Transport { 46 | if len(s.transports) == 0 { 47 | return nil 48 | } 49 | i := s.i 50 | i = i % len(s.transports) 51 | s.i = i + 1 52 | return s.transports[i] 53 | } 54 | 55 | func (s *RoundRobinSelector) Update(transports []transport.Transport) { 56 | s.transports = transports 57 | } 58 | 59 | func newRoundRobinSelector(transports []transport.Transport) Selector { 60 | return &RoundRobinSelector{ 61 | transports: transports, 62 | i: 0, 63 | } 64 | } 65 | 66 | type ConsistentHashSelector struct { 67 | } 68 | 69 | func newSelector(selectMode int, transports []transport.Transport) Selector { 70 | switch selectMode { 71 | case Random: 72 | return newRandomSelector(transports) 73 | case RoundRobin: 74 | return newRoundRobinSelector(transports) 75 | default: 76 | return newRandomSelector(transports) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /client/xclient.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | "net/url" 6 | "reflect" 7 | "strings" 8 | "xrpc/network/codec" 9 | "xrpc/network/protocol" 10 | "xrpc/network/transport" 11 | "xrpc/registry" 12 | ) 13 | 14 | type XClient interface { 15 | Go(methodName string, args, reply interface{}) *transport.Call 16 | Call(methodName string, args, reply interface{}) error 17 | } 18 | 19 | type xClient struct { 20 | serviceName string 21 | registry registry.Registry 22 | selector Selector 23 | payloadCodec codec.PayloadCodec 24 | } 25 | 26 | func firstLower(s string) string { 27 | if s == "" { 28 | return "" 29 | } 30 | return strings.ToLower(s[:1]) + s[1:] 31 | } 32 | 33 | func convertToMap(s interface{}) map[string]interface{} { 34 | t := reflect.TypeOf(s).Elem() 35 | v := reflect.ValueOf(s).Elem() 36 | m := make(map[string]interface{}) 37 | for i := 0; i < t.NumField(); i++ { 38 | field := t.Field(i) 39 | value := v.Field(i).Interface() 40 | m[firstLower(field.Name)] = value 41 | } 42 | return m 43 | } 44 | 45 | // Go invokes the function asynchronously. It returns the Call structure representing the invocation. 46 | // The done channel will signal when the call is complete by returning the same Call object. 47 | func (c *xClient) Go(methodName string, args, reply interface{}) *transport.Call { 48 | rpcRequest := protocol.RpcRequestPayload{ 49 | ServiceName: c.serviceName, 50 | MethodName: firstLower(methodName), 51 | ArgMap: convertToMap(args), 52 | } 53 | payload, _ := c.payloadCodec.Marshal(rpcRequest) 54 | uuid, _ := uuid.NewUUID() 55 | header := &protocol.Header{ 56 | MagicNumber: protocol.MagicNumber, 57 | Version: protocol.Version, 58 | HeaderLength: uint16(protocol.FixedHeaderLength), 59 | TotalLength: uint16(protocol.FixedHeaderLength + len(payload)), 60 | MessageTypeId: protocol.RpcRequest, 61 | SerializationId: uint8(codec.GetPayloadCodecId(c.payloadCodec.Name())), 62 | RequestId: uint64(uuid.ID()), 63 | } 64 | message := &protocol.Message{ 65 | Header: header, 66 | Payload: payload, 67 | } 68 | call, _ := c.selector.Select().Send(message, reply) 69 | return call 70 | } 71 | 72 | // Call invokes the named function, waits for it to complete, and returns its error status. 73 | func (c *xClient) Call(methodName string, args, reply interface{}) error { 74 | <-c.Go(methodName, args, reply).Done 75 | return nil 76 | } 77 | 78 | // watch changes of service and update transports. 79 | func (c *xClient) watch() { 80 | var transports []transport.Transport 81 | c.selector.Update(transports) 82 | } 83 | 84 | func NewXClient(serviceName string, registry registry.Registry, selectMode int, serializationMethod int) XClient { 85 | uris, err := registry.GetServiceAddress(serviceName) 86 | if err != nil { 87 | 88 | } 89 | var transports []transport.Transport 90 | for _, uri := range uris { 91 | u, _ := url.Parse(uri) 92 | transport, _ := c.CreateTransport(u.Host) 93 | transports = append(transports, transport) 94 | } 95 | return &xClient{ 96 | serviceName: serviceName, 97 | registry: registry, 98 | selector: newSelector(selectMode, transports), 99 | payloadCodec: codec.GetPayloadCodec(codec.GetPayloadCodecName(serializationMethod)), 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /demo/client/client.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "xrpc/client" 6 | "xrpc/network/codec" 7 | "xrpc/registry" 8 | ) 9 | 10 | type Args struct { 11 | Name string 12 | } 13 | 14 | func main() { 15 | r, _ := registry.NewRegistry("zookeeper://127.0.0.1:2181") 16 | xClient := client.NewXClient("com.smallc.xrpc.api.hello.HelloService", r, client.RoundRobin, codec.Json) 17 | args := &Args{Name: "World"} 18 | var reply string 19 | err := xClient.Call("Hello", args, &reply) 20 | if err != nil { 21 | 22 | } 23 | fmt.Printf("reply: %s\n", reply) 24 | } 25 | -------------------------------------------------------------------------------- /demo/server/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "xrpc/server" 5 | ) 6 | 7 | type Args struct { 8 | Name string 9 | } 10 | 11 | type HelloService struct{} 12 | 13 | func (h *HelloService) Hello(args *Args, reply *string) error { 14 | *reply = "Hello " + args.Name 15 | return nil 16 | } 17 | 18 | func main() { 19 | s, _ := server.NewServer("8090", "zookeeper://127.0.0.1:2181") 20 | s.AddService("com.smallc.xrpc.api.hello.HelloService", new(HelloService)) 21 | s.Start() 22 | } 23 | -------------------------------------------------------------------------------- /network/codec/bytebuf.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | "sync" 8 | ) 9 | 10 | // Mask bits. 11 | const ( 12 | BitReadable = 1 << iota 13 | BitWritable 14 | ) 15 | 16 | // ByteBuffer is the core abstraction of buffer. 17 | type ByteBuffer interface { 18 | io.ReadWriter 19 | 20 | // Next reads the next n bits sequentially and returns the original buffer. 21 | Next(n int) (p []byte, err error) 22 | 23 | // Peek returns the next n bits without advancing the reader. 24 | Peek(n int) (buf []byte, err error) 25 | 26 | // Skip is used to skip the next few bytes quickly. It's faster than Next and doesn't cause release. 27 | Skip(n int) (err error) 28 | 29 | // Release will free the buffer. After release, buffer read by Next/Skip/Peek is invalid. 30 | // Param e is used when the buffer release depend on error. 31 | // For example, usually the write buffer will be released inside flush, 32 | // but if flush error happen, write buffer may need to be released explicitly. 33 | Release(e error) (err error) 34 | 35 | // ReadableLen returns the total length of readable buffer. 36 | // Return: -1 means unreadable. 37 | ReadableLen() (n int) 38 | 39 | // ReadLen returns the size already read. 40 | ReadLen() (n int) 41 | 42 | // ReadString is a more efficient way to read string than Next. 43 | ReadString(n int) (s string, err error) 44 | 45 | // ReadBinary like ReadString. 46 | // Returns a copy of original buffer. 47 | ReadBinary(n int) (p []byte, err error) 48 | 49 | // Malloc n bytes sequentially in the writer buffer. 50 | Malloc(n int) (buf []byte, err error) 51 | 52 | // MallocLen returns the total length of the buffer malloced. 53 | MallocLen() (length int) 54 | 55 | // WriteString is a more efficient way to write string, using the unsafe method to convert the string to []byte. 56 | WriteString(s string) (n int, err error) 57 | 58 | // WriteBinary writes the []byte directly. Callers must guarantee that the []byte doesn't change. 59 | WriteBinary(b []byte) (n int, err error) 60 | 61 | // Flush writes any malloc data to the underlying io.Writer. 62 | // The malloced buffer must be set correctly. 63 | Flush() (err error) 64 | 65 | // NewBuffer returns a new writable remote.ByteBuffer. 66 | NewBuffer() ByteBuffer 67 | // AppendBuffer appends buf to the original buffer. 68 | AppendBuffer(buf ByteBuffer) (err error) 69 | 70 | // Bytes return the backing bytes slice of this buffer 71 | Bytes() (buf []byte, err error) 72 | } 73 | 74 | type defaultByteBuffer struct { 75 | buff []byte 76 | readIdx int 77 | writeIdx int 78 | status int 79 | } 80 | 81 | var byteBufPool sync.Pool 82 | 83 | func init() { 84 | byteBufPool.New = newDefaultByteBuffer 85 | } 86 | 87 | // NewWriterBuffer is used to create a defaultByteBuffer using the given size. 88 | func NewWriterBuffer(size int) ByteBuffer { 89 | return newWriterByteBuffer(size) 90 | } 91 | 92 | // NewReaderBuffer is used to create a defaultByteBuffer using the given buf. 93 | func NewReaderBuffer(buf []byte) ByteBuffer { 94 | return newReaderByteBuffer(buf) 95 | } 96 | 97 | // NewReaderWriterBuffer is used to create a defaultByteBuffer using the given size. 98 | func NewReaderWriterBuffer(size int) ByteBuffer { 99 | return newReaderWriterByteBuffer(size) 100 | } 101 | 102 | func newDefaultByteBuffer() interface{} { 103 | return &defaultByteBuffer{} 104 | } 105 | 106 | func newReaderByteBuffer(buf []byte) ByteBuffer { 107 | byteBuf := byteBufPool.Get().(*defaultByteBuffer) 108 | byteBuf.buff = buf 109 | byteBuf.readIdx = 0 110 | byteBuf.writeIdx = len(buf) 111 | byteBuf.status = BitReadable 112 | return byteBuf 113 | } 114 | 115 | func newWriterByteBuffer(estimatedLength int) ByteBuffer { 116 | if estimatedLength <= 0 { 117 | estimatedLength = 256 // default buffer size 118 | } 119 | byteBuf := byteBufPool.Get().(*defaultByteBuffer) 120 | byteBuf.buff = make([]byte, estimatedLength) 121 | byteBuf.status = BitWritable 122 | byteBuf.writeIdx = 0 123 | return byteBuf 124 | } 125 | 126 | func newReaderWriterByteBuffer(estimatedLength int) ByteBuffer { 127 | if estimatedLength <= 0 { 128 | estimatedLength = 256 // default buffer size 129 | } 130 | byteBuf := byteBufPool.Get().(*defaultByteBuffer) 131 | byteBuf.buff = make([]byte, estimatedLength) 132 | byteBuf.readIdx = 0 133 | byteBuf.writeIdx = 0 134 | byteBuf.status = BitReadable | BitWritable 135 | return byteBuf 136 | } 137 | 138 | // Next reads n bytes sequentially, returns the original address. 139 | func (b *defaultByteBuffer) Next(n int) (buf []byte, err error) { 140 | if b.status&BitReadable == 0 { 141 | return nil, errors.New("unreadable buffer, cannot support Next") 142 | } 143 | buf, err = b.Peek(n) 144 | b.readIdx += n 145 | return buf, err 146 | } 147 | 148 | // Peek returns the next n bytes without advancing the reader. 149 | func (b *defaultByteBuffer) Peek(n int) (buf []byte, err error) { 150 | if b.status&BitReadable == 0 { 151 | return nil, errors.New("unreadable buffer, cannot support Peek") 152 | } 153 | if err = b.readableCheck(n); err != nil { 154 | return nil, err 155 | } 156 | return b.buff[b.readIdx : b.readIdx+n], nil 157 | } 158 | 159 | // Skip is used to skip n bytes, it's much faster than Next. 160 | // Skip will not cause release. 161 | func (b *defaultByteBuffer) Skip(n int) (err error) { 162 | if b.status&BitReadable == 0 { 163 | return errors.New("unreadable buffer, cannot support Skip") 164 | } 165 | if err = b.readableCheck(n); err != nil { 166 | return err 167 | } 168 | b.readIdx += n 169 | return nil 170 | } 171 | 172 | // ReadableLen returns the total length of readable buffer. 173 | func (b *defaultByteBuffer) ReadableLen() (n int) { 174 | if b.status&BitReadable == 0 { 175 | return -1 176 | } 177 | return b.writeIdx - b.readIdx 178 | } 179 | 180 | // ReadLen returns the size already read. 181 | func (b *defaultByteBuffer) ReadLen() (n int) { 182 | return b.readIdx 183 | } 184 | 185 | // Read implement io.Reader 186 | func (b *defaultByteBuffer) Read(p []byte) (n int, err error) { 187 | if b.status&BitReadable == 0 { 188 | return -1, errors.New("unreadable buffer, cannot support Read") 189 | } 190 | pl := len(p) 191 | var buf []byte 192 | readable := b.ReadableLen() 193 | if readable == 0 { 194 | return 0, io.EOF 195 | } 196 | if pl <= readable { 197 | buf, err = b.Next(pl) 198 | if err != nil { 199 | return 200 | } 201 | n = pl 202 | } else { 203 | buf, err = b.Next(readable) 204 | if err != nil { 205 | return 206 | } 207 | n = readable 208 | } 209 | copy(p, buf) 210 | return 211 | } 212 | 213 | // ReadString is a more efficient way to read string than Next. 214 | func (b *defaultByteBuffer) ReadString(n int) (s string, err error) { 215 | if b.status&BitReadable == 0 { 216 | return "", errors.New("unreadable buffer, cannot support ReadString") 217 | } 218 | var buf []byte 219 | if buf, err = b.Next(n); err != nil { 220 | return "", err 221 | } 222 | return string(buf), nil 223 | } 224 | 225 | // ReadBinary like ReadString. 226 | // Returns a copy of original buffer. 227 | func (b *defaultByteBuffer) ReadBinary(n int) (p []byte, err error) { 228 | if b.status&BitReadable == 0 { 229 | return p, errors.New("unreadable buffer, cannot support ReadBinary") 230 | } 231 | var buf []byte 232 | if buf, err = b.Next(n); err != nil { 233 | return p, err 234 | } 235 | p = make([]byte, n) 236 | copy(p, buf) 237 | return p, nil 238 | } 239 | 240 | // Malloc n bytes sequentially in the writer buffer. 241 | func (b *defaultByteBuffer) Malloc(n int) (buf []byte, err error) { 242 | if b.status&BitWritable == 0 { 243 | return nil, errors.New("unwritable buffer, cannot support Malloc") 244 | } 245 | b.ensureWritable(n) 246 | currWIdx := b.writeIdx 247 | b.writeIdx += n 248 | return b.buff[currWIdx:b.writeIdx], nil 249 | } 250 | 251 | // MallocLen returns the total length of the buffer malloced. 252 | func (b *defaultByteBuffer) MallocLen() (length int) { 253 | if b.status&BitWritable == 0 { 254 | return -1 255 | } 256 | return b.writeIdx 257 | } 258 | 259 | // Write implement io.Writer 260 | func (b *defaultByteBuffer) Write(p []byte) (n int, err error) { 261 | if b.status&BitWritable == 0 { 262 | return -1, errors.New("unwritable buffer, cannot support Write") 263 | } 264 | return b.WriteBinary(p) 265 | } 266 | 267 | // WriteString is a more efficient way to write string, using the unsafe method to convert the string to []byte. 268 | func (b *defaultByteBuffer) WriteString(s string) (n int, err error) { 269 | if b.status&BitWritable == 0 { 270 | return -1, errors.New("unwritable buffer, cannot support WriteString") 271 | } 272 | n = len(s) 273 | b.ensureWritable(n) 274 | copy(b.buff[b.writeIdx:b.writeIdx+n], s) 275 | b.writeIdx += n 276 | return 277 | } 278 | 279 | // WriteBinary writes the []byte into buff. 280 | func (b *defaultByteBuffer) WriteBinary(p []byte) (n int, err error) { 281 | if b.status&BitWritable == 0 { 282 | return -1, errors.New("unwritable buffer, cannot support WriteBinary") 283 | } 284 | n = len(p) 285 | b.ensureWritable(n) 286 | copy(b.buff[b.writeIdx:b.writeIdx+n], p) 287 | b.writeIdx += n 288 | return 289 | } 290 | 291 | // Flush writes any malloc data to the underlying io.Writer. 292 | // The malloced buffer must be set correctly. 293 | func (b *defaultByteBuffer) Flush() (err error) { 294 | if b.status&BitWritable == 0 { 295 | return errors.New("unwritable buffer, cannot support Flush") 296 | } 297 | return nil 298 | } 299 | 300 | // AppendBuffer appends buf to the original buffer. 301 | func (b *defaultByteBuffer) AppendBuffer(buf ByteBuffer) (err error) { 302 | subBuf := buf.(*defaultByteBuffer) 303 | n := subBuf.writeIdx 304 | b.ensureWritable(n) 305 | copy(b.buff[b.writeIdx:b.writeIdx+n], subBuf.buff) 306 | b.writeIdx += n 307 | buf.Release(nil) 308 | return 309 | } 310 | 311 | // Bytes is used to get the bytes written. 312 | func (b *defaultByteBuffer) Bytes() (buf []byte, err error) { 313 | if b.status&BitWritable == 0 { 314 | return nil, errors.New("unwritable buffer, cannot support Bytes") 315 | } 316 | buf = make([]byte, b.writeIdx) 317 | copy(buf, b.buff[:b.writeIdx]) 318 | return buf, nil 319 | } 320 | 321 | // NewBuffer returns a new writable ByteBuffer. 322 | func (b *defaultByteBuffer) NewBuffer() ByteBuffer { 323 | return NewWriterBuffer(256) 324 | } 325 | 326 | // Release will free the buffer already read. 327 | // After release, buffer read by Next/Skip/Peek is invalid. 328 | func (b *defaultByteBuffer) Release(e error) (err error) { 329 | b.zero() 330 | byteBufPool.Put(b) 331 | return 332 | } 333 | 334 | func (b *defaultByteBuffer) zero() { 335 | b.status = 0 336 | b.buff = nil 337 | b.readIdx = 0 338 | b.writeIdx = 0 339 | } 340 | 341 | func (b *defaultByteBuffer) readableCheck(n int) error { 342 | readableLen := b.ReadableLen() 343 | if b.readIdx >= b.writeIdx && n > 0 { 344 | return io.EOF 345 | } 346 | if readableLen < n { 347 | return fmt.Errorf("default byteBuffer not enough, read[%d] but remain[%d]", n, readableLen) 348 | } 349 | return nil 350 | } 351 | 352 | func (b *defaultByteBuffer) writableLen() (n int) { 353 | if b.status&BitWritable == 0 { 354 | return -1 355 | } 356 | return cap(b.buff) - b.writeIdx 357 | } 358 | 359 | func (b *defaultByteBuffer) ensureWritable(minWritableBytes int) { 360 | if b.writableLen() >= minWritableBytes { 361 | return 362 | } 363 | minNewCapacity := b.writeIdx + minWritableBytes 364 | newCapacity := cap(b.buff) 365 | for newCapacity < minNewCapacity { 366 | newCapacity <<= 1 367 | } 368 | 369 | buf := make([]byte, newCapacity) 370 | copy(buf, b.buff) 371 | b.buff = buf 372 | } 373 | -------------------------------------------------------------------------------- /network/codec/bytebuf_util.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | "encoding/binary" 5 | "errors" 6 | "io" 7 | ) 8 | 9 | const ( 10 | Size8 = 1 11 | Size16 = 2 12 | Size32 = 4 13 | Size64 = 8 14 | ) 15 | 16 | // ReadByte ... 17 | func ReadByte(in ByteBuffer) (byte, error) { 18 | buf, err := in.Next(Size8) 19 | if err != nil { 20 | return 0, err 21 | } 22 | return buf[0], nil 23 | } 24 | 25 | // ReadUint16 ... 26 | func ReadUint16(in ByteBuffer) (uint16, error) { 27 | buf, err := in.Next(Size16) 28 | if err != nil { 29 | return 0, err 30 | } 31 | n := binary.BigEndian.Uint16(buf) 32 | return n, nil 33 | } 34 | 35 | // ReadUint32 ... 36 | func ReadUint32(in ByteBuffer) (uint32, error) { 37 | var buf []byte 38 | var err error 39 | if buf, err = in.Next(Size32); err != nil { 40 | return 0, err 41 | } 42 | return binary.BigEndian.Uint32(buf), nil 43 | } 44 | 45 | // PeekUint32 ... 46 | func PeekUint32(in ByteBuffer) (uint32, error) { 47 | var buf []byte 48 | var err error 49 | if buf, err = in.Peek(Size32); err != nil { 50 | return 0, err 51 | } 52 | return binary.BigEndian.Uint32(buf), nil 53 | } 54 | 55 | // ReadUint64 ... 56 | func ReadUint64(in ByteBuffer) (uint64, error) { 57 | var buf []byte 58 | var err error 59 | if buf, err = in.Next(Size64); err != nil { 60 | return 0, err 61 | } 62 | return binary.BigEndian.Uint64(buf), nil 63 | } 64 | 65 | // WriteByte ... 66 | func WriteByte(val byte, out ByteBuffer) error { 67 | var buf []byte 68 | var err error 69 | if buf, err = out.Malloc(1); err != nil { 70 | return err 71 | } 72 | buf[0] = val 73 | return nil 74 | } 75 | 76 | // WriteUint16 ... 77 | func WriteUint16(val uint16, out ByteBuffer) error { 78 | var buf []byte 79 | var err error 80 | if buf, err = out.Malloc(Size16); err != nil { 81 | return err 82 | } 83 | binary.BigEndian.PutUint16(buf, val) 84 | return nil 85 | } 86 | 87 | // WriteUint32 ... 88 | func WriteUint32(val uint32, out ByteBuffer) error { 89 | var buf []byte 90 | var err error 91 | if buf, err = out.Malloc(Size32); err != nil { 92 | return err 93 | } 94 | binary.BigEndian.PutUint32(buf, val) 95 | return nil 96 | } 97 | 98 | // WriteUint64 ... 99 | func WriteUint64(val uint64, out ByteBuffer) error { 100 | var buf []byte 101 | var err error 102 | if buf, err = out.Malloc(Size64); err != nil { 103 | return err 104 | } 105 | binary.BigEndian.PutUint64(buf, val) 106 | return nil 107 | } 108 | 109 | // Bytes2Uint32NoCheck ... 110 | func Bytes2Uint32NoCheck(bytes []byte) uint32 { 111 | return binary.BigEndian.Uint32(bytes) 112 | } 113 | 114 | // Bytes2Uint32 ... 115 | func Bytes2Uint32(bytes []byte) (uint32, error) { 116 | if len(bytes) < 4 { 117 | return 0, io.EOF 118 | } 119 | return binary.BigEndian.Uint32(bytes), nil 120 | } 121 | 122 | // Bytes2Uint16NoCheck ... 123 | func Bytes2Uint16NoCheck(bytes []byte) uint16 { 124 | return binary.BigEndian.Uint16(bytes) 125 | } 126 | 127 | // Bytes2Uint16 ... 128 | func Bytes2Uint16(bytes []byte, off int) (uint16, error) { 129 | if len(bytes)-off < 2 { 130 | return 0, io.EOF 131 | } 132 | return binary.BigEndian.Uint16(bytes[off:]), nil 133 | } 134 | 135 | // Bytes2Uint8 ... 136 | func Bytes2Uint8(bytes []byte, off int) (uint8, error) { 137 | if len(bytes)-off < 1 { 138 | return 0, io.EOF 139 | } 140 | return bytes[off], nil 141 | } 142 | 143 | // ReadString ... 144 | func ReadString(in ByteBuffer) (string, int, error) { 145 | strLen, err := ReadUint32(in) 146 | if err != nil { 147 | return "", 0, err 148 | } 149 | if strLen == 0 { 150 | return "", 0, errors.New("invalid string length in ReadString") 151 | } 152 | str, err := in.ReadString(int(strLen)) 153 | return str, int(strLen) + 32, err 154 | } 155 | 156 | // ReadString2BLen ... 157 | func ReadString2BLen(bytes []byte, off int) (string, int, error) { 158 | length, err := Bytes2Uint16(bytes, off) 159 | strLen := int(length) 160 | if err != nil { 161 | return "", 0, err 162 | } 163 | off += 2 164 | if len(bytes)-off < strLen { 165 | return "", 0, io.EOF 166 | } 167 | 168 | buf := bytes[off : off+strLen] 169 | return string(buf), int(length) + 2, nil 170 | } 171 | 172 | // WriteString ... 173 | func WriteString(val string, out ByteBuffer) (int, error) { 174 | strLen := len(val) 175 | if err := WriteUint32(uint32(strLen), out); err != nil { 176 | return 0, err 177 | } 178 | n, err := out.WriteString(val) 179 | if err != nil { 180 | return 0, err 181 | } 182 | return n + 4, nil 183 | } 184 | 185 | // WriteString2BLen ... 186 | func WriteString2BLen(val string, out ByteBuffer) (int, error) { 187 | strLen := len(val) 188 | if err := WriteUint16(uint16(strLen), out); err != nil { 189 | return 0, err 190 | } 191 | n, err := out.WriteString(val) 192 | if err != nil { 193 | return 0, err 194 | } 195 | return n + 2, nil 196 | } 197 | -------------------------------------------------------------------------------- /network/codec/header_codec.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | "xrpc/network/protocol" 5 | ) 6 | 7 | type HeaderCodec interface { 8 | Encode(header *protocol.Header) ([]byte, error) 9 | Decode([]byte, *protocol.Header) error 10 | } 11 | 12 | type headerCodec struct { 13 | } 14 | 15 | func (c *headerCodec) Encode(header *protocol.Header) ([]byte, error) { 16 | byteBuffer := NewWriterBuffer(protocol.FixedHeaderLength) 17 | WriteUint16(header.MagicNumber, byteBuffer) 18 | WriteByte(header.Version, byteBuffer) 19 | WriteUint16(header.HeaderLength, byteBuffer) 20 | WriteUint16(header.TotalLength, byteBuffer) 21 | WriteByte(header.MessageTypeId, byteBuffer) 22 | WriteByte(header.SerializationId, byteBuffer) 23 | WriteUint64(header.RequestId, byteBuffer) 24 | WriteByte(header.Status, byteBuffer) 25 | return byteBuffer.Bytes() 26 | } 27 | 28 | func (c *headerCodec) Decode(in []byte, header *protocol.Header) error { 29 | byteBuffer := NewReaderBuffer(in) 30 | header.MagicNumber, _ = ReadUint16(byteBuffer) 31 | header.Version, _ = ReadByte(byteBuffer) 32 | header.HeaderLength, _ = ReadUint16(byteBuffer) 33 | header.TotalLength, _ = ReadUint16(byteBuffer) 34 | header.MessageTypeId, _ = ReadByte(byteBuffer) 35 | header.SerializationId, _ = ReadByte(byteBuffer) 36 | header.RequestId, _ = ReadUint64(byteBuffer) 37 | header.Status, _ = ReadByte(byteBuffer) 38 | return nil 39 | } 40 | 41 | var h HeaderCodec = &headerCodec{} 42 | 43 | func NewHeaderCodec() HeaderCodec { 44 | return h 45 | } 46 | -------------------------------------------------------------------------------- /network/codec/message_codec.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "xrpc/network/protocol" 7 | ) 8 | 9 | type MessageCodec interface { 10 | ReadHeader(io.ReadWriteCloser, *protocol.Header) error 11 | Write(io.ReadWriteCloser, *protocol.Message) error 12 | } 13 | 14 | type messageCodec struct { 15 | headerCodec HeaderCodec 16 | } 17 | 18 | func (c *messageCodec) ReadHeader(conn io.ReadWriteCloser, header *protocol.Header) error { 19 | headerBytes := make([]byte, protocol.FixedHeaderLength) 20 | _, err := io.ReadFull(conn, headerBytes) 21 | if err != nil { 22 | return err 23 | } 24 | return c.headerCodec.Decode(headerBytes, header) 25 | } 26 | 27 | func (c *messageCodec) Write(conn io.ReadWriteCloser, message *protocol.Message) error { 28 | headerBytes, err := c.headerCodec.Encode(message.Header) 29 | if err != nil { 30 | return err 31 | } 32 | byteArr := [][]byte{headerBytes, message.Payload} 33 | combineBytes := bytes.Join(byteArr, []byte("")) 34 | _, err = conn.Write(combineBytes) 35 | if err != nil { 36 | return err 37 | } 38 | return nil 39 | } 40 | 41 | var m MessageCodec = &messageCodec{ 42 | headerCodec: NewHeaderCodec(), 43 | } 44 | 45 | func NewMessageCodec() MessageCodec { 46 | return m 47 | } 48 | -------------------------------------------------------------------------------- /network/codec/payload_codec.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | const ( 8 | JsonName string = "json" 9 | ) 10 | 11 | const ( 12 | Json = iota 13 | ) 14 | 15 | var payloadMap = make(map[string]PayloadCodec) 16 | var nameMap = make(map[int]string) 17 | var idMap = make(map[string]int) 18 | 19 | func init() { 20 | payloadMap[JsonName] = NewJsonCodec() 21 | nameMap[Json] = JsonName 22 | idMap[JsonName] = Json 23 | } 24 | 25 | func GetPayloadCodecName(id int) string { 26 | return nameMap[id] 27 | } 28 | 29 | func GetPayloadCodecId(name string) int { 30 | return idMap[name] 31 | } 32 | 33 | // GetPayloadCodec gets desired payload codec from message. 34 | func GetPayloadCodec(name string) PayloadCodec { 35 | pc := payloadMap[name] 36 | return pc 37 | } 38 | 39 | // PayloadCodec is used to marshal and unmarshal payload. 40 | type PayloadCodec interface { 41 | Marshal(i interface{}) ([]byte, error) 42 | Unmarshal(data []byte, i interface{}) error 43 | Name() string 44 | } 45 | 46 | type JsonCodec struct{} 47 | 48 | func (_ *JsonCodec) Marshal(i interface{}) ([]byte, error) { 49 | return json.Marshal(i) 50 | } 51 | 52 | func (_ *JsonCodec) Unmarshal(data []byte, i interface{}) error { 53 | return json.Unmarshal(data, i) 54 | } 55 | 56 | func (_ *JsonCodec) Name() string { 57 | return "json" 58 | } 59 | 60 | var jsonCodec PayloadCodec = &JsonCodec{} 61 | 62 | func NewJsonCodec() PayloadCodec { 63 | return jsonCodec 64 | } 65 | -------------------------------------------------------------------------------- /network/protocol/message.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | const ( 4 | RpcRequest = iota 5 | RpcResponse 6 | ) 7 | 8 | const ( 9 | MagicNumber = 0x8023 10 | Version = 1 11 | FixedHeaderLength = 18 12 | ) 13 | 14 | // Header 18 bytes 15 | type Header struct { 16 | MagicNumber uint16 17 | Version uint8 18 | HeaderLength uint16 19 | TotalLength uint16 20 | MessageTypeId uint8 21 | SerializationId uint8 22 | RequestId uint64 23 | Status uint8 24 | } 25 | 26 | type RpcRequestPayload struct { 27 | ServiceName string `json:"serviceName"` 28 | MethodName string `json:"methodName"` 29 | ArgMap map[string]interface{} `json:"argMap"` 30 | } 31 | 32 | type Message struct { 33 | *Header 34 | Payload []byte 35 | } 36 | -------------------------------------------------------------------------------- /network/transport/net/net_client.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | import ( 4 | "io" 5 | "net" 6 | "sync" 7 | "time" 8 | "xrpc/network/codec" 9 | "xrpc/network/protocol" 10 | "xrpc/network/transport" 11 | ) 12 | 13 | type netClient struct { 14 | conns []net.Conn 15 | } 16 | 17 | func (c *netClient) CreateTransport(address string, timeout time.Duration) (transport.Transport, error) { 18 | conn, _ := net.DialTimeout("tcp", address, timeout) 19 | c.conns = append(c.conns, conn) 20 | return newNetTransport(conn), nil 21 | } 22 | 23 | func (c *netClient) Close() error { 24 | for _, conn := range c.conns { 25 | conn.Close() 26 | } 27 | return nil 28 | } 29 | 30 | type netTransport struct { 31 | mu sync.Mutex 32 | conn io.ReadWriteCloser 33 | messageCodec codec.MessageCodec 34 | inFlightCalls transport.InFlightCalls 35 | } 36 | 37 | func (t *netTransport) Send(message *protocol.Message, reply interface{}) (*transport.Call, error) { 38 | t.mu.Lock() 39 | defer t.mu.Unlock() 40 | t.messageCodec.Write(t.conn, message) 41 | call := &transport.Call{ 42 | RequestId: int(message.Header.RequestId), 43 | Reply: reply, 44 | Done: make(chan *transport.Call, 1), 45 | } 46 | t.inFlightCalls.AddCall(call) 47 | return call, nil 48 | } 49 | 50 | func (t *netTransport) receive() error { 51 | var header protocol.Header 52 | t.messageCodec.ReadHeader(t.conn, &header) 53 | payload := make([]byte, header.TotalLength-header.HeaderLength) 54 | io.ReadFull(t.conn, payload) 55 | call, _ := t.inFlightCalls.RemoveCall(int(header.RequestId)) 56 | // 根据序列化id反序列化 57 | name := codec.GetPayloadCodecName(int(header.SerializationId)) 58 | payloadCodec := codec.GetPayloadCodec(name) 59 | payloadCodec.Unmarshal(payload, call.Reply) 60 | call.Complete() 61 | return nil 62 | } 63 | 64 | func NewNetClient() transport.TransClient { 65 | return &netClient{ 66 | conns: []net.Conn{}, 67 | } 68 | } 69 | 70 | func newNetTransport(conn net.Conn) transport.Transport { 71 | transport := &netTransport{ 72 | mu: sync.Mutex{}, 73 | conn: conn, 74 | messageCodec: codec.NewMessageCodec(), 75 | inFlightCalls: transport.InFlightCalls{}, 76 | } 77 | go transport.receive() 78 | return transport 79 | } 80 | -------------------------------------------------------------------------------- /network/transport/net/net_server.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | import ( 4 | "io" 5 | "net" 6 | "xrpc/network/codec" 7 | "xrpc/network/protocol" 8 | "xrpc/network/transport" 9 | ) 10 | 11 | type netServer struct { 12 | messageCodec codec.MessageCodec 13 | handlerMap map[int]transport.TransHandler 14 | } 15 | 16 | func (s *netServer) Start(address string, handlerMap map[int]transport.TransHandler) error { 17 | s.handlerMap = handlerMap 18 | listen, _ := net.Listen("tcp", address) 19 | for { 20 | conn, _ := listen.Accept() 21 | go s.handleRequest(conn) 22 | } 23 | } 24 | 25 | func (s *netServer) handleRequest(conn net.Conn) error { 26 | header := &protocol.Header{} 27 | s.messageCodec.ReadHeader(conn, header) 28 | payload := make([]byte, header.TotalLength-header.HeaderLength) 29 | _, err := io.ReadFull(conn, payload) 30 | if err != nil { 31 | return err 32 | } 33 | message := protocol.Message{ 34 | Header: header, 35 | Payload: payload, 36 | } 37 | // 获取对应的请求处理器 38 | handler := s.handlerMap[int(header.MessageTypeId)] 39 | // 提交给对应的请求处理器进行处理 40 | respMessage, _ := handler.Handle(&message) 41 | err = s.messageCodec.Write(conn, respMessage) 42 | if err != nil { 43 | return err 44 | } 45 | return nil 46 | } 47 | 48 | func NewNetServer() transport.TransServer { 49 | return &netServer{ 50 | messageCodec: codec.NewMessageCodec(), 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /network/transport/trans_client.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import ( 4 | "sync" 5 | "time" 6 | "xrpc/network/protocol" 7 | ) 8 | 9 | type TransClient interface { 10 | CreateTransport(address string, timeout time.Duration) (Transport, error) 11 | Close() error 12 | } 13 | 14 | type Transport interface { 15 | Send(*protocol.Message, interface{}) (*Call, error) 16 | } 17 | 18 | type Call struct { 19 | RequestId int 20 | Reply interface{} // The reply from the function (*struct). 21 | Done chan *Call 22 | } 23 | 24 | func (call *Call) Complete() { 25 | call.Done <- call 26 | } 27 | 28 | type InFlightCalls struct { 29 | callMap sync.Map 30 | } 31 | 32 | func (i *InFlightCalls) AddCall(call *Call) error { 33 | i.callMap.Store(call.RequestId, call) 34 | return nil 35 | } 36 | 37 | func (i *InFlightCalls) RemoveCall(requestId int) (*Call, error) { 38 | call, _ := i.callMap.Load(requestId) 39 | i.callMap.Delete(requestId) 40 | return call.(*Call), nil 41 | } 42 | -------------------------------------------------------------------------------- /network/transport/trans_handler.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import ( 4 | "xrpc/network/protocol" 5 | ) 6 | 7 | type TransHandler interface { 8 | Handle(message *protocol.Message) (*protocol.Message, error) 9 | } 10 | -------------------------------------------------------------------------------- /network/transport/trans_server.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | type TransServerFactory interface { 4 | NewTransServer() TransServer 5 | } 6 | 7 | type TransServer interface { 8 | Start(address string, handlerMap map[int]TransHandler) error 9 | } 10 | -------------------------------------------------------------------------------- /registry/nacos_registry.go: -------------------------------------------------------------------------------- 1 | package registry 2 | 3 | const ( 4 | NacosRegistryPath = "/registry" 5 | ) 6 | 7 | type NacosRegistry struct { 8 | } 9 | 10 | func (r *NacosRegistry) Connect(uri string) error { 11 | return nil 12 | } 13 | 14 | func (r *NacosRegistry) RegisterService(serviceName, uri string) error { 15 | return nil 16 | } 17 | 18 | func (r *NacosRegistry) GetServiceAddress(serviceName string) ([]string, error) { 19 | var uris []string 20 | return uris, nil 21 | } 22 | 23 | func (r *NacosRegistry) Name() string { 24 | return "nacos" 25 | } 26 | 27 | func NewNacosRegistry(uri string) Registry { 28 | registry := &NacosRegistry{} 29 | registry.Connect(uri) 30 | return registry 31 | } 32 | -------------------------------------------------------------------------------- /registry/registry.go: -------------------------------------------------------------------------------- 1 | package registry 2 | 3 | import "net/url" 4 | 5 | const ( 6 | ZooKeeperName string = "zookeeper" 7 | NacosName string = "nacos" 8 | ) 9 | 10 | const ( 11 | ZooKeeper = iota 12 | Nacos 13 | ) 14 | 15 | type NewRegistryFunc func(string) Registry 16 | 17 | var registryMap = make(map[string]NewRegistryFunc) 18 | var nameMap = make(map[int]string) 19 | 20 | func init() { 21 | registryMap[ZooKeeperName] = NewZookeeperRegistry 22 | nameMap[ZooKeeper] = ZooKeeperName 23 | registryMap[NacosName] = NewNacosRegistry 24 | nameMap[Nacos] = NacosName 25 | } 26 | 27 | type Registry interface { 28 | Connect(uri string) error 29 | RegisterService(serviceName, uri string) error 30 | GetServiceAddress(serviceName string) ([]string, error) 31 | Name() string 32 | } 33 | 34 | func NewRegistry(nameServiceUri string) (Registry, error) { 35 | u, err := url.Parse(nameServiceUri) 36 | if err != nil { 37 | return nil, err 38 | } 39 | return registryMap[u.Scheme](u.Host), nil 40 | } 41 | -------------------------------------------------------------------------------- /registry/zookeeper_registry.go: -------------------------------------------------------------------------------- 1 | package registry 2 | 3 | import ( 4 | "fmt" 5 | "github.com/go-zookeeper/zk" 6 | "time" 7 | ) 8 | 9 | const ( 10 | ZKRegistryPath = "/registry" 11 | ) 12 | 13 | type ZookeeperRegistry struct { 14 | conn *zk.Conn 15 | } 16 | 17 | func (r *ZookeeperRegistry) Connect(uri string) error { 18 | conn, _, err := zk.Connect([]string{uri}, time.Second) 19 | if err != nil { 20 | return err 21 | } 22 | r.conn = conn 23 | return nil 24 | } 25 | 26 | func (r *ZookeeperRegistry) RegisterService(serviceName, uri string) error { 27 | var registryPath = ZKRegistryPath 28 | isExist, _, err := r.conn.Exists(registryPath) 29 | if err != nil { 30 | return err 31 | } 32 | // 创建永久节点 33 | if !isExist { 34 | r.conn.Create(registryPath, nil, 0, zk.WorldACL(zk.PermAll)) 35 | } 36 | var servicePath = registryPath + "/" + serviceName 37 | isExist, _, err = r.conn.Exists(servicePath) 38 | if err != nil { 39 | return err 40 | } 41 | // 创建永久节点 42 | if !isExist { 43 | r.conn.Create(servicePath, nil, 0, zk.WorldACL(zk.PermAll)) 44 | } 45 | // 创建临时顺序节点 46 | var addressPath = servicePath + "/" 47 | r.conn.Create(addressPath, []byte(uri), zk.FlagEphemeral|zk.FlagSequence, zk.WorldACL(zk.PermAll)) 48 | fmt.Println(addressPath) 49 | fmt.Println(uri) 50 | return nil 51 | } 52 | 53 | func (r *ZookeeperRegistry) GetServiceAddress(serviceName string) ([]string, error) { 54 | var servicePath = ZKRegistryPath + "/" + serviceName 55 | addrs, _, err := r.conn.Children(servicePath) 56 | if err != nil { 57 | return nil, err 58 | } 59 | if len(addrs) == 0 { 60 | return nil, nil 61 | } 62 | var uris []string 63 | for _, addr := range addrs { 64 | uri, _, _ := r.conn.Get(servicePath + "/" + addr) 65 | uris = append(uris, string(uri)) 66 | } 67 | return uris, nil 68 | } 69 | 70 | func (r *ZookeeperRegistry) Name() string { 71 | return "zookeeper" 72 | } 73 | 74 | func NewZookeeperRegistry(uri string) Registry { 75 | registry := &ZookeeperRegistry{} 76 | registry.Connect(uri) 77 | return registry 78 | } 79 | -------------------------------------------------------------------------------- /server/handler.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "reflect" 5 | "strings" 6 | "xrpc/network/codec" 7 | "xrpc/network/protocol" 8 | "xrpc/network/transport" 9 | ) 10 | 11 | type RpcRequestHandler struct { 12 | serviceMap map[string]*service 13 | } 14 | 15 | func firstUpper(s string) string { 16 | if s == "" { 17 | return "" 18 | } 19 | return strings.ToUpper(s[:1]) + s[1:] 20 | } 21 | 22 | func (h *RpcRequestHandler) Handle(message *protocol.Message) (*protocol.Message, error) { 23 | header := message.Header 24 | name := codec.GetPayloadCodecName(int(header.SerializationId)) 25 | payloadCodec := codec.GetPayloadCodec(name) 26 | rpcRequest := &protocol.RpcRequestPayload{} 27 | payloadCodec.Unmarshal(message.Payload, rpcRequest) 28 | service := h.serviceMap[rpcRequest.ServiceName] 29 | serviceMethod := service.methodMap[firstUpper(rpcRequest.MethodName)] 30 | argv := reflect.New(serviceMethod.argsType) 31 | argMap := rpcRequest.ArgMap 32 | for name, value := range argMap { 33 | argv.Elem().FieldByName(firstUpper(name)).Set(reflect.ValueOf(value)) 34 | } 35 | replv := reflect.New(serviceMethod.replyType) 36 | service.call(serviceMethod, argv, replv) 37 | payload, err := payloadCodec.Marshal(replv.Interface()) 38 | if err != nil { 39 | return nil, err 40 | } 41 | respHeader := &protocol.Header{ 42 | MagicNumber: protocol.MagicNumber, 43 | Version: protocol.Version, 44 | HeaderLength: uint16(protocol.FixedHeaderLength), 45 | TotalLength: uint16(protocol.FixedHeaderLength + len(payload)), 46 | MessageTypeId: protocol.RpcResponse, 47 | SerializationId: header.SerializationId, 48 | RequestId: header.RequestId, 49 | } 50 | return &protocol.Message{ 51 | Header: respHeader, 52 | Payload: payload, 53 | }, nil 54 | } 55 | 56 | func NewRpcRequestHandler(serviceMap map[string]*service) transport.TransHandler { 57 | return &RpcRequestHandler{ 58 | serviceMap: serviceMap, 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /server/server.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "net" 5 | "xrpc/network/protocol" 6 | "xrpc/network/transport" 7 | _net "xrpc/network/transport/net" 8 | "xrpc/registry" 9 | ) 10 | 11 | const ( 12 | serviceNamePrefix = "com.smallc.xrpc" 13 | ) 14 | 15 | type Server interface { 16 | Start() 17 | AddService(string, interface{}) 18 | } 19 | 20 | type server struct { 21 | host string 22 | port string 23 | uri string 24 | serviceMap map[string]*service 25 | handlerMap map[int]transport.TransHandler 26 | registry registry.Registry 27 | transServer transport.TransServer 28 | } 29 | 30 | func (s *server) Start() { 31 | if s.transServer == nil { 32 | s.transServer = _net.NewNetServer() 33 | s.handlerMap[protocol.RpcRequest] = NewRpcRequestHandler(s.serviceMap) 34 | s.transServer.Start(s.host+":"+s.port, s.handlerMap) 35 | } 36 | } 37 | 38 | func (s *server) AddService(serviceName string, rcvr interface{}) { 39 | service := NewService(rcvr) 40 | s.serviceMap[serviceName] = service 41 | s.registry.RegisterService(serviceName, s.uri) 42 | } 43 | 44 | func NewServer(port string, nameServiceUri string) (Server, error) { 45 | registry, err := registry.NewRegistry(nameServiceUri) 46 | if err != nil { 47 | return nil, err 48 | } 49 | 50 | // get local ip address 51 | interfaces, err := net.Interfaces() 52 | var host string 53 | for _, i := range interfaces { 54 | if i.Flags&net.FlagUp == 0 { 55 | continue 56 | } 57 | if (i.Flags & net.FlagLoopback) != 0 { 58 | continue 59 | } 60 | addresses, _ := i.Addrs() 61 | for _, addr := range addresses { 62 | if ipNet, ok := addr.(*net.IPNet); ok && !ipNet.IP.IsLoopback() { 63 | if ipNet.IP.To4() != nil { 64 | host = ipNet.IP.String() 65 | break 66 | } 67 | } 68 | } 69 | } 70 | return &server{ 71 | host: host, 72 | port: port, 73 | uri: "rpc://" + host + ":" + port, 74 | serviceMap: make(map[string]*service), 75 | handlerMap: make(map[int]transport.TransHandler), 76 | registry: registry, 77 | }, nil 78 | } 79 | -------------------------------------------------------------------------------- /server/service.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "go/ast" 5 | "log" 6 | "reflect" 7 | ) 8 | 9 | var ( 10 | errorType = reflect.TypeOf((*error)(nil)).Elem() 11 | ) 12 | 13 | type serviceMethod struct { 14 | method reflect.Method 15 | argsType reflect.Type 16 | replyType reflect.Type 17 | } 18 | 19 | type service struct { 20 | name string 21 | typ reflect.Type 22 | rcvr reflect.Value 23 | methodMap map[string]*serviceMethod 24 | } 25 | 26 | func NewService(rcvr interface{}) *service { 27 | s := new(service) 28 | s.rcvr = reflect.ValueOf(rcvr) 29 | s.typ = reflect.TypeOf(rcvr) 30 | s.name = reflect.Indirect(s.rcvr).Type().Name() 31 | if !ast.IsExported(s.name) { 32 | log.Fatalf("%s is not a valid service name.", s.name) 33 | } 34 | s.registerMethods() 35 | return s 36 | } 37 | 38 | func (s *service) registerMethods() { 39 | s.methodMap = make(map[string]*serviceMethod) 40 | for i := 0; i < s.typ.NumMethod(); i++ { 41 | method := s.typ.Method(i) 42 | mType := method.Type 43 | if mType.NumIn() != 3 || mType.NumOut() != 1 { 44 | continue 45 | } 46 | argsType, replyType := mType.In(1), mType.In(2) 47 | if argsType.Kind() != reflect.Ptr { 48 | continue 49 | } 50 | if replyType.Kind() != reflect.Ptr { 51 | continue 52 | } 53 | if !isExportedOrBuiltinType(argsType) || !isExportedOrBuiltinType(replyType) { 54 | continue 55 | } 56 | if returnType := mType.Out(0); returnType != errorType { 57 | continue 58 | } 59 | s.methodMap[method.Name] = &serviceMethod{ 60 | method: method, 61 | argsType: argsType.Elem(), 62 | replyType: replyType.Elem(), 63 | } 64 | } 65 | } 66 | 67 | func isExportedOrBuiltinType(t reflect.Type) bool { 68 | return ast.IsExported(t.Name()) || t.PkgPath() == "" 69 | } 70 | 71 | func (s *service) call(m *serviceMethod, argv, replyv reflect.Value) error { 72 | f := m.method.Func 73 | ret := f.Call([]reflect.Value{s.rcvr, argv, replyv}) 74 | if err := ret[0].Interface(); err != nil { 75 | return err.(error) 76 | } 77 | return nil 78 | } 79 | --------------------------------------------------------------------------------