类NettyChannelProvider和OkHttpChannelProvider

类NettyChannelProvider

用于创建 NettyChannelBuilder 实例的provider。

  1. @Internal
  2. public final class NettyChannelProvider extends ManagedChannelProvider {
  3. @Override
  4. public boolean isAvailable() {
  5. // 总是返回true
  6. return true;
  7. }
  8. @Override
  9. public int priority() {
  10. // 使用默认优先级 5
  11. return 5;
  12. }
  13. @Override
  14. public NettyChannelBuilder builderForAddress(String name, int port) {
  15. // 对接NettyChannelBuilder
  16. return NettyChannelBuilder.forAddress(name, port);
  17. }
  18. @Override
  19. public NettyChannelBuilder builderForTarget(String target) {
  20. // 对接NettyChannelBuilder
  21. return NettyChannelBuilder.forTarget(target);
  22. }
  23. }

类OkHttpChannelProvider

用于创建 OkHttpChannelBuilder 实例的provider。

  1. @Internal
  2. public final class OkHttpChannelProvider extends ManagedChannelProvider {
  3. @Override
  4. public boolean isAvailable() {
  5. return true;
  6. }
  7. @Override
  8. public int priority() {
  9. // 会更加当前环境动态调整优先级
  10. // 如果是 IS_RESTRICTED_APPENGINE 或者 android 环境下,调整为 8, 此时优先级高于 netty(默认为5)
  11. // 其他情况下为 3, 此时优先级低于 netty(默认为5)
  12. return (GrpcUtil.IS_RESTRICTED_APPENGINE || isAndroid()) ? 8 : 3;
  13. }
  14. @Override
  15. public OkHttpChannelBuilder builderForAddress(String name, int port) {
  16. return OkHttpChannelBuilder.forAddress(name, port);
  17. }
  18. @Override
  19. public OkHttpChannelBuilder builderForTarget(String target) {
  20. return OkHttpChannelBuilder.forTarget(target);
  21. }
  22. }

IS_RESTRICTED_APPENGINE的判断逻辑如下(和 google appengine 有关,细节不追究了):

  1. public static final boolean IS_RESTRICTED_APPENGINE =
  2. "Production".equals(System.getProperty("com.google.appengine.runtime.environment"))
  3. && "1.7".equals(System.getProperty("java.specification.version"));

ServiceProvider 的实现

为了实现jdk的ServiceProvider,以便被load()函数装载,okjava 和 netty 在打包的时候都会按照JDK SPI的要求在他们的jar文件中加入SPI的内容,以netty为例:

类NettyChannelProvider - 图1

上图是 grpc-java 中 netty 子项目的相关文件,在resources下的 META-INF.services 目录,存在一个名为 io.grpc.ManagedChannelProvider 文件,其内容为:

  1. io.grpc.netty.NettyChannelProvider

总结

通过这种标准的SPI的方式,grpc实现了将 channel 的提供者和使用者分离并解藕。