You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

182 lines
5.1 KiB

5 years ago
6 years ago
6 years ago
5 years ago
6 years ago
5 years ago
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
5 years ago
  1. package pb
  2. import (
  3. "context"
  4. "fmt"
  5. "net/http"
  6. "strconv"
  7. "strings"
  8. "sync"
  9. "time"
  10. "google.golang.org/grpc"
  11. "google.golang.org/grpc/keepalive"
  12. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  13. "github.com/chrislusf/seaweedfs/weed/pb/master_pb"
  14. )
  15. var (
  16. // cache grpc connections
  17. grpcClients = make(map[string]*grpc.ClientConn)
  18. grpcClientsLock sync.Mutex
  19. )
  20. func init() {
  21. http.DefaultTransport.(*http.Transport).MaxIdleConnsPerHost = 1024
  22. }
  23. func NewGrpcServer(opts ...grpc.ServerOption) *grpc.Server {
  24. var options []grpc.ServerOption
  25. options = append(options, grpc.KeepaliveParams(keepalive.ServerParameters{
  26. Time: 10 * time.Second, // wait time before ping if no activity
  27. Timeout: 20 * time.Second, // ping timeout
  28. }), grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{
  29. MinTime: 60 * time.Second, // min time a client should wait before sending a ping
  30. PermitWithoutStream: true,
  31. }))
  32. for _, opt := range opts {
  33. if opt != nil {
  34. options = append(options, opt)
  35. }
  36. }
  37. return grpc.NewServer(options...)
  38. }
  39. func GrpcDial(ctx context.Context, address string, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
  40. // opts = append(opts, grpc.WithBlock())
  41. // opts = append(opts, grpc.WithTimeout(time.Duration(5*time.Second)))
  42. var options []grpc.DialOption
  43. options = append(options,
  44. // grpc.WithInsecure(),
  45. grpc.WithKeepaliveParams(keepalive.ClientParameters{
  46. Time: 30 * time.Second, // client ping server if no activity for this long
  47. Timeout: 20 * time.Second,
  48. PermitWithoutStream: true,
  49. }))
  50. for _, opt := range opts {
  51. if opt != nil {
  52. options = append(options, opt)
  53. }
  54. }
  55. return grpc.DialContext(ctx, address, options...)
  56. }
  57. func WithCachedGrpcClient(fn func(*grpc.ClientConn) error, address string, opts ...grpc.DialOption) error {
  58. grpcClientsLock.Lock()
  59. existingConnection, found := grpcClients[address]
  60. if found {
  61. grpcClientsLock.Unlock()
  62. err := fn(existingConnection)
  63. if err != nil {
  64. grpcClientsLock.Lock()
  65. delete(grpcClients, address)
  66. grpcClientsLock.Unlock()
  67. existingConnection.Close()
  68. }
  69. return err
  70. }
  71. grpcConnection, err := GrpcDial(context.Background(), address, opts...)
  72. if err != nil {
  73. grpcClientsLock.Unlock()
  74. return fmt.Errorf("fail to dial %s: %v", address, err)
  75. }
  76. grpcClients[address] = grpcConnection
  77. grpcClientsLock.Unlock()
  78. err = fn(grpcConnection)
  79. if err != nil {
  80. grpcClientsLock.Lock()
  81. delete(grpcClients, address)
  82. grpcClientsLock.Unlock()
  83. grpcConnection.Close()
  84. }
  85. return err
  86. }
  87. func ParseServerToGrpcAddress(server string) (serverGrpcAddress string, err error) {
  88. colonIndex := strings.LastIndex(server, ":")
  89. if colonIndex < 0 {
  90. return "", fmt.Errorf("server should have hostname:port format: %v", server)
  91. }
  92. port, parseErr := strconv.ParseUint(server[colonIndex+1:], 10, 64)
  93. if parseErr != nil {
  94. return "", fmt.Errorf("server port parse error: %v", parseErr)
  95. }
  96. grpcPort := int(port) + 10000
  97. return fmt.Sprintf("%s:%d", server[:colonIndex], grpcPort), nil
  98. }
  99. func ServerToGrpcAddress(server string) (serverGrpcAddress string) {
  100. hostnameAndPort := strings.Split(server, ":")
  101. if len(hostnameAndPort) != 2 {
  102. return fmt.Sprintf("unexpected server address: %s", server)
  103. }
  104. port, parseErr := strconv.ParseUint(hostnameAndPort[1], 10, 64)
  105. if parseErr != nil {
  106. return fmt.Sprintf("failed to parse port for %s:%s", hostnameAndPort[0], hostnameAndPort[1])
  107. }
  108. grpcPort := int(port) + 10000
  109. return fmt.Sprintf("%s:%d", hostnameAndPort[0], grpcPort)
  110. }
  111. func WithMasterClient(master string, grpcDialOption grpc.DialOption, fn func(client master_pb.SeaweedClient) error) error {
  112. masterGrpcAddress, parseErr := ParseServerToGrpcAddress(master)
  113. if parseErr != nil {
  114. return fmt.Errorf("failed to parse master grpc %v: %v", master, parseErr)
  115. }
  116. return WithCachedGrpcClient(func(grpcConnection *grpc.ClientConn) error {
  117. client := master_pb.NewSeaweedClient(grpcConnection)
  118. return fn(client)
  119. }, masterGrpcAddress, grpcDialOption)
  120. }
  121. func WithFilerClient(filer string, grpcDialOption grpc.DialOption, fn func(client filer_pb.SeaweedFilerClient) error) error {
  122. filerGrpcAddress, parseErr := ParseServerToGrpcAddress(filer)
  123. if parseErr != nil {
  124. return fmt.Errorf("failed to parse filer grpc %v: %v", filer, parseErr)
  125. }
  126. return WithGrpcFilerClient(filerGrpcAddress, grpcDialOption, fn)
  127. }
  128. func WithGrpcFilerClient(filerGrpcAddress string, grpcDialOption grpc.DialOption, fn func(client filer_pb.SeaweedFilerClient) error) error {
  129. return WithCachedGrpcClient(func(grpcConnection *grpc.ClientConn) error {
  130. client := filer_pb.NewSeaweedFilerClient(grpcConnection)
  131. return fn(client)
  132. }, filerGrpcAddress, grpcDialOption)
  133. }
  134. func ParseFilerGrpcAddress(filer string) (filerGrpcAddress string, err error) {
  135. hostnameAndPort := strings.Split(filer, ":")
  136. if len(hostnameAndPort) != 2 {
  137. return "", fmt.Errorf("filer should have hostname:port format: %v", hostnameAndPort)
  138. }
  139. filerPort, parseErr := strconv.ParseUint(hostnameAndPort[1], 10, 64)
  140. if parseErr != nil {
  141. return "", fmt.Errorf("filer port parse error: %v", parseErr)
  142. }
  143. filerGrpcPort := int(filerPort) + 10000
  144. return fmt.Sprintf("%s:%d", hostnameAndPort[0], filerGrpcPort), nil
  145. }