go get -v -u -d github.com/metaverse/truss cd$GOPATH/src/github.com/metaverse/truss make dependencies make
二 proto 内容说明
在 .proto 文件中定义通讯接口。truss 将基于 package 指定的包名称定义服务的名称,为保证代码可读性 package 指定名称应该与 service 指定名称相同。如下:
1 2 3
// echo.proto package echo; service Echo{...}
一个 API 服务是通过 rpc 调用以及 rpc 调用的参数消息和响应消息构成。请求和响应消息中的字段是枚举类型(protobuf 序列化要求)。
1 2 3 4
message LouderRequest { string In = 1; // In is the string to echo back int32 Loudness = 2; // Loudness is the number of exclamations marks to add to the echoed string }
在使用 rpc 描述 API 接口时可以添加 HTTP 注解使接口支持 HTTP 调用(需要导入谷歌注解包)。
service Echo { ... rpc Echo (EchoRequest) returns (EchoResponse) { option (google.api.http) = { // All message fields are query parameters of the http request unless otherwise specified get: "/echo" }; } ... }
除了想上面使用 GET 方法,还可以使用 POST 方法,从 HTTP Body 中获取参数(如果 API 接口中包含 map 类型变量,必须使用 POST 方法,将参数放在 Body 中):
1 2 3 4 5 6
rpc Louder (LouderRequest) returns (EchoResponse) { option (google.api.http) = { post: "/louder/{Loudness}"// Loudness is accepted in the http path body: "*"// All other fields (In) are located in the body of the http/json request }; }
// Serve accepts incoming connections on the listener lis, creating a new // ServerTransport and service goroutine for each. The service goroutines // read gRPC requests and then call the registered handlers to reply to them. // Serve returns when lis.Accept fails with fatal errors. lis will be closed when // this method returns. // Serve will return a non-nil error unless Stop or GracefulStop is called. func(s *Server) Serve(lis net.Listener) error { s.mu.Lock() s.printf("serving") s.serve = true if s.lis == nil { // Serve called after Stop or GracefulStop. s.mu.Unlock() lis.Close() return ErrServerStopped }
s.serveWG.Add(1) deferfunc() { s.serveWG.Done() select { // Stop or GracefulStop called; block until done and return nil. case <-s.quit: <-s.done default: } }()
ls := &listenSocket{Listener: lis} s.lis[ls] = true
if channelz.IsOn() { ls.channelzID = channelz.RegisterListenSocket(ls, s.channelzID, "") } s.mu.Unlock()
var tempDelay time.Duration // how long to sleep on accept failure
for { rawConn, err := lis.Accept() if err != nil { if ne, ok := err.(interface { Temporary() bool }); ok && ne.Temporary() { if tempDelay == 0 { tempDelay = 5 * time.Millisecond } else { tempDelay *= 2 } if max := 1 * time.Second; tempDelay > max { tempDelay = max } s.mu.Lock() s.printf("Accept error: %v; retrying in %v", err, tempDelay) s.mu.Unlock() timer := time.NewTimer(tempDelay) select { case <-timer.C: case <-s.quit: timer.Stop() returnnil } continue } s.mu.Lock() s.printf("done serving; Accept = %v", err) s.mu.Unlock()
select { case <-s.quit: returnnil default: } return err } tempDelay = 0 // Start a new goroutine to deal with rawConn so we don't stall this Accept // loop goroutine. // // Make sure we account for the goroutine so GracefulStop doesn't nil out // s.conns before this conn can be added. s.serveWG.Add(1) gofunc() { s.handleRawConn(rawConn) s.serveWG.Done() }() } }