grpc v1.34.1 的客户端负载平衡,nameResolverFactory 已弃用

Nit*_*waj 5 java load-balancing grpc grpc-java

我将 grpc v1.34.1 与 Java 结合使用,很难配置客户端负载平衡,因为该版本中不推荐使用某些方法。在早期版本中通过以下方式配置客户端负载平衡非常简单:

final ManagedChannel channel = ManagedChannelBuilder.forTarget(target)
        .nameResolverFactory(new DnsNameResolverProvider())  // this is on by default
        .loadBalancerFactory(RoundRobinLoadBalancerFactory.getInstance())
        .usePlaintext(true)
        .build();
Run Code Online (Sandbox Code Playgroud)

或者通过这个https://sultanov.dev/blog/grpc-client-side-load-balancing/

但是,没有任何可用于已弃用nameResolverFactory并删除 method的新版本的参考loadBalancerFactory

NameResolver.Factory nameResolverFactory = new MultiAddressNameResolverFactory(
        new InetSocketAddress("localhost", 50000),
        new InetSocketAddress("localhost", 50001),
        new InetSocketAddress("localhost", 50002)
);

channel = ManagedChannelBuilder.forTarget("localhost")
        .nameResolverFactory(nameResolverFactory)
        .defaultLoadBalancingPolicy("round_robin")
        .usePlaintext()
        .build();
Run Code Online (Sandbox Code Playgroud)

客户端负载平衡有效。但是,较新的 API 已弃用nameResolverFactory.

有人可以指出我nameResolverFactory在新版本中使用不同服务器(主机和端口)进行客户端负载平衡的替代方案吗?

Nit*_*waj 4

在查看 grpc-java 内部实现之后,我发现新版本接受对象的NameResolver.Factory方式略有不同。它被封装到了NameResolverProvider需要注册为default的地方NameResolverRegistry。下面分享了在新版本中执行此操作的示例代码:

NameResolverProvider nameResolverFactory = new MultiAddressNameResolverFactory(
                new InetSocketAddress("localhost", 50000),
                new InetSocketAddress("localhost", 50001),
                new InetSocketAddress("localhost", 50002)
        );

NameResolverRegistry nameResolverRegistry = NameResolverRegistry.getDefaultRegistry();
nameResolverRegistry.register(nameResolverFactory);
channel = ManagedChannelBuilder.forTarget("localhost")
          .defaultLoadBalancingPolicy("round_robin")
          .usePlaintext()
          .build();


public class MultiAddressNameResolverFactory extends NameResolverProvider {
    final List<EquivalentAddressGroup> addresses;

    MultiAddressNameResolverFactory(SocketAddress... addresses) {
        this.addresses = Arrays.stream(addresses)
                .map(EquivalentAddressGroup::new)
                .collect(Collectors.toList());
    }

    public NameResolver newNameResolver(URI notUsedUri, NameResolver.Args args) {
        return new NameResolver() {
            @Override
            public String getServiceAuthority() {
                return "fakeAuthority";
            }
            public void start(Listener2 listener) {
                listener.onResult(ResolutionResult.newBuilder().setAddresses(addresses).setAttributes(Attributes.EMPTY).build());
            }
            public void shutdown() {
            }
        };
    }

    @Override
    public String getDefaultScheme() {
        return "multiaddress";
    }

    @Override
    protected boolean isAvailable() {
        return true;
    }

    @Override
    protected int priority() {
        return 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

默认情况下,NameResolver.Factory 的自定义实现将由通道选取以连接到服务器。根据负载平衡策略,SocketAddress将选择一个连接到服务器。