无题

Apollo

1. Google Guice

概念:Guice 是 google 开源的轻量级依赖注入框架(DI),类似于重量级的Spring IOC的DI。所以对于轻量级的应用,Guice比较合适。

  • Guice:整个框架的门面
  • Injector:一个依赖的管理上下文
  • Binder:一个接口和实现的绑定
  • Module:一组 Binder
  • Provider:bean 的提供者
  • Key:Binder 中对应一个 Provider
  • Scope:Provider 的作用域

Binding类型结构:

1
2
3
4
public interface Binding<T> extends Element {
Key<T> getKey();
Provider<T> getProvider();
}
  • 键 Key 唯一地确定每一个绑定。 键 Key 包含了客户代码所依赖的类型以及一个可选的标注。你可以使用标注来区分指向同一类型的多个绑定。
  • 生成T类型实例的工厂

Module:继承AbstractModule来生产Binding对象,该步骤在com.google.inject.internal.InternalInjectorCreator#injectDynamically完成

1
2
3
4
5
6
7
public class BasicModule extends AbstractModule {
@Override
protected void configure() {
bind(Communication.class)
.toInstance(new Communication(true));
}
}

由 Guice 创建Injector,可以从Injector中获取Binding,Instance,Provider

1
2
3
4
5
public interface Injector {
<T> Binding<T> getBinding(Key<T> key);
<T> Provider<T> getProvider(Key<T> key);
<T> T getInstance(Key<T> key);
}

Binding生成过程解析

  1. com.google.inject.Guice#createInjector(com.google.inject.Stage, java.lang.Iterable<? extends com.google.inject.Module>)
  2. new InternalInjectorCreator().stage(stage).addModules(modules).build()
  3. com.google.inject.internal.InjectorShell.Builder#build
  4. com.google.inject.internal.AbstractProcessor#process(com.google.inject.internal.InjectorImpl, java.util.List<com.google.inject.spi.Element>)
  5. com.google.inject.spi.Element#acceptVisitor
  6. com.google.inject.spi.ScopeBinding#acceptVisitor
  7. com.google.inject.internal.ScopeBindingProcessor#visit
  8. com.google.inject.internal.State#putScopeBinding
  9. com.google.inject.internal.InheritingState#putScopeBinding / com.google.inject.internal.InheritingState#putBinding

但是如果配置的Binding属性时有 bind(Communication.class).toInstance(new Communication(true)).asEagerSingleton();则会创建并实例化对象

  1. com.google.inject.internal.InternalInjectorCreator#build
  2. com.google.inject.internal.InternalInjectorCreator#injectDynamically
  3. com.google.inject.internal.InternalInjectorCreator#loadEagerSingletons

2. Apollo 模块解析

  • Config Service提供配置的读取、推送等功能,服务对象是Apollo客户端

  • Admin Service提供配置的修改、发布等功能,服务对象是Apollo Portal(管理界面)

  • Client通过域名访问Meta Server获取Config Service服务列表(IP+Port),而后直接通过IP+Port访问服务,同时在Client侧会做load balance、错误重试

3. Client 流程分析

  1. 将于Spring整合的自动配置类写入spring.factories

  2. ApolloApplicationContextInitializer 继承自 Spring的 ApplicationContextInitializer 和 EnvironmentPostProcessor

  3. ApolloApplicationContextInitializer 创建的时候创建 SpringInjector,Spring注入了 SpringModule 模块,该模块绑定了如下Binding

    1
    2
    3
    bind(PlaceholderHelper.class).in(Singleton.class);
    bind(ConfigPropertySourceFactory.class).in(Singleton.class);
    bind(SpringValueRegistry.class).in(Singleton.class);
  4. EnvironmentPostProcessor 在Spring 环境创建结束执行com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer#postProcessEnvironment

  5. com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer#initialize(org.springframework.core.env.ConfigurableEnvironment)

  6. 利用ApolloModule 创建DefaultInjector

    1
    2
    3
    4
    5
    6
    7
    8
    9
    bind(ConfigManager.class).to(DefaultConfigManager.class).in(Singleton.class); // 配置管理
    bind(ConfigFactoryManager.class).to(DefaultConfigFactoryManager.class).in(Singleton.class); // 配置工厂管理,可基于 Namespace 获得配置工厂
    bind(ConfigRegistry.class).to(DefaultConfigRegistry.class).in(Singleton.class); // 管理 ConfigFactory 和 Namespace 的映射关系
    bind(ConfigFactory.class).to(DefaultConfigFactory.class).in(Singleton.class); // 默认的配置工厂
    bind(ConfigUtil.class).in(Singleton.class);
    bind(HttpUtil.class).in(Singleton.class);
    bind(ConfigServiceLocator.class).in(Singleton.class);
    bind(RemoteConfigLongPollService.class).in(Singleton.class);
    bind(YamlParser.class).in(Singleton.class);

    ConfigService 初始化

    1. ConfigService#getManager → ApolloInjector.getInstance(ConfigManager.class)
    2. DefaultConfigManager#DefaultConfigManager → ApolloInjector.getInstance(ConfigFactoryManager.class)
    3. DefaultConfigFactoryManager#DefaultConfigFactoryManager → ApolloInjector.getInstance(ConfigRegistry.class)

    ConfigService.getConfig(namespace) 流程

    1. ConfigService#getManager → ConfigManager

    2. ConfigManager#getConfig → Config

    3. DefaultConfigManager#m_configs中获取,有则返回

    4. ConfigFactoryManager#getFactory

    5. m_factoryManager.getFactory(namespace)

    6. config = factory.create(namespace)

    7. DefaultConfigFactory#create

    8. DefaultConfigFactory#createLocalConfigRepository

    9. DefaultConfigFactory#createLocalConfigRepository

    10. DefaultConfigFactory#createRemoteConfigRepository

    11. RemoteConfigRepository#RemoteConfigRepository

    12. 定时配置拉取任务schedulePeriodicRefresh,配置变化之后调用 AbstractConfigRepository#fireRepositoryChange通知

    13. 长轮询拉取配置 RemoteConfigRepository#scheduleLongPollingRefresh → while (!m_longPollingStopped.get() && !Thread.currentThread().isInterrupted())

    14. RemoteConfigLongPollService#doLongPollingRefresh → RemoteConfigLongPollService#notify

    配置变更监听器

    1. Config#addChangeListener(com.ctrip.framework.apollo.ConfigChangeListener, java.util.Set<java.lang.String>, java.util.Set<java.lang.String>)
    2. m_listeners.add(listener)
    3. AbstractConfigRepository#fireRepositoryChange配置变更后一次通知Config的监听器对配置变更响应