Apache eagle入门--代码主逻辑分析

版权声明:著作权归作者所有,任何形式的转载都请注明出处。 https://blog.csdn.net/xiaokui9/article/details/82226707

由于项目使用apache eagle框架,所以学习了一下代码结构。由于还不会java,所以看得很艰难,只能大体先猜测了代码主结构,可能下面说的有不对的地方,望见谅。

页面保存出错,编辑了好几遍,格式太难调了,不调了。。。凑合看吧,想看带彩色的在编译器里看吧,页面实在调不出来了。

官方文档在:http://eagle.apache.org/docs/latest/getting-started/

源码中文档在E:\code\eagle\eagle-master-0.5.0-SNAPSHOT\docs\docs\目录下。

使用了Dropwizard框架,框架的文档在:https://www.dropwizard.io/0.7.1/docs/manual/core.html#bundles

目录

一、相关操作使用rest接口进行

二、eagle-server.sh启动脚本

三、ServerMain.java程序主入口

1、ServerApplication

1)initialize函数

a)GuiceBundleLoader.load()注册所有的Module

ApplicationProviderServiceImpl    
ServerModule    
ApplicationGuiceModule    
ModuleRegistry 

b)EntityRepositoryScanner注册所有的Entity

EntityRepository repo  
EntityDefinitionManager.registerEntity 

2)run函数

jersey().register注册REST接口对应的resources


一、相关操作使用rest接口进行

例如启动一个app

E:\code\eagle\eagle-master-0.5.0-SNAPSHOT\eagle-security\eagle-security-hdfs-auditlog\README.md

二、eagle-server.sh启动脚本

E:\code\eagle\eagle-master-0.5.0-SNAPSHOT\eagle-assembly\src\main\bin\eagle-server.sh

PROGRAM="java $JVM_OPTS -cp $EAGLE_CLASSPATH org.apache.eagle.server.ServerMain server ${CONFIGURATION_YML}"

org.apache.eagle.server.ServerMain就是主入口

三、ServerMain.java程序主入口

E:\code\eagle\eagle-master-0.5.0-SNAPSHOT\eagle-server\src\main\java\org\apache\eagle\server\ServerMain.java

main函数

System.out.println("\nStarting Eagle Server ...\n");
try {
    new ServerApplication().run(args);
}

1、ServerApplication

1)initialize函数

LOG.debug("Loading and registering guice bundle");
GuiceBundle<ServerConfig> guiceBundle = GuiceBundleLoader.load();
bootstrap.addBundle(guiceBundle);

LOG.debug("Loading and registering static AssetsBundle on /assets");
bootstrap.addBundle(new AssetsBundle("/assets", "/", "index.html", "/"));

LOG.debug("Initializing guice injector context for current ServerApplication");
guiceBundle.getInjector().injectMembers(this);

EntityRepositoryScanner.scan();

a)GuiceBundleLoader.load()注册所有的Module

public static GuiceBundle<ServerConfig> load(List<Module> modules) {
    /*
       We use tow injectors, one is Dropwizard injector, the other injector is to instantiate ApplicationProvider and load sub modules from applications
       so we need make Config and ApplicationProviderServiceImpl to have a global instance across multiple injectors
     */

    // Eagle server module
    Config config = ConfigFactory.load();
    ApplicationProviderService appProviderSvc = new ApplicationProviderServiceImpl[c2] (config);
    ServerModule serveBaseModule = new ServerModule[c3] (appProviderSvc);

    // load application specific modules
    ModuleRegistry registry = ApplicationExtensionLoader.load(serveBaseModule);

    // add application specific modules
    MetadataStore metadataStoreModule = MetadataStoreModuleFactory.getModule[c4] ();
    List<Module> metadataExtensions = metadataStoreModule.getModules(registry);
    int extensionNum = 0;
    GuiceBundle.Builder<ServerConfig> builder = GuiceBundle.newBuilder();
    if (metadataExtensions != null) {
        extensionNum = metadataExtensions.size();
        metadataExtensions.forEach(builder::addModule);
    }
    LOGGER.warn("Loaded {} modules (scope: metadataStore)", extensionNum);

    List<Module> globalExtensions = registry.getModules(GlobalScope.class);
    extensionNum = 0;

    if (globalExtensions != null) {
        extensionNum = globalExtensions.size();
        globalExtensions.forEach(builder::addModule);
    }
    LOGGER.warn("Loaded {} modules (scope: global)", extensionNum);

    if (modules != null) {
        modules.forEach(builder::addModule);
    }
    return builder.addModule(serveBaseModule)
        .setConfigClass(ServerConfig.class)
        .build();
}

 [c2]返回provider,代码看应该是获取要启动的Application

如后面ApplicationProviderServiceImpl的代码

代码中要求匹配到配置文件中的application.provider.load,但配置文件中只对应到application里可能类似的一个是:

stream {

    provider = org.apache.eagle.app.messaging.KafkaStreamProvider

  }

 [c4]从配置文件中读取数据库的类型,返回的就是JDBCMetadataStore类的实例

ApplicationProviderServiceImpl

public ApplicationProviderServiceImpl(Config config) {
    LOG.warn("Initializing {}", this.getClass().getCanonicalName());
    this.config = config;
    String appProviderLoaderClass = this.config.hasPath(APP_PROVIDER_LOADER_CLASS_KEY)
        ? this.config.getString(APP_PROVIDER_LOADER_CLASS_KEY) : ApplicationProviderLoader.getDefaultAppProviderLoader[c5] ();
    LOG.warn("Initializing {} = {}", APP_PROVIDER_LOADER_CLASS_KEY, appProviderLoaderClass);
    appProviderLoader = initializeAppProviderLoader(appProviderLoaderClass);
    LOG.warn("Initialized {}", appProviderLoader);
    reload();
}

 [c5]对应的provider.xml文件里的类是TestStormApplication

ServerModule

public class ServerModule extends AbstractModule {
    private ApplicationProviderService appProviderInst;

    public ServerModule(ApplicationProviderService appProviderInst) {
        this.appProviderInst = appProviderInst;
    }
    @Override
    protected void configure() {
        install(new CommonGuiceModule());
        install(new ApplicationGuiceModule(appProviderInst));
        install(MetadataStoreModuleFactory.getModule());
    }
}

ApplicationGuiceModule

public class ApplicationGuiceModule extends AbstractModule {
    private final ApplicationProviderService appProviderInst;

    public ApplicationGuiceModule(ApplicationProviderService appProviderInst) {
        this.appProviderInst = appProviderInst;
    }

    public ApplicationGuiceModule() {
        this.appProviderInst = new ApplicationProviderServiceImpl(ConfigFactory.load());
    }

    @Override
    protected void configure() {
        bind(ApplicationProviderService.class).toProvider(Providers.of(appProviderInst));
        bind(ApplicationDescService.class).toProvider(Providers.of(appProviderInst));
        bind(ApplicationManagementService.class).to(ApplicationManagementServiceImpl.class).in(Singleton.class);
       bind(ApplicationStatusUpdateService.class).to(ApplicationStatusUpdateServiceImpl.class).in(Singleton.class);
        bind(ApplicationHealthCheckService.class).to(ApplicationHealthCheckServiceImpl.class).in(Singleton.class);
    }
}

ModuleRegistry

public static ModuleRegistry load(Module... context) {
    LOGGER.warn("Loading application extension modules");
    ModuleRegistry registry = new ModuleRegistryImpl();
    Guice.createInjector(context).getInstance(ApplicationProviderService.class).getProviders().forEach((provider) -> {
        LOGGER.warn("Registering modules from {}", provider);
        provider.register(registry);
    });
    return registry;
}

b)EntityRepositoryScanner注册所有的Entity

个人理解这个Entity可能指的是所有组件?

final Collection<Class<? extends TaggedLogAPIEntity>> entityClasses = repo.getEntitySet();

        for (Class<? extends TaggedLogAPIEntity> clazz : entityClasses) {

            EntityDefinitionManager.registerEntity(clazz);

EntityRepository repo

        public synchronized Collection<Class<? extends TaggedLogAPIEntity>> getEntitySet()

{                return new ArrayList<Class<? extends TaggedLogAPIEntity>>(entitySet);

        }

EntityDefinitionManager.registerEntity

public static void registerEntity(Class<? extends TaggedLogAPIEntity> clazz) throws IllegalArgumentException{
   registerEntity(createEntityDefinition(clazz));
}

public static EntityDefinition createEntityDefinition(Class<? extends TaggedLogAPIEntity> cls) {
      final EntityDefinition ed = new EntityDefinition();
      ed.setEntityClass(cls);
      // parse cls' annotations
      Table table = cls.getAnnotation(Table.class);
      if(table == null || table.value().isEmpty()){
         throw new IllegalArgumentException("Entity class must have a non-empty table name annotated with @Table");
      }
      String tableName = table.value();
      if(EagleConfigFactory.load().isTableNamePrefixedWithEnvironment()){
         tableName = EagleConfigFactory.load().getEnv() + "_" + tableName;
      }
      ed.setTable(tableName);

      ColumnFamily family = cls.getAnnotation(ColumnFamily.class);
      if(family == null || family.value().isEmpty()){
         throw new IllegalArgumentException("Entity class must have a non-empty column family name annotated with @ColumnFamily");
      }
      ed.setColumnFamily(family.value());

      Prefix prefix = cls.getAnnotation(Prefix.class);
      if(prefix == null || prefix.value().isEmpty()){
         throw new IllegalArgumentException("Entity class must have a non-empty prefix name annotated with @Prefix");
      }
      ed.setPrefix(prefix.value());

      TimeSeries ts = cls.getAnnotation(TimeSeries.class);
      if(ts == null){
         throw new IllegalArgumentException("Entity class must have a non-empty timeseries name annotated with @TimeSeries");
      }
      ed.setTimeSeries(ts.value());

      Service service = cls.getAnnotation(Service.class);
      if(service == null || service.value().isEmpty()){
         ed.setService(cls.getSimpleName());
      } else {
         ed.setService(service.value());
      }

      Metric m = cls.getAnnotation(Metric.class);
      Map<String, Class<?>> dynamicFieldTypes = new HashMap<String, Class<?>>();
      if(m != null){
         // metric has to be timeseries
         if(!ts.value()){
            throw new IllegalArgumentException("Metric entity must be time series as well");
         }
         MetricDefinition md = new MetricDefinition();
         md.setInterval(m.interval());
         ed.setMetricDefinition(md);
      }

      java.lang.reflect.Field[] fields = cls.getDeclaredFields();
      for(java.lang.reflect.Field f : fields){
         Column column = f.getAnnotation(Column.class); 
         if(column == null || column.value().isEmpty()){
            continue;
         }
         Class<?> fldCls = f.getType();
         // intrusive check field type for metric entity
         checkFieldTypeForMetric(ed.getMetricDefinition(), f.getName(), fldCls, dynamicFieldTypes);
         Qualifier q = new Qualifier();
         q.setDisplayName(f.getName());
         q.setQualifierName(column.value());
         EntitySerDeser<?> serDeser = _serDeserMap.get(fldCls); 
         if(serDeser == null){
//          throw new IllegalArgumentException(fldCls.getName() + " in field " + f.getName() +
//                " of entity " + cls.getSimpleName() + " has no serializer associated ");
            serDeser = DefaultJavaObjctSerDeser.INSTANCE;
         }

         q.setSerDeser((EntitySerDeser<Object>)serDeser);
         ed.getQualifierNameMap().put(q.getQualifierName(), q);
         ed.getDisplayNameMap().put(q.getDisplayName(), q);
         // TODO: should refine rules, consider fields like "hCol", getter method should be gethCol() according to org.apache.commons.beanutils.PropertyUtils
         final String propertyName = f.getName().substring(0,1).toUpperCase() + f.getName().substring(1);
         String getterName = "get" + propertyName;
         try {
            Method method = cls.getMethod(getterName);
            ed.getQualifierGetterMap().put(f.getName(), method);
         } catch (Exception e) {
            // Check if the type is boolean
            getterName = "is" + propertyName;
            try {
               Method method = cls.getMethod(getterName);
               ed.getQualifierGetterMap().put(f.getName(), method);
            } catch (Exception e1) {
               throw new IllegalArgumentException("Field " + f.getName() + " hasn't defined valid getter method: " + getterName, e);
            }
         }
         if(LOG.isDebugEnabled()) LOG.debug("Field registered " + q);
      }

      // TODO: Lazy create because not used at all
      // dynamically create bean class
      if(ed.getMetricDefinition() != null){
         Class<?> metricCls = createDynamicClassForMetric(cls.getName()+"_SingleTimestamp", dynamicFieldTypes);
         ed.getMetricDefinition().setSingleTimestampEntityClass(metricCls);
      }

      final Partition partition = cls.getAnnotation(Partition.class);
      if (partition != null) {
         final String[] partitions = partition.value();
         ed.setPartitions(partitions);
         // Check if partition fields are all tag fields. Partition field can't be column field, must be tag field.
         for (String part : partitions) {
            if (!ed.isTag(part)) {
               throw new IllegalArgumentException("Partition field can't be column field, must be tag field. "
                     + "Partition name: " + part);
            }
         }
      }

      final Indexes indexes = cls.getAnnotation(Indexes.class);
      if (indexes != null) {
         final Index[] inds = indexes.value();
         final IndexDefinition[] indexDefinitions = new IndexDefinition[inds.length];
         for (int i = 0; i < inds.length; ++i) {
            final Index ind = inds[i];
            indexDefinitions[i] = new IndexDefinition(ed, ind);
         }
         ed.setIndexes(indexDefinitions);
      }

      final ServicePath path = cls.getAnnotation(ServicePath.class);
      if (path != null) {
         if (path.path() != null && (!path.path().isEmpty())) {
            ed.setServiceCreationPath(path.path());
         }
      }

      final Tags tags = cls.getAnnotation(Tags.class);
      if(tags != null) {
         String[] tagNames = tags.value();
         ed.setTags(tagNames);
      }
      return ed;
   }

2)run函数

public void run(ServerConfig configuration, Environment environment) throws Exception {
    environment.getApplicationContext().setContextPath(ServerConfig.getContextPath());
    environment.jersey().register(RESTExceptionMapper.class);
    environment.jersey().setUrlPattern(ServerConfig.getApiBasePath());
    environment.getObjectMapper().setFilters(TaggedLogAPIEntity.getFilterProvider());
    environment.getObjectMapper().registerModule(new EntityJsonModule());

    // Automatically scan all REST resources
    new PackagesResourceConfig(ServerConfig.getResourcePackage()).getClasses().forEach(environment.jersey()::register);

    // Swagger resources
    environment.jersey().register(ApiListingResource.class);

    BeanConfig swaggerConfig = new BeanConfig();
    swaggerConfig.setTitle(ServerConfig.getServerName());
    swaggerConfig.setVersion(ServerConfig.getServerVersion().version);
    swaggerConfig.setBasePath(ServerConfig.getApiBasePath());
    swaggerConfig.setResourcePackage(ServerConfig.getResourcePackage());
    swaggerConfig.setLicense(ServerConfig.getLicense());
    swaggerConfig.setLicenseUrl(ServerConfig.getLicenseUrl());
    swaggerConfig.setDescription(Version.str());
    swaggerConfig.setScan(true);

    // Simple CORS filter
    environment.servlets().addFilter(SimpleCORSFiler.class.getName(), new SimpleCORSFiler())
        .addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");

    // Register authentication provider
    BasicAuthBuilder authBuilder = new BasicAuthBuilder(configuration.getAuthConfig(), environment);
    environment.jersey().register(authBuilder.getBasicAuthProvider());
    if (configuration.getAuthConfig().isEnabled()) {
        environment.jersey().getResourceConfig().getResourceFilterFactories()
            .add(new BasicAuthResourceFilterFactory(authBuilder.getBasicAuthenticator()));
    }
    registerAppServices(environment);
}

jersey().register注册REST接口对应的resources

// Automatically scan all REST resources    

new PackagesResourceConfig(ServerConfig.getResourcePackage()).getClasses().forEach(environment.jersey()::register);

getResourcePackage()返回"org.apache.eagle"。

个人理解是在org.apache.eagle包下的所有Resource类都被注册。

PackagesResourceConfig是ResourceConfig的子类。(https://www.cnblogs.com/newstar/archive/2013/06/01/3112086.html

jersey 的使用,必须要有一个全局的配置类,这个类需满足以下条件:

1、@ApplicationPath 注解该类

2、并且在参数中指定相对路径继承org.glassfish.jersey.server.ResourceConfig 类

3、该类构造方法中设置jersey的配置,比如指定接口的包路径

@ApplicationPath("/")

public class RESTServiceConfig extends ResourceConfig {

  public RESTServiceConfig() {

    packages("web.rest");

    register(MultiPartFeature.class);

  }

}

https://www.jianshu.com/p/15c32cb52da1


猜你喜欢

转载自blog.csdn.net/xiaokui9/article/details/82226707