Ambari源碼API調用鏈剖析(最細)

1、Ambari-Server中基本的Rest API請求舉例

(1)認證
對Ambari API操作需要認證,在Ambari中採用的HTTP基本認證。

該認證可使用-u或是–user參數指定,例如:

curl –user name:password http://{your.ambari.server}/api/v1/clusters

(2)監控
Ambari API提供監控Hadoop集羣運行狀況和metrics信息的接口。

例子:獲取c1集羣中HDFS服務的DataNode組件資源信息。
請求:

GET /clusters/c1/services/HDFS/components/DATANODE

響應:

200 OK
{
    "href" : "http://your.ambari.server/api/v1/clusters/c1/services/HDFS/components/DATANODE",
    "metrics" : {
        "process" : { "proc_total" : 697.75, "proc_run" : 0.875},
        "rpc" : {...},
        "ugi" : {...},
        "dfs" : {"datanode" : {...}},
        "disk" : {...},
        "cpu" : {...}
        ...
    },
    "ServiceComponentInfo" : {
        "cluster_name" : "c1",
        "component_name" : "DATANODE",
        "service_name" : "HDFS"
        "state" : "STARTED"
    },
    "host_components" : [
        {
            "href" : "http://your.ambari.server/api/v1/clusters/c1/hosts/host1/host_components/DATANODE",
            "HostRoles" : {"cluster_name" : "c1","component_name" : "DATANODE","host_name" : "host1"}
        }
    ]
}

(3)管理

Ambari API提供了對Hadoop集羣資源管理的方法,包括資源創建、刪除和更新。

例如
創建HDFS服務,請求:POST /clusters/c1/services/HDFS;響應:201 Created。
啓動服務,請求:

PUT /clusters/c1/services/HDFS/

傳入body:

 {“serviceInfo”:{”state”:”STARTED”} };

響應:202 Accepted。

2、Ambari-Server目錄

目錄 描述
org.apache.ambari.server.api.services 對web接口的入口方法,處理/api/v1/* 的請求
org.apache.ambari.server.controller 對Ambari中cluster的管理處理,如新增host,更service、刪除component等
org.apache.ambari.server.controller.internal 主要存放ResourceProvider和PropertyProvider;
org.apache.ambari.service.orm.* 對數據庫的操作
org.apache.ambari.server.agent.rest 處理與Agent的接口的入口方法
org.apache.ambari.security 使用Spring Security來做權限管理

其中,每一種Resource都對應一個ResourceProvider,對應關係如下
在這裏插入圖片描述

3、RestApi調用過程剖析

下面以查看集羣中主機列表API爲例,說明Ambari-Server處理Rest API的基本處理框架。

該API的具體形式爲:

get: api/v1/clusters/mycluster/hosts。

Ambari-Server中嵌入Jetty,使用Jetty爲容器處理Web請求

Ambari-Server在收到Web請求後,轉入到Jetty Hander邏輯中,由Jetty Hander進行處理

每個Rest API有對應的處理Handler,可直接進行Rest API的URI進行標註對比。

對於get:api/v1/clusters/mycluster/hosts URI請求的Handler,可直接找標註了@path(/clusters/)的類,該類爲ClusterService。

並找到URI路徑全匹配的Get方法,最終找到getHostHandler方法。

該方法返回一個JAX-RS子資源,表明對該Get請求由HostService的相應方法進行處理響應。具體下文有詳細配圖介紹

3.1 源代碼調用跟蹤

3.1.1、 api->service層

ambari-server module 對web接口的入口方法中處理形如/api/v1/* 的請求,由上文2中可知,需要在service層找對應的服務處理類

get: api/v1/clusters/mycluster/hosts。

對應的就是ClustersService.java了

在這裏插入圖片描述

在Ambari-Server中,幾個常用的Service列表如下:
在這裏插入圖片描述

Ambari-Server使用Jersey框架作爲JAX-RS標準的實現。

具體的資源及資源方法通過JAX-RS標註進行標識。

Ambari-Server將org.apache.ambari.server.api.services包下所有類都通過Jersey註冊成Jetty Handler。

3.1.2、Service->Handler

找到URI路徑全匹配的Get方法,最終找到getHostHandler方法

該方法返回一個JAX-RS子資源,表明對該Get請求由HostService的相應方法進行處理響應。

說明是拿HostService這個服務對應的Handler調度的
在這裏插入圖片描述

同理,在HostService中按照路徑匹配規則找到響應的處理方法,方法爲:getHosts。

在這裏插入圖片描述

  public Response getHosts(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
    return handleRequest(headers, body, ui, Request.Type.GET,
        createHostResource(m_clusterName, null));
  }

3.1.3、Handler->Request

將Rest API請求進行轉發時,首先轉發給一級JAX-RS資源的相關方法。

如果該JAX-RS資源能直接處理,則直接調用BaseSevrvice類的handleRequest方法進行請求處理。

否則轉發給二級JAX-RS資源,由該JAX-RS資源處理,處理方式相同(要麼直接調用BaseService.handleRequest方法或是繼續轉給下一級資源)。
getHosts()–>BaseService.handleRequest()

  protected Response handleRequest(HttpHeaders headers, String body, UriInfo uriInfo,
                                   Request.Type requestType, ResourceInstance resource) {

    return handleRequest(headers, body, uriInfo, requestType, null, resource);
  }
protected Response handleRequest(HttpHeaders headers, String body,
                                 UriInfo uriInfo, Request.Type requestType,
                                 MediaType mediaType, ResourceInstance resource) {

  // original request and initial result
  RequestBody rb = new RequestBody();
  rb.setBody(body);
  Request request = getRequestFactory().createRequest(headers, rb, uriInfo, requestType, resource);
  Result result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.OK));

  try {
    Set<RequestBody> requestBodySet = getBodyParser().parse(body);

    Iterator<RequestBody> iterator = requestBodySet.iterator();
    while (iterator.hasNext() && result.getStatus().getStatus().equals(ResultStatus.STATUS.OK)) {
      RequestBody requestBody = iterator.next();//獲取列表中下一個RequestBody元素,創建一個request對象(下面)

      request = getRequestFactory().createRequest(
              headers, requestBody, uriInfo, requestType, resource);//Request對象類型有GetRequest、PostRequest、PutRequest

      result  = request.process();//調用request.process函數處理請求
      // if it is not OK, then it is logged below
      if(ResultStatus.STATUS.OK.equals(result.getStatus().getStatus())) {
        requestAuditLogger.log(request, result);//獲取請求的原始處理結果,並寫日誌
      }
    }

    if(requestBodySet.isEmpty() || !ResultStatus.STATUS.OK.equals(result.getStatus().getStatus())) {
      requestAuditLogger.log(request, result);//獲取請求的原始處理結果,並寫日誌
    }
  } catch (BodyParseException e) {
    result =  new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST, e.getMessage()));
    LOG.error("Bad request received: " + e.getMessage());
    requestAuditLogger.log(request, result);
  } catch (Throwable t) {
    requestAuditLogger.log(request, new ResultImpl(new ResultStatus(ResultStatus.STATUS.SERVER_ERROR, t.getMessage())));
    throw t;
  }

  ResultSerializer serializer = mediaType == null ? getResultSerializer() : getResultSerializer(mediaType);

  Response.ResponseBuilder builder = Response.status(result.getStatus().getStatusCode()).entity(
          serializer.serialize(result));

  if (mediaType != null) {
    builder.type(mediaType);
  }

  RetryHelper.clearAffectedClusters();
  return builder.build();
}

3.1.4、Request.process()->Result

在這裏插入圖片描述

/**
BaseRequest類實現了這個接口,返回一個Result結果集

process實現裏調用了result = getRequestHandler().handleRequest(this)

其中 getRequestHandler()是確定哪種類型的請求,這裏是GetRequest

GetRequest調用自己的RequestHandler返回一個ReadHandler()實例



*
*/
@Override
public Result process() {
  if (LOG.isDebugEnabled()) {
    LOG.debug("Handling API Request: '{}'", getURI());
  }

  Result result;
  try {
    parseRenderer();
    parseQueryPredicate();
    result = getRequestHandler().handleRequest(this);//用一種Request來調用handleRequest()
  } catch (InvalidQueryException e) {
    String message = "Unable to compile query predicate: " + e.getMessage();
    LOG.error(message, e);
    result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST, message));
  } catch (IllegalArgumentException e) {
    String message = "Invalid Request: " + e.getMessage();
    LOG.error(message, e);
    result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST, message));
  }

  if (! result.getStatus().isErrorState()) {
    getResultPostProcessor().process(result);
  }

  return result;
}

在這裏插入圖片描述

如下圖、GetRequest調用自己的RequestHandler返回一個ReadHandler()實例

在這裏插入圖片描述

如下圖、ReadHandler實例

其中的handleRequest(Request)方法

在這裏插入圖片描述
如下圖、handleRequest()做真正請求處理的工作,通過這個方法使Request轉化爲Result結果集

其中的query對象執行execute操作,返回result結果,核心方法

  @Override
  public Result handleRequest(Request request) {//此方法做真正請求處理的工作,通過這個方法使Request轉化爲Result結果集
    Query query = request.getResource().getQuery();

    query.setPageRequest(request.getPageRequest());//根據Rquest參數設置Query參數
    query.setSortRequest(request.getSortRequest());
    query.setRenderer(request.getRenderer());

    // If the request body exists, copy the requstInfoProperties from it.  This map should contain
    // the _directives_ specified in the request.
    RequestBody body = request.getBody();
    if(body != null) {
      query.setRequestInfoProps(body.getRequestInfoProperties());
    }

    try {
      addFieldsToQuery(request, query);//向提供的查詢query裏添加部分響應字段。
    } catch (IllegalArgumentException e) {
      return new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST, e.getMessage()));
    }

    Result result;
    Predicate p = null;
    try {
      p = request.getQueryPredicate();
      query.setUserPredicate(p);

      result = query.execute();//query進行execute執行操作,返回result結果,核心方法
      result.setResultStatus(new ResultStatus(ResultStatus.STATUS.OK));
    } catch (AuthorizationException e) {
      result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.FORBIDDEN, e.getMessage()));
    } catch (SystemException e) {
      result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.SERVER_ERROR, e));
    } catch (NoSuchParentResourceException e) {
      result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.NOT_FOUND, e.getMessage()));
    } catch (UnsupportedPropertyException e) {
      result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST, e.getMessage()));
    } catch (NoSuchResourceException e) {
      if (p == null) {
        // no predicate specified, resource requested by id
        result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.NOT_FOUND, e.getMessage()));
      } else {
        // resource(s) requested using predicate
        result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.OK, e));
        result.getResultTree().setProperty("isCollection", "true");
      }
    } catch (IllegalArgumentException e) {
      result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST,
          "Invalid Request: " + e.getMessage()));
      LOG.error("Bad request: ", e);
    }  catch (RuntimeException e) {
      if (LOG.isErrorEnabled()) {
        LOG.error("Caught a runtime exception executing a query", e);
      }
      //result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.SERVER_ERROR, e));
      throw e;
    }
    return result;
  }

Request如何到Result?

handleReques()中的query.execute()爲核心方法

此方法爲Query接口方法,QueryImpl實現了它

  @Override
  public Result execute()
      throws UnsupportedPropertyException,
             SystemException,
             NoSuchResourceException,
             NoSuchParentResourceException {
    queryForResources();
    return getResult(null);
  }

3.1.4.1、QueryImpl.queryForResources()

如下圖、由此看出,是queryForResources()查詢出的資源列表才最終拼接成Result對象

queryForResources()中,核心方法爲doQuery()方法

  /**
   * Query the cluster controller for the top level resources.
   */
  private void queryForResources()
      throws UnsupportedPropertyException,
      SystemException,
      NoSuchResourceException,
      NoSuchParentResourceException {

    Resource.Type resourceType    = getResourceDefinition().getType();
    Predicate     queryPredicate  = createPredicate(getKeyValueMap(), processUserPredicate(userPredicate));

    // must occur after processing user predicate and prior to creating request
    finalizeProperties();

    Request request = createRequest();

    // use linked hash sets so that we maintain insertion and traversal order
    // in the event that the resource provider already gave us a sorted set
    // back
    Set<Resource> resourceSet = new LinkedHashSet<>();
    Set<Resource> providerResourceSet = new LinkedHashSet<>();
    //doQuery方法向Clustercontroller查詢Request所指定的一級資源列表
    QueryResponse queryResponse = doQuery(resourceType, request, queryPredicate, true);

    // If there is a page request and the predicate does not contain properties
    // that need to be set
    if ((pageRequest != null || sortRequest != null ) &&
      !populateResourceRequired(resourceType)) {
      PageResponse pageResponse = clusterController.getPage(resourceType,
          queryResponse, request, queryPredicate, pageRequest, sortRequest);

      // build a new set
      for (Resource r : pageResponse.getIterable()) {
        resourceSet.add(r);
        providerResourceSet.add(r);
      }
    } else {
      resourceSet.addAll(queryResponse.getResources());
      providerResourceSet.addAll(queryResponse.getResources());
    }

    populatedQueryResults.put(null, new QueryResult(
      request, queryPredicate, userPredicate, getKeyValueMap(), new QueryResponseImpl(resourceSet)));

    queryResults.put(null, new QueryResult(
      request, queryPredicate, userPredicate, getKeyValueMap(), queryResponse));

    if (renderer.requiresPropertyProviderInput()) {
      clusterController.populateResources(resourceType, providerResourceSet, request, queryPredicate);
    }

    // Optimization:
    // Currently the steps executed when sub-resources are requested are:
    //   (1) Get *all* top-level resources
    //   (2) Populate all top-level resources
    //   (3) Query for and populate sub-resources of *all* top-level resources
    //   (4) Apply pagination and predicate on resources from above
    //
    // Though this works, it is very inefficient when either:
    //   (a) Predicate does not apply to sub-resources
    //   (b) Page request is present
    // It is inefficient because we needlessly populate sub-resources that might not get
    // used due to their top-level resources being filtered out by the predicate and paging
    //
    // The optimization is to apply the predicate and paging request on the top-level resources
    // directly if there are no sub-resources predicates.
    if ((pageRequest != null || userPredicate != null) && !hasSubResourcePredicate() && populateResourceRequired(resourceType)) {
      QueryResponse newResponse = new QueryResponseImpl(resourceSet, queryResponse.isSortedResponse(), queryResponse.isPagedResponse(),
          queryResponse.getTotalResourceCount());
      PageResponse pageResponse = clusterController.getPage(resourceType, newResponse, request, queryPredicate, pageRequest, sortRequest);
      // build a new set
      Set<Resource> newResourceSet = new LinkedHashSet<>();
      for (Resource r : pageResponse.getIterable()) {
        newResourceSet.add(r);
      }
      populatedQueryResults.put(null, new QueryResult(request, queryPredicate, userPredicate, getKeyValueMap(), new QueryResponseImpl(newResourceSet)));
    }

    queryForSubResources();
  }

3.1.4.2、QueryImpl.doQuery()

用ClusterController去查詢資源列表

 /**
   * Query the cluster controller for the resources.
   *
   * @param type                the resource type
   * @param request             the request information
   * @param predicate           the predicate
   * @param checkEmptyResponse  true if an empty query response can trigger a NoSuchResourceException
   *
   * @return the result of the cluster controller query
   *
   * @throws NoSuchResourceException if a specific resource was asked for and not found and checkEmptyResponse == true
   */
  private QueryResponse doQuery(Resource.Type type, Request request, Predicate predicate, boolean checkEmptyResponse)
      throws UnsupportedPropertyException,
      SystemException,
      NoSuchResourceException,
      NoSuchParentResourceException {

    if (LOG.isDebugEnabled()) {
      LOG.debug("Executing resource query: {} where {}", request, predicate);
    }
    //用ClusterController去查詢資源列表
    QueryResponse queryResponse = clusterController.getResources(type, request, predicate);

    if (checkEmptyResponse && queryResponse.getResources().isEmpty()) {

      // If this is not a collection request then we must throw
      // NoSuchResourceException (404 response) for an empty query result
      if(!isCollectionResource()) {
        throw new NoSuchResourceException(
            "The requested resource doesn't exist: " + type + " not found where " + predicate + ".");
      }
    }
    return queryResponse;
  }

query -> controller層

3.1.4.3、clusterControllerImpl.getResources()

如下圖、getResources()中2個核心功能點爲

  • 封裝資源的privider對象
  • privider對象去查詢資源,然後返回一個QueryResponse對象
@Override
  public QueryResponse getResources(Type type, Request request, Predicate predicate)
      throws UnsupportedPropertyException, NoSuchResourceException,
             NoSuchParentResourceException, SystemException {
    QueryResponse queryResponse = null;
	// 1、封裝資源的ExtendedResourceProviderWrapper對象  provider
    ExtendedResourceProviderWrapper provider = ensureResourceProviderWrapper(type);
    ensurePropertyProviders(type);

    if (provider != null) {
      if (LOG.isDebugEnabled()) {
        LOG.debug("Using resource provider {} for request type {}", provider.getClass().getName(), type);
      }
      // make sure that the providers can satisfy the request
      checkProperties(type, request, predicate);
   	  //2、privider對象去查詢資源
      //queryForResources方法是provider調用的,ExtendedResourceProviderWrapper是一個內部類。
      // get the resources---》
      queryResponse = provider.queryForResources(request, predicate);
    }
    return queryResponse == null ? new QueryResponseImpl(Collections.emptySet()) : queryResponse;
  }

3.1.4.4、clusterControllerImpl.queryForResources()

如下圖、queryForResources()中getResources()是ResourceProvider接口的一個方法

    @Override
    public QueryResponse queryForResources(Request request, Predicate predicate)
        throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
      return extendedResourceProvider == null ?
          new QueryResponseImpl(resourceProvider.getResources(request, predicate)) ://(resourceProvider)去獲取資源列表
          extendedResourceProvider.queryForResources(request, predicate);
    }

controller層->provider

ResourceProvider接口,顧名思義,資源提供者接口,將controller層的資源請求調用通過各個ResourceProvider的實現類來實現getResources的動作事件

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-nU4nbLW0-1591958373708)(D:\Work\CompanyFiles\AsiaInfo\AmbariRD\Ambari\Ambari_REST_api源碼調用過程.assets\image-20200612175934892.png)]

3.1.4.5、HostComponentResourceProvider.getResources()

HostComponentResourceProvider類是進行hostcomponent資源的獲取

如下圖、HostComponentResourceProvider類中的getResources()方法,通過調用findResources()返回一個Set

  @Override
  public Set<Resource> getResources(Request request, Predicate predicate)
      throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {

    final Set<ServiceComponentHostRequest> requests = new HashSet<>();

    for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
      requests.add(getRequest(propertyMap));
    }
    //獲取資源列表---》
    return findResources(request, predicate, requests);
  }

3.1.4.6、HostComponentResourceProvider.findResources()

  private Set<Resource> findResources(Request request, final Predicate predicate,
                                      final Set<ServiceComponentHostRequest> requests)
          throws SystemException, NoSuchResourceException, NoSuchParentResourceException {
    Set<Resource> resources = new HashSet<>();
    Set<String> requestedIds = getRequestPropertyIds(request, predicate);
    // We always need host_name for sch
    requestedIds.add(HOST_NAME);
    //AmbariManagementController獲取Request對應的集羣CLuster,Cluster在Ambari-server啓動是初始化,其儲存了相應host列表
    Set<ServiceComponentHostResponse> responses = getResources(new Command<Set<ServiceComponentHostResponse>>() {
      @Override
      public Set<ServiceComponentHostResponse> invoke() throws AmbariException {
        return getManagementController().getHostComponents(requests);//獲取HostComponents--》》
      }
    });

    for (ServiceComponentHostResponse response : responses) {
      Resource resource = new ResourceImpl(Resource.Type.HostComponent);
      setResourceProperty(resource, CLUSTER_NAME,
              response.getClusterName(), requestedIds);
      setResourceProperty(resource, SERVICE_NAME,
              response.getServiceName(), requestedIds);
      setResourceProperty(resource, COMPONENT_NAME,
              response.getComponentName(), requestedIds);
      setResourceProperty(resource, DISPLAY_NAME,
              response.getDisplayName(), requestedIds);
      setResourceProperty(resource, HOST_NAME,
              response.getHostname(), requestedIds);
      setResourceProperty(resource, PUBLIC_HOST_NAME,
          response.getPublicHostname(), requestedIds);
      setResourceProperty(resource, STATE,
              response.getLiveState(), requestedIds);
      setResourceProperty(resource, DESIRED_STATE,
              response.getDesiredState(), requestedIds);
      setResourceProperty(resource, VERSION, response.getVersion(),
          requestedIds);
      setResourceProperty(resource, DESIRED_STACK_ID,
              response.getDesiredStackVersion(), requestedIds);
      setResourceProperty(resource, ACTUAL_CONFIGS,
              response.getActualConfigs(), requestedIds);
      setResourceProperty(resource, STALE_CONFIGS,
              response.isStaleConfig(), requestedIds);
      setResourceProperty(resource, RELOAD_CONFIGS,
              response.isReloadConfig(), requestedIds);
      setResourceProperty(resource, UPGRADE_STATE,
              response.getUpgradeState(), requestedIds);
      setResourceProperty(resource, DESIRED_REPOSITORY_VERSION,
          response.getDesiredRepositoryVersion(), requestedIds);

      if (response.getAdminState() != null) {
        setResourceProperty(resource, DESIRED_ADMIN_STATE,
                response.getAdminState(), requestedIds);
      }

      if (null != response.getMaintenanceState()) {
        setResourceProperty(resource, MAINTENANCE_STATE,
                response.getMaintenanceState(), requestedIds);
      }

      resources.add(resource);
    }
    return resources;
  }

provider層->controller實現層

3.1.4.7、AmbariManagementControllerImpl.getHostComponents()

@Override
public Set<ServiceComponentHostResponse> getHostComponents(
    Set<ServiceComponentHostRequest> requests, boolean statusOnly) throws AmbariException {
  LOG.debug("Processing requests: {}", requests);
  Set<ServiceComponentHostResponse> response =
      new HashSet<>();
  for (ServiceComponentHostRequest request : requests) {
    try {
      response.addAll(getHostComponents(request, statusOnly));//getHostComponents---》獲取HostComponents資源
    } catch (ServiceComponentHostNotFoundException | ServiceComponentNotFoundException | 
   。。。。。
             
        ↓

		↓     
             
             
 private Set<ServiceComponentHostResponse> getHostComponents(
      ServiceComponentHostRequest request, boolean statusOnly) throws AmbariException {
    LOG.debug("Processing request {}", request);

    if (request.getClusterName() == null
        || request.getClusterName().isEmpty()) {
      IllegalArgumentException e = new IllegalArgumentException("Invalid arguments, cluster name should not be null");
      LOG.debug("Cluster not specified in request", e);
      throw e;
    }

    final Cluster cluster;
    try {
      cluster = clusters.getCluster(request.getClusterName());//這裏就調用Cluster實現類了
    } catch (ClusterNotFoundException e) {
      LOG.error("Cluster not found ", e);
      throw new ParentObjectNotFoundException("Parent Cluster resource doesn't exist", e);
    }

    if (request.getHostname() != null) {
      try {
        if (!clusters.getClustersForHost(request.getHostname()).contains(cluster)) {
          // case where host exists but not associated with given cluster
         
          。。。。。。。。

3.1.4.8、ClusterImpl.getClustersForHost()

如下圖、ClusterImpl.getClustersForHost()方法返回Set

其中的getHostClustersMap()初始化時會從庫中獲取

@Override
public Set<Cluster> getClustersForHost(String hostname)
    throws AmbariException {
  Set<Cluster> clusters = getHostClustersMap().get(hostname);//getHostClustersMap()初始化時會從庫中獲取
  if(clusters == null){
    throw new HostNotFoundException(hostname);
  }
  if (LOG.isDebugEnabled()) {
    LOG.debug("Looking up clusters for hostname, hostname={}, mappedClusters={}", hostname, clusters.size());
  }
  return Collections.unmodifiableSet(clusters);

}

loadClustersAndHosts()中爲實體類的邏輯處理

controller實現層->Dao層

3.1.4.9、ClusterImpl調用鏈

getHostClustersMap() ->safelyLoadClustersAndHosts()->loadClustersAndHosts()

  /**
   * Gets the internal host/clusters map, ensuring that the relevant data has been previously initialized.
   *
   * @return a map of the requested data
   */
  private ConcurrentHashMap<String, Set<Cluster>> getHostClustersMap() {
    if (hostClustersMap == null) {
      safelyLoadClustersAndHosts();
    }
    return hostClustersMap;
  }

  synchronized private void safelyLoadClustersAndHosts() {
    if (clustersByName == null || clustersById == null ||
        hostsByName == null || hostsById == null ||
        hostClustersMap == null || clusterHostsMap1 == null) {
      loadClustersAndHosts();
    }
  }


 private void loadClustersAndHosts() {
    LOG.info("Initializing cluster and host data.");

    ConcurrentHashMap<String, Cluster> clustersByNameTemp = new ConcurrentHashMap<>();
    ConcurrentHashMap<Long, Cluster> clustersByIdTemp = new ConcurrentHashMap<>();
    ConcurrentHashMap<String, Host> hostsByNameTemp = new ConcurrentHashMap<>();
    ConcurrentHashMap<Long, Host> hostsByIdTemp = new ConcurrentHashMap<>();
    ConcurrentHashMap<String, Set<Cluster>> hostClustersMapTemp = new ConcurrentHashMap<>();
    ConcurrentHashMap<String, Set<Host>> clusterHostsMap1Temp = new ConcurrentHashMap<>();

    List<HostEntity> hostEntities = hostDAO.findAll();
    for (HostEntity hostEntity : hostEntities) {
      Host host = hostFactory.create(hostEntity);
      hostsByNameTemp.put(hostEntity.getHostName(), host);
      hostsByIdTemp.put(hostEntity.getHostId(), host);
    }
    hostsByName = hostsByNameTemp;
    hostsById = hostsByIdTemp;

    for (ClusterEntity clusterEntity : clusterDAO.findAll()) {
      Cluster currentCluster = clusterFactory.create(clusterEntity);
      clustersByNameTemp.put(clusterEntity.getClusterName(), currentCluster);
      clustersByIdTemp.put(currentCluster.getClusterId(), currentCluster);
      clusterHostsMap1Temp.put(currentCluster.getClusterName(), Collections.newSetFromMap(new ConcurrentHashMap<>()));
    }
    clustersByName = clustersByNameTemp;
    clustersById = clustersByIdTemp;

    for (HostEntity hostEntity : hostEntities) {
      Set<Cluster> cSet = Collections.newSetFromMap(new ConcurrentHashMap<Cluster, Boolean>());
      hostClustersMapTemp.put(hostEntity.getHostName(), cSet);

      Host host = getHostsByName().get(hostEntity.getHostName());
      for (ClusterEntity clusterEntity : hostEntity.getClusterEntities()) {
        clusterHostsMap1Temp.get(clusterEntity.getClusterName()).add(host);
        cSet.add(clustersByName.get(clusterEntity.getClusterName()));
      }
    }
    hostClustersMap = hostClustersMapTemp;
    clusterHostsMap1 = clusterHostsMap1Temp;
    // init host configs
    for (Long hostId : hostsById.keySet()) {
      try {
        m_agentConfigsHolder.get().initializeDataIfNeeded(hostId, true);
      } catch (AmbariException e) {
        LOG.error("Agent configs initialization was failed", e);
      }
    }
  }

如上圖、

例如clusterEntity.getClusterName()等API即爲從數據庫中查詢對應sql(基於JPA框架,Guice註解方式)

Dao層->Entity層->DB

3.1.4.10、HostDAO.findAll()

  @RequiresSession
  public List<HostEntity> findAll() {
    TypedQuery<HostEntity> query = entityManagerProvider.get().createQuery("SELECT host FROM HostEntity host", HostEntity.class);
    try {
      return query.getResultList();
    } catch (NoResultException e) {
      return Collections.emptyList();
    }
  }

至此,就將host列表查出來了,會進行一個page分頁,返回前端

具體的調用流程比較複雜,建議看目錄,我已經都調好格式了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章