main.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. *
  3. * Copyright 2016 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package main
  19. import (
  20. "context"
  21. "flag"
  22. "fmt"
  23. "io"
  24. "net"
  25. "net/http"
  26. _ "net/http/pprof"
  27. "runtime"
  28. "strconv"
  29. "time"
  30. "google.golang.org/grpc"
  31. testpb "google.golang.org/grpc/benchmark/grpc_testing"
  32. "google.golang.org/grpc/codes"
  33. "google.golang.org/grpc/grpclog"
  34. "google.golang.org/grpc/status"
  35. )
  36. var (
  37. driverPort = flag.Int("driver_port", 10000, "port for communication with driver")
  38. serverPort = flag.Int("server_port", 0, "port for benchmark server if not specified by server config message")
  39. pprofPort = flag.Int("pprof_port", -1, "Port for pprof debug server to listen on. Pprof server doesn't start if unset")
  40. blockProfRate = flag.Int("block_prof_rate", 0, "fraction of goroutine blocking events to report in blocking profile")
  41. )
  42. type byteBufCodec struct {
  43. }
  44. func (byteBufCodec) Marshal(v interface{}) ([]byte, error) {
  45. b, ok := v.(*[]byte)
  46. if !ok {
  47. return nil, fmt.Errorf("failed to marshal: %v is not type of *[]byte", v)
  48. }
  49. return *b, nil
  50. }
  51. func (byteBufCodec) Unmarshal(data []byte, v interface{}) error {
  52. b, ok := v.(*[]byte)
  53. if !ok {
  54. return fmt.Errorf("failed to marshal: %v is not type of *[]byte", v)
  55. }
  56. *b = data
  57. return nil
  58. }
  59. func (byteBufCodec) String() string {
  60. return "bytebuffer"
  61. }
  62. // workerServer implements WorkerService rpc handlers.
  63. // It can create benchmarkServer or benchmarkClient on demand.
  64. type workerServer struct {
  65. stop chan<- bool
  66. serverPort int
  67. }
  68. func (s *workerServer) RunServer(stream testpb.WorkerService_RunServerServer) error {
  69. var bs *benchmarkServer
  70. defer func() {
  71. // Close benchmark server when stream ends.
  72. grpclog.Infof("closing benchmark server")
  73. if bs != nil {
  74. bs.closeFunc()
  75. }
  76. }()
  77. for {
  78. in, err := stream.Recv()
  79. if err == io.EOF {
  80. return nil
  81. }
  82. if err != nil {
  83. return err
  84. }
  85. var out *testpb.ServerStatus
  86. switch argtype := in.Argtype.(type) {
  87. case *testpb.ServerArgs_Setup:
  88. grpclog.Infof("server setup received:")
  89. if bs != nil {
  90. grpclog.Infof("server setup received when server already exists, closing the existing server")
  91. bs.closeFunc()
  92. }
  93. bs, err = startBenchmarkServer(argtype.Setup, s.serverPort)
  94. if err != nil {
  95. return err
  96. }
  97. out = &testpb.ServerStatus{
  98. Stats: bs.getStats(false),
  99. Port: int32(bs.port),
  100. Cores: int32(bs.cores),
  101. }
  102. case *testpb.ServerArgs_Mark:
  103. grpclog.Infof("server mark received:")
  104. grpclog.Infof(" - %v", argtype)
  105. if bs == nil {
  106. return status.Error(codes.InvalidArgument, "server does not exist when mark received")
  107. }
  108. out = &testpb.ServerStatus{
  109. Stats: bs.getStats(argtype.Mark.Reset_),
  110. Port: int32(bs.port),
  111. Cores: int32(bs.cores),
  112. }
  113. }
  114. if err := stream.Send(out); err != nil {
  115. return err
  116. }
  117. }
  118. }
  119. func (s *workerServer) RunClient(stream testpb.WorkerService_RunClientServer) error {
  120. var bc *benchmarkClient
  121. defer func() {
  122. // Shut down benchmark client when stream ends.
  123. grpclog.Infof("shuting down benchmark client")
  124. if bc != nil {
  125. bc.shutdown()
  126. }
  127. }()
  128. for {
  129. in, err := stream.Recv()
  130. if err == io.EOF {
  131. return nil
  132. }
  133. if err != nil {
  134. return err
  135. }
  136. var out *testpb.ClientStatus
  137. switch t := in.Argtype.(type) {
  138. case *testpb.ClientArgs_Setup:
  139. grpclog.Infof("client setup received:")
  140. if bc != nil {
  141. grpclog.Infof("client setup received when client already exists, shuting down the existing client")
  142. bc.shutdown()
  143. }
  144. bc, err = startBenchmarkClient(t.Setup)
  145. if err != nil {
  146. return err
  147. }
  148. out = &testpb.ClientStatus{
  149. Stats: bc.getStats(false),
  150. }
  151. case *testpb.ClientArgs_Mark:
  152. grpclog.Infof("client mark received:")
  153. grpclog.Infof(" - %v", t)
  154. if bc == nil {
  155. return status.Error(codes.InvalidArgument, "client does not exist when mark received")
  156. }
  157. out = &testpb.ClientStatus{
  158. Stats: bc.getStats(t.Mark.Reset_),
  159. }
  160. }
  161. if err := stream.Send(out); err != nil {
  162. return err
  163. }
  164. }
  165. }
  166. func (s *workerServer) CoreCount(ctx context.Context, in *testpb.CoreRequest) (*testpb.CoreResponse, error) {
  167. grpclog.Infof("core count: %v", runtime.NumCPU())
  168. return &testpb.CoreResponse{Cores: int32(runtime.NumCPU())}, nil
  169. }
  170. func (s *workerServer) QuitWorker(ctx context.Context, in *testpb.Void) (*testpb.Void, error) {
  171. grpclog.Infof("quitting worker")
  172. s.stop <- true
  173. return &testpb.Void{}, nil
  174. }
  175. func main() {
  176. grpc.EnableTracing = false
  177. flag.Parse()
  178. lis, err := net.Listen("tcp", ":"+strconv.Itoa(*driverPort))
  179. if err != nil {
  180. grpclog.Fatalf("failed to listen: %v", err)
  181. }
  182. grpclog.Infof("worker listening at port %v", *driverPort)
  183. s := grpc.NewServer()
  184. stop := make(chan bool)
  185. testpb.RegisterWorkerServiceServer(s, &workerServer{
  186. stop: stop,
  187. serverPort: *serverPort,
  188. })
  189. go func() {
  190. <-stop
  191. // Wait for 1 second before stopping the server to make sure the return value of QuitWorker is sent to client.
  192. // TODO revise this once server graceful stop is supported in gRPC.
  193. time.Sleep(time.Second)
  194. s.Stop()
  195. }()
  196. runtime.SetBlockProfileRate(*blockProfRate)
  197. if *pprofPort >= 0 {
  198. go func() {
  199. grpclog.Infoln("Starting pprof server on port " + strconv.Itoa(*pprofPort))
  200. grpclog.Infoln(http.ListenAndServe("localhost:"+strconv.Itoa(*pprofPort), nil))
  201. }()
  202. }
  203. s.Serve(lis)
  204. }