導讀
gRPC 是google開源的很是優秀的RPC框架,支持PYTHON/JAVA/PHP/GO/C/C++/C#/NODEJS/RUBY 等編程語言,在跨語言調用十分方便。編程
在產品環境,一般要部署多個RPC服務,已提升可用性,以及響應速度。可是 在負載均衡方面不如dubbo的組件那麼豐富,可是其提供了服務發現的接口, 能夠經過實現其接口,靈活實現負載均衡功能。bash
下面經過本地配置文件,啓動時註冊可用的服務,能夠快速實現負載均衡功能。負載均衡
grpc:
hosts: host1:8080,host2:8080
複製代碼
GRPC channel 建立
ManagedChannelBuilder
// 設置鏈接的目標地址
.forTarget("local")
// 設置地址服務
.nameResolverFactory(new LocalNameResolverProvider(configInterface))
.enableRetry()
.maxRetryAttempts(5)
.keepAliveTime(5, TimeUnit.MINUTES)
.keepAliveWithoutCalls(true)
.keepAliveTimeout(10, TimeUnit.MINUTES)
.idleTimeout(24, TimeUnit.HOURS)
// 設置輪詢策略
.loadBalancerFactory(RoundRobinLoadBalancerFactory.getInstance())
.usePlaintext()
.build();
複製代碼
nameResolverFactory 配置方式
GRPC client 經過loadBalancerFactory
來設置負載均衡的策略,這裏選擇RoundRobinLoadBalancerFactory
,即服務輪詢策略。框架
經過nameResolverFactory
配置地址服務的發現方式,經過NameResolverProvider
來實現服務的註冊與發現。socket
服務提供者類編程語言
// 須要實現NameResolverProvider抽象類中的相關方法
public class LocalNameResolverProvider extends NameResolverProvider {
private final ConfigInterface configInterface;
@Inject
public LocalNameResolverProvider(ConfigInterface configInterface) {
this.configInterface = configInterface;
}
// 服務是否可用
@Override
protected boolean isAvailable() {
return true;
}
// 優先級默認5
@Override
protected int priority() {
return 5;
}
// 服務發現類
@Nullable
@Override
public NameResolver newNameResolver(URI targetUri, Attributes params) {
return new LocalNameResolver(configInterface);
}
// 服務協議
@Override
public String getDefaultScheme() {
return "local";
}
}
複製代碼
public class LocalNameResolver extends NameResolver {
private final ConfigInterface configInterface;
@Inject
public LocalNameResolver(ConfigInterface configInterface) {
this.configInterface = configInterface;
}
@Override
public String getServiceAuthority() {
return "none";
}
// 配置可用服務,RPC在調用的時候,輪詢選擇這裏配置的可用的服務地址列表
@Override
public void start(Listener listener) {
LogUtils.info("LocalNameResolver start ...");
ArrayList<EquivalentAddressGroup> addressGroups = new ArrayList<EquivalentAddressGroup>();
// 獲取rpc地址的配置列表
// 地址格式 host1:8080,host2:8081
Map<String, Object> config = (Map<String, Object>) this.configInterface.getRpcConfig().get("grpc");
String[] hosts = config.get("hosts").toString().split(",");
for (String host : hosts) {
if (host.trim().length() > 0) {
String[] address = host.split(":");
List<SocketAddress> socketAddresses = new ArrayList<SocketAddress>();
socketAddresses.add(new InetSocketAddress(address[0], Integer.parseInt(address[1])));
addressGroups.add(new EquivalentAddressGroup(socketAddresses));
}
}
listener.onAddresses(addressGroups, Attributes.EMPTY);
}
@Override
public void shutdown() {
}
}
複製代碼
動態註冊與發現
NameResolver
start 方法,監聽zookeeper變化,實時更新可用地址列表