GRPC 负载均衡实现

本文介绍了如何使用gRPC实现服务发现和负载均衡。通过配置本地文件启动时注册服务,利用RoundRobinLoadBalancerFactory实现轮询策略。同时探讨了通过NameResolverProvider和LocalNameResolver实现动态服务注册与发现,以及监听Zookeeper更新可用服务地址的方法。
摘要由CSDN通过智能技术生成

gRPC 是google开源的非常优秀的RPC框架,支持PYTHON/JAVA/PHP/GO/C/C++/C#/NODEJS/RUBY 等编程语言,在跨语言调用十分方便。
在产品环境,通常要部署多个RPC服务,已提高可用性,以及响应速度。但是
在负载均衡方面不如dubbo的组件那么丰富,但是其提供了服务发现的接口, 可以通过实现其接口,灵活实现负载均衡功能。
下面通过本地配置文件,启动时注册可用的服务,可以快速实现负载均衡功能。
grpc:
hosts: host1:8080,host2:8080

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();

forTarget 设置连接RPC服务的地址,比如"127.0.0.1:8080"
nameResolverFactory 服务发现
LocalNameResolverProvider 服务提供者
loadBalancerFactory 设置负载均衡策略
RoundRobinLoadBalancerFactory 轮询策略

nameResolverFactory 配置方式

GRPC client 通过loadBalancerFactory来设置负载均衡的策略,这里选择RoundRobinLoadBalancerFactory,即服务轮询策略。

通过nameResolverFactory配置地址服务的发现方式,通过NameResolverProvider来实现服务的注册与发现。

服务提供者类

// 需要实现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() {

}

通过以上配置, 在进行RPC调用的时候,会轮询选择注册的服务地址
添加新的可用服务节点需要更新配置文件


动态注册与发现


启动GRPC服务的同时,把服务的地址注册到zookeeper上
实现NameResolverstart 方法,监听zookeeper变化,实时更新可用地址列表

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北漂雨田

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值