返回介绍

Channel Builder设计与代码实现 - 类AbstractManagedChannelImplBuilder

发布于 2020-09-14 13:14:41 字数 17387 浏览 1598 评论 0 收藏 0

类AbstractManagedChannelImplBuilder 是 channel builder的基类。

类定义

  1. package io.grpc.internal;
  2. public abstract class AbstractManagedChannelImplBuilder
  3. <T extends AbstractManagedChannelImplBuilder<T>> extends ManagedChannelBuilder<T> {}

注: package从 ManagedChannelBuilder 的 io.grpc 变成 io.grpc.internal 了。

类属性和方法实现

executor

  1. @Nullable
  2. private Executor executor;
  3. @Override
  4. public final T directExecutor() {
  5. return executor(MoreExecutors.directExecutor());
  6. }
  7. @Override
  8. public final T executor(Executor executor) {
  9. this.executor = executor;
  10. return thisT();
  11. }

executor(Executor executor)方法只是一个简单赋值,而directExecutor()则调用 MoreExecutors.directExecutor() 方法得到 direct executor。

executor 在 build() 方法中被传递给新创建的 ManagedChannelImpl() 实例。

访问地址相关

和访问地址相关的三个属性:

  1. target
  2. directServerAddress
  3. nameResolverFactory
  1. private final String target;
  2. @Nullable
  3. private final SocketAddress directServerAddress;
  4. @Nullable
  5. private NameResolver.Factory nameResolverFactory;

使用target来构造实例:

  1. protected AbstractManagedChannelImplBuilder(String target) {
  2. this.target = Preconditions.checkNotNull(target);
  3. // directServerAddress 设置为null
  4. this.directServerAddress = null;
  5. }

使用directServerAddress来构造实例:

  1. private static final String DIRECT_ADDRESS_SCHEME = "directaddress";
  2. protected AbstractManagedChannelImplBuilder(SocketAddress directServerAddress, String authority) {
  3. // target被设置为 directaddress:///directServerAddress
  4. this.target = makeTargetStringForDirectAddress(directServerAddress);
  5. this.directServerAddress = directServerAddress;
  6. // nameResolverFactory 使用 DirectAddressNameResolverFactory
  7. this.nameResolverFactory = new DirectAddressNameResolverFactory(directServerAddress, authority);
  8. }
  9. @VisibleForTesting
  10. static String makeTargetStringForDirectAddress(SocketAddress address) {
  11. try {
  12. // "directaddress:///address"
  13. return new URI(DIRECT_ADDRESS_SCHEME, "", "/" + address, null).toString();
  14. } catch (URISyntaxException e) {
  15. // It should not happen.
  16. throw new RuntimeException(e);
  17. }
  18. }

设置nameResolverFactory的函数,注意NameResolverFactory和directServerAddress是互斥的:

  1. @Override
  2. public final T nameResolverFactory(NameResolver.Factory resolverFactory) {
  3. // 如果设置directServerAddress,就不能再使用NameResolverFactory
  4. Preconditions.checkState(directServerAddress == null,
  5. "directServerAddress is set (%s), which forbids the use of NameResolverFactory",
  6. directServerAddress);
  7. this.nameResolverFactory = resolverFactory;
  8. return thisT();
  9. }

target 和 nameResolverFactory 在 build() 方法中被传递给新创建的 ManagedChannelImpl() 实例。

user agent

  1. @Override
  2. @Nullable
  3. private String userAgent;
  4. public final T userAgent(String userAgent) {
  5. this.userAgent = userAgent;
  6. return thisT();
  7. }

user agent 只是做了一个简单赋值,然后在 build() 方法中被传递给新创建的 ManagedChannelImpl() 实例。

authorityOverride

  1. @Nullable
  2. private String authorityOverride;
  3. @Override
  4. public final T overrideAuthority(String authority) {
  5. this.authorityOverride = checkAuthority(authority);
  6. return thisT();
  7. }

简单做了个赋值,然后在build()方法中,在构建AuthorityOverridingTransportFactory时使用:

  1. @Override
  2. public ManagedChannelImpl build() {
  3. ClientTransportFactory transportFactory = buildTransportFactory();
  4. if (authorityOverride != null) {
  5. transportFactory = new AuthorityOverridingTransportFactory(
  6. transportFactory, authorityOverride);
  7. }
  8. ......
  9. return new ManagedChannelImpl(
  10. ......,transportFactory,......);
  11. }

通过buildTransportFactory()方法得到ClientTransportFactory,然后传递给ManagedChannelImpl的构造函数。为了覆盖原来的Authority,实现了一个AuthorityOverridingTransportFactory内部类,以装饰模式包裹了一个ClientTransportFactory的实例,然后将请求都代理给这个包装的ClientTransportFactory实例:

  1. private static class AuthorityOverridingTransportFactory implements ClientTransportFactory {
  2. final ClientTransportFactory factory;
  3. final String authorityOverride;
  4. AuthorityOverridingTransportFactory(
  5. ClientTransportFactory factory, String authorityOverride) {
  6. this.factory = Preconditions.checkNotNull(factory, "factory should not be null");
  7. this.authorityOverride = Preconditions.checkNotNull(
  8. authorityOverride, "authorityOverride should not be null");
  9. }
  10. @Override
  11. public ConnectionClientTransport newClientTransport(SocketAddress serverAddress,
  12. String authority, @Nullable String userAgent) {
  13. // 在这里做覆盖,用authorityOverride覆盖原有的authority
  14. return factory.newClientTransport(serverAddress, authorityOverride, userAgent);
  15. }
  16. ......

在newClientTransport()方法中, 前面传递进来的 authorityOverride 派上用场了。

注: 之前AuthorityOverridingTransportFactory的实现有点小问题,我提交了一个pull request给grpc,后来被采纳,现在这里的代码已经合并到master,看着真亲切 :): https://github.com/grpc/grpc-java/pull/1666

nameResolverFactory

  1. @Nullable
  2. private NameResolver.Factory nameResolverFactory;
  3. protected AbstractManagedChannelImplBuilder(SocketAddress directServerAddress, String authority) {
  4. ......
  5. this.nameResolverFactory = new DirectAddressNameResolverFactory(directServerAddress, authority);
  6. }
  7. @Override
  8. public final T nameResolverFactory(NameResolver.Factory resolverFactory) {
  9. Preconditions.checkState(directServerAddress == null,
  10. "directServerAddress is set (%s), which forbids the use of NameResolverFactory",
  11. directServerAddress);
  12. this.nameResolverFactory = resolverFactory;
  13. return thisT();
  14. }

如前所述,如果设置了directServerAddress,则nameResolverFactory自动设置为 DirectAddressNameResolverFactory 。而且不能再设置 nameResolverFactory 。

nameResolverFactory在build()方法中使用,有一个null的检查,如果 nameResolverFactory 有设置则使用 nameResolverFactory, 否则使用默认的 NameResolverProvider.asFactory():

  1. @Override
  2. public ManagedChannelImpl build() {
  3. ......
  4. NameResolver.Factory nameResolverFactory = this.nameResolverFactory;
  5. if (nameResolverFactory == null) {
  6. nameResolverFactory = NameResolverProvider.asFactory();
  7. }
  8. return new ManagedChannelImpl(
  9. ......,
  10. nameResolverFactory,
  11. getNameResolverParams(),
  12. ......);
  13. }

注:这里的NameResolverProvider.asFactory()看不懂……

额外的getNameResolverParams()用来给子类使用(以override的方式),可以传递更多参数给 NameResolver.Factory.newNameResolver() 方法。默认实现只是返回一个Attributes.EMPTY

  1. protected Attributes getNameResolverParams() {
  2. return Attributes.EMPTY;
  3. }

loadBalancerFactory

  1. @Nullable
  2. private LoadBalancer.Factory loadBalancerFactory;
  3. @Override
  4. public final T loadBalancerFactory(LoadBalancer.Factory loadBalancerFactory) {
  5. Preconditions.checkState(directServerAddress == null,
  6. "directServerAddress is set (%s), which forbids the use of LoadBalancerFactory",
  7. directServerAddress);
  8. this.loadBalancerFactory = loadBalancerFactory;
  9. return thisT();
  10. }
  11. public ManagedChannelImpl build() {
  12. return new ManagedChannelImpl(
  13. ......,
  14. firstNonNull(loadBalancerFactory, DummyLoadBalancerFactory.getInstance()),
  15. ......);
  16. }

和 nameResolverFactory 的使用非常类似,同样是 directServerAddress 设置后不能再用,使用的方式也是在build()中检查是否有设置,如果没有设置则默认使用 DummyLoadBalancerFactory 。

decompressorRegistry 和 compressorRegistry

  1. public ManagedChannelImpl build() {
  2. return new ManagedChannelImpl(
  3. ......,
  4. firstNonNull(decompressorRegistry, DecompressorRegistry.getDefaultInstance()),
  5. firstNonNull(compressorRegistry, CompressorRegistry.getDefaultInstance()),
  6. ......);
  7. }

decompressorRegistry 和 compressorRegistry 基本就是个简单设置+ 在build()方法中传递给ManagedChannelImpl(),如果没有设置则用默认值。

关键方法

抽象方法 buildTransportFactory()

定义抽象方法 buildTransportFactory(), 用于子类实现这个方法来为这个channel提供 ClientTransportFactory 。这个方法只对Transport 的实现者有意义,而不应该被普通用户使用。

  1. protected abstract ClientTransportFactory buildTransportFactory();

返回的 ClientTransportFactory 将在 build() 方法中传递给 ManagedChannelImpl() 的构造函数。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文