我正在尝试为我的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上的完整代码
提前感谢。
我测试了您的代码,发现了两个问题:
>
自定义 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检查了它。我们在不同的主机和同一台主机上进行了检查,但这两种情