golang-im聊天
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

65 lines
1.4 KiB

  1. package picker
  2. import (
  3. "context"
  4. "errors"
  5. "gim/pkg/logger"
  6. "go.uber.org/zap"
  7. "google.golang.org/grpc/balancer"
  8. "google.golang.org/grpc/balancer/base"
  9. )
  10. // AddrPickerName 实现指定地址调用的RPC调用
  11. const AddrPickerName = "addr"
  12. type addrKey struct{}
  13. var ErrNoSubConnSelect = errors.New("no sub conn select")
  14. func init() {
  15. balancer.Register(newBuilder())
  16. }
  17. func ContextWithAddr(ctx context.Context, addr string) context.Context {
  18. return context.WithValue(ctx, addrKey{}, addr)
  19. }
  20. type addrPickerBuilder struct{}
  21. func newBuilder() balancer.Builder {
  22. return base.NewBalancerBuilder(AddrPickerName, &addrPickerBuilder{}, base.Config{HealthCheck: true})
  23. }
  24. func (*addrPickerBuilder) Build(info base.PickerBuildInfo) balancer.Picker {
  25. if len(info.ReadySCs) == 0 {
  26. return base.NewErrPicker(balancer.ErrNoSubConnAvailable)
  27. }
  28. subConns := make(map[string]balancer.SubConn, len(info.ReadySCs))
  29. for k, sc := range info.ReadySCs {
  30. subConns[sc.Address.Addr] = k
  31. }
  32. return &addrPicker{
  33. subConnes: subConns,
  34. }
  35. }
  36. type addrPicker struct {
  37. subConnes map[string]balancer.SubConn
  38. }
  39. func (p *addrPicker) Pick(info balancer.PickInfo) (balancer.PickResult, error) {
  40. pr := balancer.PickResult{}
  41. address := info.Ctx.Value(addrKey{}).(string)
  42. sc, ok := p.subConnes[address]
  43. if !ok {
  44. logger.Logger.Error("Pick error", zap.String("address", address), zap.Any("subConnes", p.subConnes))
  45. return pr, ErrNoSubConnSelect
  46. }
  47. pr.SubConn = sc
  48. return pr, nil
  49. }