原理:


resolver解析地址,然后获取出 解析后的 resolveConnect;

调用 updateResolveStatus

然后 根据负载均衡 设置,生成负载均衡器;

负载均衡器内负责创建子链接;

子链接创建完后,将子链接传给picker管理,然后更新主链接的状态;

使用步骤:

  1. 定义自己的resolver
  2. resolve出相应的地址,传给负载均衡器builder
  3. 负载均衡器builder创建连接,传给picker

使用方法:

  1. const (
  2. exampleScheme = "example"
  3. exampleServiceName = "lb.example.grpc.io"
  4. )
  5. var addrs = []string{"localhost:50051", "localhost:50052"}
  6. func callUnaryEcho(c ecpb.EchoClient, message string) {
  7. ctx, cancel := context.WithTimeout(context.Background(), time.Second)
  8. defer cancel()
  9. r, err := c.UnaryEcho(ctx, &ecpb.EchoRequest{Message: message})
  10. if err != nil {
  11. log.Fatalf("could not greet: %v", err)
  12. }
  13. fmt.Println(r.Message)
  14. }
  15. func makeRPCs(cc *grpc.ClientConn, n int) {
  16. hwc := ecpb.NewEchoClient(cc)
  17. for i := 0; i < n; i++ {
  18. callUnaryEcho(hwc, "this is examples/load_balancing")
  19. }
  20. }
  21. func main() {
  22. pickfirstConn, err := grpc.Dial(
  23. fmt.Sprintf("%s:///%s", exampleScheme, exampleServiceName),
  24. // grpc.WithBalancerName("pick_first"), // "pick_first" is the default, so this DialOption is not necessary.
  25. grpc.WithInsecure(),
  26. grpc.WithBlock(),
  27. )
  28. if err != nil {
  29. log.Fatalf("did not connect: %v", err)
  30. }
  31. defer pickfirstConn.Close()
  32. fmt.Println("--- calling helloworld.Greeter/SayHello with pick_first ---")
  33. makeRPCs(pickfirstConn, 10)
  34. fmt.Println()
  35. // Make another ClientConn with round_robin policy.
  36. roundrobinConn, err := grpc.Dial(
  37. fmt.Sprintf("%s:///%s", exampleScheme, exampleServiceName),
  38. grpc.WithBalancerName("round_robin"), // This sets the initial balancing policy.
  39. grpc.WithInsecure(),
  40. grpc.WithBlock(),
  41. )
  42. if err != nil {
  43. log.Fatalf("did not connect: %v", err)
  44. }
  45. defer roundrobinConn.Close()
  46. fmt.Println("--- calling helloworld.Greeter/SayHello with round_robin ---")
  47. makeRPCs(roundrobinConn, 10)
  48. }
  49. // Following is an example name resolver implementation. Read the name
  50. // resolution example to learn more about it.
  51. type exampleResolverBuilder struct{}
  52. func (*exampleResolverBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
  53. r := &exampleResolver{
  54. target: target,
  55. cc: cc,
  56. addrsStore: map[string][]string{
  57. exampleServiceName: addrs,
  58. },
  59. }
  60. r.start()
  61. return r, nil
  62. }
  63. func (*exampleResolverBuilder) Scheme() string { return exampleScheme }
  64. type exampleResolver struct {
  65. target resolver.Target
  66. cc resolver.ClientConn
  67. addrsStore map[string][]string
  68. }
  69. func (r *exampleResolver) start() {
  70. addrStrs := r.addrsStore[r.target.Endpoint]
  71. addrs := make([]resolver.Address, len(addrStrs))
  72. for i, s := range addrStrs {
  73. addrs[i] = resolver.Address{Addr: s}
  74. }
  75. r.cc.UpdateState(resolver.State{Addresses: addrs})
  76. }
  77. func (*exampleResolver) ResolveNow(o resolver.ResolveNowOptions) {}
  78. func (*exampleResolver) Close() {}
  79. func init() {
  80. resolver.Register(&exampleResolverBuilder{})
  81. }