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



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

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

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

但是,对于已弃用nameResolverFactory并删除方法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();

客户端负载平衡工作。但是,较新的API已经否决了nameResolverFactory

有人能告诉我新版本中nameResolverFactory的替代方案吗?该方案用于不同服务器(主机和端口(的客户端负载平衡?

在完成grpc-java内部实现后,我发现新版本接受NameResolver.Factory对象的方式略有不同。它被封装到NameResolverProvider,需要注册到默认的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;
}
}

默认情况下,是NameResolver的自定义实现。工厂将通过通道连接到服务器。根据负载平衡策略,将拾取一个SocketAddress来连接到服务器。

只有一件事要添加到Nitish Bhardwaj的答案中,对我来说是方法

int priority()

无法使用值0,因为io.grpc.internal.DnsNameResolverProvider的值为5,而io.grpc.nety.shaded.io.grpc.nety.UdsNameResolverProvider的值为3,在我的情况下,它没有设置我的自定义NameResolverrovider,我可以通过将方法priority()重写为大于5的值来修复它,使其自动获取我的自定义名称ResolverProvider。

完整代码:

package iam.mfa.grpc.client.resolvers;
import java.net.URI;
import java.util.List;
import io.grpc.Attributes;
import io.grpc.EquivalentAddressGroup;
import io.grpc.NameResolver;
import io.grpc.NameResolverProvider;
import lombok.RequiredArgsConstructor;
/**
* @author HAMMA FATAKA (mfataka@monetplus.cz)
* @project gRPC
* @date 07.04.2023 21:54
*/
@RequiredArgsConstructor(staticName = "of")
public class MultipleAddressNameResolverProvider extends NameResolverProvider {
private final List<EquivalentAddressGroup> addresses;
@Override
public NameResolver newNameResolver(URI targetUri, NameResolver.Args args) {
return new NameResolver() {
@Override
public String getServiceAuthority() {
return "noAuthority";
}

@Override
public void start(Listener2 listener) {
listener.onResult(ResolutionResult.newBuilder().setAddresses(addresses).setAttributes(Attributes.EMPTY).build());
}
@Override
public void shutdown() {
}
};
}
@Override
public String getDefaultScheme() {
return "multiTarget";
}
@Override
protected boolean isAvailable() {
return true;
}
@Override
protected int priority() {
return 6;
}
}

客户端配置:


package iam.mfa.grpc.client.config;
import java.net.InetSocketAddress;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import iam.mfa.grpc.client.resolvers.MultipleAddressNameResolver;
import io.grpc.EquivalentAddressGroup;
import io.grpc.ManagedChannel;
import io.grpc.NameResolverRegistry;
import io.grpc.internal.DnsNameResolver;
import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder;
/**
* @author HAMMA FATAKA (mfataka@monetplus.cz)
* @project gRPC
* @date 26.02.2023 16:03
*/
@Configuration
public class ClientConfig {
@Value("#{'${grpc.client.targets}'.split(',')}")
private List<String> targets;

@PostConstruct
public void initNameResolver(){
final var addresses = targets.stream()
.map(target -> {
final var splitTarget = target.split(":");
final var host = splitTarget[0];
final var port = splitTarget[1];
return new EquivalentAddressGroup(new InetSocketAddress(host, Integer.parseInt(port)));
})
.toList();
final var nameResolverFactory = MultipleAddressNameResolver.of(addresses);
NameResolverRegistry.getDefaultRegistry().register(nameResolverFactory);
}

@Bean
public ManagedChannel channel() {
return NettyChannelBuilder.forTarget("localhost")
.defaultLoadBalancingPolicy("round_robin")
.usePlaintext()
.build();
}
}

希望这能有所帮助。

相关内容

  • 没有找到相关文章

最新更新