我正在尝试为我的java服务器实现grpc客户端负载平衡。
一
server
在端口6565和另一个端口上运行
server
运行在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());
}
}
我的
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(new TempNameResolverProvider())
为了使全局名称解析能够工作,应用程序失败并出现以下错误-
警告:[Channel<1>:(银行服务)]解析名称失败。status=status{code=UNAVAILABLE,description=无法解析主机银行服务,cause=java.lang.RuntimeException:java.net.UnnknownHostException:银行服务:名称解析中的临时故障
位于io.grpc.internal.DnsNameResolver.resolveAddresses(DnsNameResolver.java:223)
位于io.grpc.internal.DnsNameResolver.doResolve(DnsNameResolve.java:282)
位于io.grpc.internal.DnsNameResolver$Resolve.run(DnsNameResolve.java:318)
位于java.base/java.util.concurrent.ThreadPoolExecutiator.runWorker(ThreadPoolExecutiator.java:1136)
位于java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
位于java.base/java.lang.Thread.run(Thread.java:833)
引起原因:java.net.UnnknownHostException:银行服务:名称解析临时失败
位于java.base/java.net.Inet6AddressImpl.lookupAllHostAddr(本机方法)
位于java.base/java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:52)
位于java.base/java.net.InetAddress$PlatformResolver.lookupByName(InetAddress.java:1048)
位于java.base/java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1638)
位于java.base/java.net.InetAddress$NameServiceAddresses.get(InetAddress.java:997)
位于java.base/java.net.InetAddress.getAllByName0(InetAddress.java:1628)
位于java.base/java.net.InetAddress.getAllByName(InetAddress.java:1494)
位于io.grpc.internal.DnsNameResolver$JdkAddressResolver.resolveAddress(DnsNameResolver.java:631)
位于io.grpc.internal.DnsNameResolver.resolveAddresses(DnsNameResolver.java:219)
…还有5个
}
出现错误:不可用:无法解析主机银行服务
UNAVAILABLE:无法解析主机银行服务
io.grpc.StatusRuntimeException:不可用:无法解析主机银行服务
在app//io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:262)
位于app//io.grpc.stub.ClientCalls.getUnchecked(ClientCalls.java:243)
位于app//io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:156)
访问app//com.raj.models.BankServiceGrpc$BankServiceBlockingStub.getBalance(BankServiceGrpc.java:284)
位于app//client.lb.ClientSideLoadBalancerTest.balanceTest(ClientSideLoad平衡器测试.java:39)
在java.base@18/jdk.internal.reflect.DirectMethodHandleAccessor.ioke(DirectMethodHandleAccessor.java:104)
在java.base@18/java.lang.reflect.Method.ioke(Method.java:577)
位于app//org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
位于app//org.junit.jupiter.engine.execulation.MethodInvocation.prough(MethodInvocation.java:60)
位于app//org.junit.jupiter.engine.exexecution.InvocationInterceptorChain$ValidatingInvocation.procent(InvocationIntersectorChain.java:131)
位于app//org.junit.jupiter.engine.exextension.TimeoutExtension.incept(TimeoutExtension.java:149)
位于app//org.junit.jupiter.engine.exextension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
位于app//org.junit.jupiter.engine.extension.TimeoutExtension.enterceptTestMethod(TimeoutExtension.java:84)
位于app//org.junit.jupiter.engine.execulation.ExecutableInvoker$ReflectiveInterceptorCallLambda$ofVoidMethod$0(ExecutiableInvoker.java:115)
位于app//org.junit.jupiter.engine.execulation.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
位于app//org.junit.jupiter.engine.exexecution.InvocationInterceptorChain$InterceptedInvocation.prough(InvocationIntersectorChain.java:106)
位于app//org.junit.jupiter.engine.execulation.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
位于app//org.junit.jupiter.engine.execulation.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
位于app//org.junit.jupiter.engine.execulation.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
位于app//org.junit.jupiter.engine.execulation.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
位于app//org.junit.jupiter.engine.execulation.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
位于app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptorLambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
位于app//org.junit.platform.engine.support.histrared.SthrowableCollector.execute(ThrowableCollector.java:73)
位于app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
位于app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
位于app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
位于app//org.junit.platform.engine.support.histrared.NodeTestTaskLambda$executeSecurive$6(NodeTestTask.java:151)
位于app//org.junit.platform.engine.support.histrared.SthrowableCollector.execute(ThrowableCollector.java:73)
位于app//org.junit.platform.engine.support.histrared.NodeTestTaskLambda$executeSecurive$8(NodeTestTask.java:141)
位于app//org.junit.platform.engine.support.histrared.Node.around(Node.java:137)
位于app//org.junit.platform.engine.support.histrared.NodeTestTaskLambda$executeSecurive$9(NodeTestTask.java:139)
位于app//org.junit.platform.engine.support.histrared.SthrowableCollector.execute(ThrowableCollector.java:73)
位于app//org.junit.platform.engine.support.histrared.NodeTestTask.executeSecurively(NodeTestTask.java:138)
在app//org.junit.platform.engine.support.histrared.NodeTestTask.execute(NodeTestTask.java:95)
在java.base@18/java.util.ArrayList.forEach(ArrayList.java:1511)
位于app//org.junit.platform.engine.support.histrared.SameThreadHierarchicalTestExecutiorService.invokeAll(SameThreadHierarchialTestExecutiorServices.java:41)
位于app//org.junit.platform.engine.support.histrared.NodeTestTaskLambda$executeSecurive$6(NodeTestTask.java:155)
位于app//org.junit.platform.engine.support.histrared.SthrowableCollector.execute(ThrowableCollector.java:73)
位于app//org.junit.platform.engine.support.histrared.NodeTestTaskLambda$executeSecurive$8(NodeTestTask.java:141)
位于app//org.junit.platform.engine.support.histrared.Node.around(Node.java:137)
位于app//org.junit.platform.engine.support.histrared.NodeTestTaskLambda$executeSecurive$9(NodeTestTask.java:139)
位于app//org.junit.platform.engine.support.histrared.SthrowableCollector.execute(ThrowableCollector.java:73)
位于app//org.junit.platform.engine.support.histrared.NodeTestTask.executeSecurively(NodeTestTask.java:138)
在app//org.junit.platform.engine.support.histrared.NodeTestTask.execute(NodeTestTask.java:95)
在java.base@18/java.util.ArrayList.forEach(ArrayList.java:1511)
位于app//org.junit.platform.engine.support.histrared.SameThreadHierarchicalTestExecutiorService.invokeAll(SameThreadHierarchialTestExecutiorServices.java:41)
位于app//org.junit.platform.engine.support.histrared.NodeTestTaskLambda$executeSecurive$6(NodeTestTask.java:155)
位于app//org.junit.platform.engine.support.histrared.SthrowableCollector.execute(ThrowableCollector.java:73)
位于app//org.junit.platform.engine.support.histrared.NodeTestTaskLambda$executeSecurive$8(NodeTestTask.java:141)
位于app//org.junit.platform.engine.support.histrared.Node.around(Node.java:137)
位于app//org.junit.platform.engine.support.histrared.NodeTestTaskLambda$executeSecurive$9(NodeTestTask.java:139)
位于app//org.junit.platform.engine.support.histrared.SthrowableCollector.execute(ThrowableCollector.java:73)
位于app//org.junit.platform.engine.support.histrared.NodeTestTask.executeSecurively(NodeTestTask.java:138)
在app//org.junit.platform.engine.support.histrared.NodeTestTask.execute(NodeTestTask.java:95)
位于app//org.junit.platform.engine.support.histrared.SameThreadHierarchicalTestExecutiorService.submit(SameThreadHierarchialTestExecutiorServices.java:35)
位于app//org.junit.platform.engine.support.hhierarchicalTestExecution.execute(HierarchicalTestExecution.java:57)
位于app//org.junit.platform.engine.support.hhierarchicalTestEngine.exexecute(HierarchicalTestEngine.java:54)
位于org.junit.platform.selauncher.core.EngineExecutionOrchestrator.exexecute(EngineExecutionOrhestrator.java:108)
位于org.junit.platform.selauncher.core.EngineExecutionOrchestrator.exexecute(EngineExecutionOrhestrator.java:88)
位于org.junit.platform.selauncher.core.EngineExecutionOrchestratorLambda$execute$0(EngineExecutionOrhestrator.java:54)
位于org.junit.platform.selauncher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrhestrator.java:67)
位于org.junit.platform.selauncher.core.EngineExecutionOrchestrator.exexecute(EngineExecutionOrhestrator.java:52)
位于org.junit.platform.selauncher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
位于org.junit.platform.selauncher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
网址:org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasss(JUnitPlatformTestClassProcessor.java:99)
网址:org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
网址:org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
网址:org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
在java.base@18/jdk.internal.reflect.DirectMethodHandleAccessor.ioke(DirectMethodHandleAccessor.java:104)
在java.base@18/java.lang.reflect.Method.ioke(Method.java:577)
网址:org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDisptch.java:36)
网址:org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDisptch.java:24)
位于org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
位于org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
位于jdk.proxy1/jdk.proxy1.$Proxy2.stop(未知源)
网址:org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
位于org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintaineThreadName(TestWorker.java:129)
网址:org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
网址:org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
位于org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
网址:org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoader worker.java:133)
网址:org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoader worker.java:71)
位于app//worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorker Main.java:69)
位于app//worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorker main.java:74)
引起原因:java.lang.RuntimeException:java.net.UnnknownHostException:银行服务:名称解析临时失败
位于io.grpc.internal.DnsNameResolver.resolveAddresses(DnsNameResolver.java:223)
位于io.grpc.internal.DnsNameResolver.doResolve(DnsNameResolve.java:282)
位于io.grpc.internal.DnsNameResolver$Resolve.run(DnsNameResolve.java:318)
位于java.base/java.util.concurrent.ThreadPoolExecutiator.runWorker(ThreadPoolExecutiator.java:1136)
位于java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
位于java.base/java.lang.Thread.run(Thread.java:833)
引起原因:java.net.UnnknownHostException:银行服务:名称解析临时失败
位于java.base/java.net.Inet6AddressImpl.lookupAllHostAddr(本机方法)
位于java.base/java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:52)
位于java.base/java.net.InetAddress$PlatformResolver.lookupByName(InetAddress.java:1048)
位于java.base/java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1638)
位于java.base/java.net.InetAddress$NameServiceAddresses.get(InetAddress.java:997)
位于java.base/java.net.InetAddress.getAllByName0(InetAddress.java:1628)
位于java.base/java.net.InetAddress.getAllByName(InetAddress.java:1494)
位于io.grpc.internal.DnsNameResolver$JdkAddressResolver.resolveAddress(DnsNameResolver.java:631)
位于io.grpc.internal.DnsNameResolver.resolveAddresses(DnsNameResolver.java:219)
…还有5个
我不知道为什么全局服务名称解析不起作用。我的代码出了什么问题?
github上的完整代码是
here
提前谢谢。