当前位置: 首页 > 知识库问答 >
问题:

grpc客户端负载平衡失败,错误为:警告:[通道< 1>: ()]无法解析名称

谷彦君
2023-03-14

我正在尝试为我的java服务器实现grpc客户端负载平衡。一台服务器运行在端口6565上,另一台服务器运行在端口7575上。两台服务器的代码是相同的,但端口除外。

现在我想为这些服务器实现客户端负载平衡。

我的ServiceRegistry类如下-

import io.grpc.EquivalentAddressGroup;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class ServiceRegistry {

    private static final Map<String, List<EquivalentAddressGroup>> MAP = new HashMap<>();

    public static  void register(String service, List<String> instances) {
        MAP.put(service, toEquivAddrGroup(instances));
    }

    public static List<EquivalentAddressGroup> getInstances(String service) {
        return MAP.get(service);
    }
    private static List<EquivalentAddressGroup> toEquivAddrGroup(List<String> instances) {
        return instances.stream().map(i -> i.split(":"))
                .map(a -> new InetSocketAddress(a[0], Integer.parseInt(a[1])))
                .map(EquivalentAddressGroup::new).collect(Collectors.toList());
    }
}

我的< code>TempNameResolver类如下所示

import io.grpc.EquivalentAddressGroup;
import io.grpc.NameResolver;
import java.util.List;

public class TempNameResolver extends NameResolver {

    private final String service;

    public TempNameResolver(String service) {
        this.service = service;
    }

    @Override
    public String getServiceAuthority() {
        return "temp";
    }

    @Override
    public void shutdown() {

    }

    @Override
    public void start(Listener2 listener) {
        List<EquivalentAddressGroup> addrGroups = ServiceRegistry.getInstances(this.service);
        ResolutionResult resolutionResult = ResolutionResult.newBuilder().setAddresses(addrGroups).build();
        listener.onResult(resolutionResult);
    }
}

TempNameResolverProvider类是-

import io.grpc.NameResolver;
import io.grpc.NameResolverProvider;
import java.net.URI;

public class TempNameResolverProvider extends NameResolverProvider {

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

    @Override
    protected int priority() {
        return 5;
    }

    @Override
    public NameResolver newNameResolver(URI targetUri, NameResolver.Args args) {
        System.out.println("Looking for service " + targetUri);
        return new TempNameResolver(targetUri.toString());
    }

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

我的客户代码是

import client.DepositStreamObserver;
import com.raj.models.*;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.NameResolverRegistry;
import io.grpc.stub.StreamObserver;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class ClientSideLoadBalancerTest {

    private BankServiceGrpc.BankServiceBlockingStub bs;
    private BankServiceGrpc.BankServiceStub bss;

    @BeforeAll
    public void setUp() {
        ServiceRegistry.register("bank-service", Arrays.asList("localhost:6565", "localhost:7575"));
        NameResolverRegistry.getDefaultRegistry().register(new TempNameResolverProvider());
        ManagedChannel mc = ManagedChannelBuilder

                //.forAddress("localhost", 8585)
                .forTarget("bank-service")
                .nameResolverFactory(new TempNameResolverProvider())
                .usePlaintext()
                .build();
        this.bs = BankServiceGrpc.newBlockingStub(mc);
        this.bss = BankServiceGrpc.newStub(mc);
    }

    @Test
    public void balanceTest() {
        for (int i = 0; i < 10; i++) {
            BalanceCheckRequest bcr = BalanceCheckRequest.newBuilder().setAccountNumber(i).build();
            Balance b = this.bs.getBalance(bcr);
            System.out.println("balance received " + b.getAmount());
        }
    }

上面的代码工作正常。当我删除或注释已弃用的代码 .nameResolverFactory(新的 TempName重新解决者提供程序())以便全局名称解析将起作用时,应用程序失败并出现以下错误 -

警告:[频道

我不知道为什么全局服务名称解析不起作用。我的代码出了什么问题?

这里是github上的完整代码

提前感谢。


共有1个答案

浦琪
2023-03-14
匿名用户

我测试了您的代码,发现了两个问题:

>

  • 自定义 NameResolver 优先级需要比 5 更高的优先级,因为默认 dns 名称解析程序优先级为 5,如果具有相同的优先级,则默认情况下将使用 dns。优先级可以是 0-10。

    在< code > service registry # register 中注册服务时需要处理方案前缀,将方案前缀< code>dns:///添加到authority < code > bank-service 中。或者在< code>getInstances时删除前缀,因为在创建< code>NameResolver时,将使用scheme作为前缀。< code>bank-service将注册为< code>dns:///bank-service

    我建议在使用注册中心(如领事馆等)时,使用独立的方案,避免与其他方案相同。

    如果你对grpc-java有更多要求,你可以参考回购https://github.com/helloworlde/grpc-java-sample了解更多细节。

  •  类似资料:
    • 我在kubernetes pods中使用带有Python的gRPC作为客户端/服务器......我希望能够启动多个相同类型的pod(gRPC服务器)并让客户端(随机)连接到它们。 我调度了10个服务器吊舱,并设置了一个“服务”来瞄准它们。然后,在客户端,我连接到服务的DNS名称——这意味着kubernetes应该进行负载平衡,并将我指向一个随机服务器pod。实际上,客户机调用gRPC函数(这很有效

    • Ribbon是一个客户端负载均衡器,它可以很好地控制HTTP和TCP客户端的行为。Feign已经使用Ribbon,所以如果您使用@FeignClient,则本节也适用。 Ribbon中的中心概念是指定客户端的概念。每个负载平衡器是组合的组合的一部分,它们一起工作以根据需要联系远程服务器,并且集合具有您将其作为应用程序开发人员(例如使用@FeignClient注释)的名称。Spring Cloud使

    • 在花了几个小时阅读Http客户机文档和源代码后,我决定在这里寻求帮助。 我有一个使用循环算法的负载均衡服务器

    • 使用Cloud Foundry功能“Polyglot”集成服务发现和通过内部路由在服务容器之间直接通信,负载平衡如何工作?Cloud Foundry是否负责负载平衡?有没有一种方法可以利用客户端负载平衡,比如在这种支持Polyglot的通信之上使用Ribbon?

    • 我一直在使用,Consul作为服务注册表,Ribbon作为负载均衡器。我目前正在使用spring-boot 2.3.10。释放。 我真的很喜欢spring-blod-feign-继承支持,在我的理解中,它允许我编写服务器端和客户端使用的单个接口。 https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.

    • 我们正在运行“helloworld”示例https://grpc.io/docs/quickstart/cpp.html#update-a-grpc-service,我们收到以下错误: 14:连接失败 迎宾员收到:RPC失败。 服务器和客户端正在监听:。服务器正在运行。首先,我们在服务器上只收到一个数据包,客户端崩溃,我用tcpdump检查了它。我们在不同的主机和同一台主机上进行了检查,但这两种情