[Apache Atlas] Atlas 架构设计及源代码简单分析

Apache Atlas 架构图

[Apache Atlas] Atlas 架构设计及源代码简单分析

Atlas 支持多数据源接入:Hive、HBase、Storm等

Type System

Type

Atlas 中定义了一些元数据类型

── AtlasBaseTypeDef
  │   ├── AtlasEnumDef
  │   └── AtlasStructDef
  │       ├── AtlasBusinessMetadataDef
  │       ├── AtlasClassificationDef
  │       ├── AtlasEntityDef
  │       └── AtlasRelationshipDef
  ├── AtlasStructType
  │   ├── AtlasBusinessMetadataType
  │   ├── AtlasClassificationType
  │   ├── AtlasRelationshipType
  │   └── AtlasEntityType
  │       └── AtlasRootEntityType
  ├── AtlasType
  │   ├── AtlasArrayType
  │   ├── AtlasBigDecimalType
  │   ├── AtlasBigIntegerType
  │   ├── AtlasByteType
  │   ├── AtlasDateType
  │   ├── AtlasDoubleType
  │   ├── AtlasEnumType
  │   ├── AtlasFloatType
  │   ├── AtlasIntType
  │   ├── AtlasLongType
  │   ├── AtlasMapType
  │   ├── AtlasObjectIdType
  │   ├── AtlasShortType
  │   ├── AtlasStringType
  │   └── AtlasStructType
  │       ├── AtlasBusinessMetadataType
  │       ├── AtlasClassificationType
  │       ├── AtlasEntityType
  │       └── AtlasRelationshipType
  ├── AtlasTypeDefStore
  │   └── AtlasTypeDefGraphStore
  │       └── AtlasTypeDefGraphStoreV2
  └── StructTypeDefinition
      └── HierarchicalTypeDefinition
          ├── ClassTypeDefinition
          └── TraitTypeDefinition

Entity

Entity 是基于类型的具体实现

AtlasEntity
  ├── AtlasEntityExtInfo
  │   ├── AtlasEntitiesWithExtInfo
  │   └── AtlasEntityWithExtInfo
  ├── AtlasEntityStore
  │   └── AtlasEntityStoreV2
  ├── AtlasEntityStream
  │   └── AtlasEntityStreamForImport
  ├── AtlasEntityType
  │   └── AtlasRootEntityType
  └── IAtlasEntityChangeNotifier
      ├── AtlasEntityChangeNotifier
      └── EntityChangeNotifierNop

Attributes

针对模型定义属性

AtlasAttributeDef
      └── AtlasRelationshipAttributeDef

AtlasAttributeDef 属性字段:

private String                   name;
private String                   typeName;
private boolean                  isOptional;
private Cardinality              cardinality;
private int                      valuesMinCount;
private int                      valuesMaxCount;
private boolean                  isUnique;
private boolean                  isIndexable;
private boolean                  includeInNotification;
private String                   defaultValue;
private String                   description;
private int                      searchWeight = DEFAULT_SEARCHWEIGHT;
private IndexType                indexType    = null;
private List<atlasconstraintdef> constraints;
private Map<string, string>      options;
private String                   displayName;

&#x5177;&#x4F53;&#x5B9E;&#x73B0;&#xFF1A;

db:
    "name":        "db",
    "typeName":    "hive_db",
    "isOptional":  false,
    "isIndexable": true,
    "isUnique":    false,
    "cardinality": "SINGLE"

columns:
    "name":        "columns",
    "typeName":    "array<hive_column>",
    "isOptional":  optional,
    "isIndexable": true,
    &#x201C;isUnique":    false,
    "constraints": [ { "type": "ownedRef" } ]
</hive_column></string,></atlasconstraintdef>
  • isComposite – 是否复合
  • isIndexable – 是否索引
  • isUnique – 是否唯一
  • multiplicity – 指示此属性是(必需的/可选的/还是可以是多值)的

System specific types and their significance

Referenceable

This type represents all entities that can be searched for using a unique attribute called qualifiedName.

  &#x251C;&#x2500;&#x2500; Referenceable
  &#x251C;&#x2500;&#x2500; ReferenceableDeserializer
  &#x251C;&#x2500;&#x2500; ReferenceableSerializer
  &#x2514;&#x2500;&#x2500; V1SearchReferenceableSerializer

Hooks

以Hive元信息采集为例分析采集过程:

全量导入

import-hive.sh

"${JAVA_BIN}" ${JAVA_PROPERTIES} -cp "${CP}"
org.apache.atlas.hive.bridge.HiveMetaStoreBridge $IMPORT_ARGS
importTables
  &#x2514;&#x2500;&#x2500; importDatabases        [addons/hive-bridge/src/main/java/org/apache/atlas/hive/bridge/HiveMetaStoreBridge.java +295]
      &#x2514;&#x2500;&#x2500; importHiveMetadata [addons/hive-bridge/src/main/java/org/apache/atlas/hive/bridge/HiveMetaStoreBridge.java +289]

上面是调用过程:

importTables -> importTable –> registerInstances

AtlasEntitiesWithExtInfo ret = null;
EntityMutationResponse   response        = atlasClientV2.createEntities(entities);
List<atlasentityheader>  createdEntities = response.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE);

if (CollectionUtils.isNotEmpty(createdEntities)) {
    ret = new AtlasEntitiesWithExtInfo();

    for (AtlasEntityHeader createdEntity : createdEntities) {
        AtlasEntityWithExtInfo entity = atlasClientV2.getEntityByGuid(createdEntity.getGuid());

        ret.addEntity(entity.getEntity());

        if (MapUtils.isNotEmpty(entity.getReferredEntities())) {
            for (Map.Entry<string, atlasentity> entry : entity.getReferredEntities().entrySet()) {
                ret.addReferredEntity(entry.getKey(), entry.getValue());
            }
        }

        LOG.info("Created {} entity: name={}, guid={}", entity.getEntity().getTypeName(), entity.getEntity().getAttribute(ATTRIBUTE_QUALIFIED_NAME), entity.getEntity().getGuid());
    }
}
</string,></atlasentityheader>

通过Http Post 的请求将库表数据更新至Atlas

atlasClientV2有很多Http接口

Atlas HTTP 客户端API:

[Apache Atlas] Atlas 架构设计及源代码简单分析

实时监听

HiveHook implements ExecuteWithHookContext

ExecuteWithHookContext is a new interface that the Pre/Post Execute Hook can run with the HookContext.

实现run()方法来对Hive 相关事件做处理

Hive相关事件:

BaseHiveEvent
      &#x251C;&#x2500;&#x2500; AlterTableRename
      &#x251C;&#x2500;&#x2500; CreateHiveProcess
      &#x251C;&#x2500;&#x2500; DropDatabase
      &#x251C;&#x2500;&#x2500; DropTable
      &#x251C;&#x2500;&#x2500; CreateDatabase
      &#x2502;   &#x2514;&#x2500;&#x2500; AlterDatabase
      &#x2514;&#x2500;&#x2500; CreateTable
          &#x2514;&#x2500;&#x2500; AlterTable
              &#x2514;&#x2500;&#x2500; AlterTableRenameCol

以create database 为例分析流程:

//&#x5904;&#x7406;Hook &#x4E0A;&#x4E0B;&#x6587;&#x4FE1;&#x606F;
AtlasHiveHookContext context =
new AtlasHiveHookContext(this, oper, hookContext, getKnownObjects(), isSkipTempTables());

//&#x5EFA;&#x5E93;&#x4E8B;&#x4EF6;&#x5904;&#x7406;,&#x63D0;&#x53D6;&#x76F8;&#x5173;&#x5E93;&#x4FE1;&#x606F;
event = new CreateDatabase(context);

if (event != null) {
    final UserGroupInformation ugi = hookContext.getUgi() == null ? Utils.getUGI() : hookContext.getUgi();
    super.notifyEntities(ActiveEntityFilter.apply(event.getNotificationMessages()), ugi);
}

public enum HookNotificationType {
    TYPE_CREATE, TYPE_UPDATE, ENTITY_CREATE, ENTITY_PARTIAL_UPDATE, ENTITY_FULL_UPDATE, ENTITY_DELETE,
    ENTITY_CREATE_V2, ENTITY_PARTIAL_UPDATE_V2, ENTITY_FULL_UPDATE_V2, ENTITY_DELETE_V2
}

//&#x64CD;&#x4F5C;&#x7528;&#x6237;&#x83B7;&#x53D6;
if (context.isMetastoreHook()) {
    try {
        ugi = SecurityUtils.getUGI();
    } catch (Exception e) {
        //do nothing
    }
} else {
    ret = getHiveUserName();

    if (StringUtils.isEmpty(ret)) {
        ugi = getUgi();
    }
}

if (ugi != null) {
    ret = ugi.getShortUserName();
}

if (StringUtils.isEmpty(ret)) {
    try {
        ret = UserGroupInformation.getCurrentUser().getShortUserName();
    } catch (IOException e) {
        LOG.warn("Failed for UserGroupInformation.getCurrentUser() ", e);

        ret = System.getProperty("user.name");
    }
}

主要:

获取实体信息, 传递Hook message的类型、操作用户

notifyEntities 可以看出其他组件HBase、impala也会调用该方法进行消息的发送

[Apache Atlas] Atlas 架构设计及源代码简单分析
public static void notifyEntities(List<hooknotification> messages, UserGroupInformation ugi, int maxRetries) {
    if (executor == null) { // send synchronously
        notifyEntitiesInternal(messages, maxRetries, ugi, notificationInterface, logFailedMessages, failedMessagesLogger);
    } else {
        executor.submit(new Runnable() {
            @Override
            public void run() {
                notifyEntitiesInternal(messages, maxRetries, ugi, notificationInterface, logFailedMessages, failedMessagesLogger);
            }
        });
    }
}
</hooknotification>

消息通知框架:

NotificationInterface
      &#x251C;&#x2500;&#x2500; AtlasFileSpool
      &#x2514;&#x2500;&#x2500; AbstractNotification
          &#x251C;&#x2500;&#x2500; KafkaNotification
          &#x2514;&#x2500;&#x2500; Spooler

数据写入Kafka中:

@Override
public void sendInternal(NotificationType notificationType, List<string> messages) throws NotificationException {
    KafkaProducer producer = getOrCreateProducer(notificationType);

    sendInternalToProducer(producer, notificationType, messages);
}
</string>

根据NotificationType写入指定topic 中:

private static final Map<notificationtype, string> PRODUCER_TOPIC_MAP = new HashMap<notificationtype, string>() {
    {
        put(NotificationType.HOOK, ATLAS_HOOK_TOPIC);
        put(NotificationType.ENTITIES, ATLAS_ENTITIES_TOPIC);
    }
};

NOTIFICATION_HOOK_TOPIC_NAME("atlas.notification.hook.topic.name", "ATLAS_HOOK"),
NOTIFICATION_ENTITIES_TOPIC_NAME("atlas.notification.entities.topic.name", "ATLAS_ENTITIES"),
</notificationtype,></notificationtype,>

数据主要写入两个Topic中: ATLAS_ENTITIES、ATLAS_HOOK

ATLAS_HOOK是写入Hook事件消息, 创建库的事件元数据信息会写入该Topic中

如何唯一确定一个库:

public String getQualifiedName(Database db) {
    return getDatabaseName(db) + QNAME_SEP_METADATA_NAMESPACE + getMetadataNamespace();
}

dbName@clusterName 确定唯一性

外延应用

一个基于Hive hook 实现Impala 元数据刷新的用例:
AutoRefreshImpala:https://github.com/Observe-secretly/AutoRefreshImpala

参考

[1] Apache Atlas – Data Governance and Metadata framework for Hadoop
[2] Apache Atlas 源码

Original: https://www.cnblogs.com/bigdata1024/p/15306365.html
Author: chaplinthink
Title: [Apache Atlas] Atlas 架构设计及源代码简单分析

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/522721/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球