hdfs dfs -du -h /hbase/data/default/dal_hx_lct_700_800/999fdd6a2ed426fcb33d202195fdd7d2/i/ 16.0 G /hbase/data/default/dal_hx_lct_700_800/999fdd6a2ed426fcb33d202195fdd7d2/i/0e950ca090d54eb2b98abffc2e285cfa_SeqId_4_ 16.0 G /hbase/data/default/dal_hx_lct_700_800/999fdd6a2ed426fcb33d202195fdd7d2/i/bfc0c2e4fae84ba19ad1eaf78ea04967_SeqId_4_ 16.0 G /hbase/data/default/dal_hx_lct_700_800/999fdd6a2ed426fcb33d202195fdd7d2/i/e5f3675a6b0040faa695ec3b35b2e951_SeqId_4_ 6.1 G /hbase/data/default/dal_hx_lct_700_800/999fdd6a2ed426fcb33d202195fdd7d2/i/f5c2d2461e0f4eb58ed6c75aa1ae9ffa_SeqId_4_
JobLeaderIdService#addJob() /** * Add a job to be monitored to retrieve the job leader id. * 添加要监控的作业以检索作业领导者ID * @param jobId identifying the job to monitor * @throws Exception if the job could not be added to the service */ publicvoidaddJob(JobID jobId)throws Exception { Preconditions.checkNotNull(jobLeaderIdActions); LOG.debug("Add job {} to job leader id monitoring.", jobId); if (!jobLeaderIdListeners.containsKey(jobId)) { // 从ha中选择出合适的leader LeaderRetrievalServiceleaderRetrievalService= highAvailabilityServices.getJobManagerLeaderRetriever(jobId); JobLeaderIdListenerjobIdListener=newJobLeaderIdListener(jobId, jobLeaderIdActions, leaderRetrievalService); jobLeaderIdListeners.put(jobId, jobIdListener); }}
future.whenCompleteAsync( (Tuple2<G, S> result, Throwable failure) -> { if (failure != null) { if (failure instanceof CancellationException) { // we ignore cancellation exceptions because they originate from cancelling // the RetryingRegistration log.debug("Retrying registration towards {} was cancelled.", targetAddress); } else { // this future should only ever fail if there is a bug, not if the registration is declined onRegistrationFailure(failure); } } else { targetGateway = result.f0; // 成功后异步回调执行connection连接确认及TM slot资源上报 // 其异步注册的监听器为ResourceManagerRegistrationListener onRegistrationSuccess(result.f1); } }, executor);
return newRegistration; }
// 向RM的注册 publicvoidstartRegistration() { try { // trigger resolution of the resource manager address to a callable gateway final CompletableFuture<G> resourceManagerFuture;
if (FencedRpcGateway.class.isAssignableFrom(targetType)) { resourceManagerFuture = (CompletableFuture<G>) rpcService.connect( // rpc连接 targetAddress, fencingToken, targetType.asSubclass(FencedRpcGateway.class)); } else { resourceManagerFuture = rpcService.connect(targetAddress, targetType); } // upon success, start the registration attempts CompletableFuture<Void> resourceManagerAcceptFuture= resourceManagerFuture.thenAcceptAsync( (G result) -> { log.info("Resolved {} address, beginning registration", targetName); register(result, 1, initialRegistrationTimeout); //注册主体 // 其会调用ResourceManagerRegistration#invokeRegistration()来进行实际的注册 }, rpcService.getExecutor()); // upon failure, retry, unless this is cancelled ...... // 注册失败会重试 }
4、DispatcherRestEndpoint、WebMonitorEndpoint
web 界面展示接口相关,其主要初始化 web 相关的服务及接口;主要包括 jobmanager、taskmanager 信息及日志监控、web job submit 初始化、metric 监控指标、checkpoint 检查点、savepoint 保存点等等 web 界面可查询到的指标;并且将服务以 netty 其 handler 以及接口初始化 log 日志信息如下 (部分):
// we have to allow queued scheduling in Flip-6 mode because we need to request slots // from the ResourceManager jobGraph.setAllowQueuedScheduling(true);
JobManagerRunner#start() publicvoidstart()throws Exception { try { leaderElectionService.start(this); } catch (Exception e) { log.error("Could not start the JobManager because the leader election service did not start.", e); thrownewException("Could not start the leader election service.", e); } }
JobMaster#startJobExecution#startJobMasterServices privatevoidstartJobMasterServices()throws Exception { // start the slot pool make sure the slot pool now accepts messages for this leader slotPool.start(getFencingToken(), getAddress());
//TODO: Remove once the ZooKeeperLeaderRetrieval returns the stored address upon start // try to reconnect to previously known leader reconnectToResourceManager(newFlinkException("Starting JobMaster component."));
// job is ready to go, try to establish connection with resource manager // - activate leader retrieval for the resource manager // - on notification of the leader, the connection will be established and // the slot pool will start requesting slots resourceManagerLeaderRetriever.start(newResourceManagerLeaderListener()); }
Standalone Cluster 模式的启动流程
在 windows 或者 linux 环境下通过 /flink/bin/start-cluster.bat 或者 start-cluster.sh 来启动对应的 flink 集群 Standalone Cluster 模式;
简化shell启动脚本后,其组件实例化入口类主要为下:
1 2 3 4 5 6 7
case $DAEMON in (taskexecutor) CLASS_TO_RUN=org.apache.flink.runtime.taskexecutor.TaskManagerRunner (zookeeper) CLASS_TO_RUN=org.apache.flink.runtime.zookeeper.FlinkZooKeeperQuorumPeer (historyserver) CLASS_TO_RUN=org.apache.flink.runtime.webmonitor.history.HistoryServer (standalonesession) CLASS_TO_RUN=org.apache.flink.runtime.entrypoint.StandaloneSessionClusterEntrypoint (standalonejob) CLASS_TO_RUN=org.apache.flink.container.entrypoint.StandaloneJobClusterEntryPoint esac
/** * The yarn implementation of the resource manager. Used when the system is started * via the resource framework YARN. */ // 其内部主要持有的组件 以及 向yarn申请新container的方法 publicclassYarnResourceManagerextendsResourceManager<YarnWorkerNode\> implementsAMRMClientAsync.CallbackHandler { /** Default heartbeat interval between this resource manager and the YARN ResourceManager. */ privatefinalint yarnHeartbeatIntervalMillis; privatefinal Configuration flinkConfig; privatefinal YarnConfiguration yarnConfig; privatefinalint numberOfTaskSlots; privatefinalint defaultTaskManagerMemoryMB; privatefinalint defaultCpus; /** The heartbeat interval while the resource master is waiting for containers. */ privatefinalint containerRequestHeartbeatIntervalMillis; /** Client to communicate with the Resource Manager (YARN's master). */ private AMRMClientAsync<AMRMClient.ContainerRequest> resourceManagerClient; // Yarn ResourceManager Client /** Client to communicate with the Node manager and launch TaskExecutor processes. */ private NMClient nodeManagerClient; // /** The number of containers requested, but not yet granted. */ privateint numPendingContainerRequests; privatefinalMap<ResourceProfile, Integer> resourcePriorities=newHashMap<>(); privatefinal Collection<ResourceProfile> slotsPerWorker; privatefinal Resource resource; ...... }
// make sure we transmit the request fast and receive fast news of granted allocations resourceManagerClient.setHeartbeatInterval(containerRequestHeartbeatIntervalMillis); numPendingContainerRequests++; log.info("Requesting new TaskExecutor container with resources {}. Number pending requests {}.", resource, numPendingContainerRequests);
}
// 申请到container资源后,异步回调 @Override publicvoidonContainersAllocated(List<Container> containers) { runAsync(() -> { final Collection<AMRMClient.ContainerRequest> pendingRequests = getPendingRequests(); final Iterator<AMRMClient.ContainerRequest> pendingRequestsIterator = pendingRequests.iterator();
for (Container container : containers) { log.info( "Received new container: {} - Remaining pending container requests: {}", container.getId(), numPendingContainerRequests); if (numPendingContainerRequests > 0) { removeContainerRequest(pendingRequestsIterator.next()); finalStringcontainerIdStr= container.getId().toString(); finalResourceIDresourceId=newResourceID(containerIdStr); workerNodeMap.put(resourceId, newYarnWorkerNode(container)); try { // Context information used to start a TaskExecutor Java process // 构建TaskManager启动的ContainerLaunchContext信息 ContainerLaunchContexttaskExecutorLaunchContext= createTaskExecutorLaunchContext( container.getResource(), containerIdStr, container.getNodeId().getHost()); // 远程提交执行 启动TaskManager nodeManagerClient.startContainer(container, taskExecutorLaunchContext); } catch (Throwable t) { log.error("Could not start TaskManager in container {}.", container.getId(), t); // release the failed container workerNodeMap.remove(resourceId); resourceManagerClient.releaseAssignedContainer(container.getId()); // and ask for a new one requestYarnContainerIfRequired(); } } else { // return the excessive containers log.info("Returning excess container {}.", container.getId()); resourceManagerClient.releaseAssignedContainer(container.getId()); } } // if we are waiting for no further containers, we can go to the // regular heartbeat interval if (numPendingContainerRequests <= 0) { resourceManagerClient.setHeartbeatInterval(yarnHeartbeatIntervalMillis); } });
// set a special environment variable to uniquely identify this container taskExecutorLaunchContext.getEnvironment() .put(ENV_FLINK_CONTAINER_ID, containerId); taskExecutorLaunchContext.getEnvironment() .put(ENV_FLINK_NODE_ID, host); return taskExecutorLaunchContext;
impala darmon running on datanode cache some of the data that is in HDFS
why fast
why Impala is faster than Hive in Query processing? Below are the some key points.
While processing SQL-like queries, Impala does not write intermediate results on disk(like in Hive MapReduce); instead full SQL processing is done in memory, which makes it faster.
With Impala, the query starts its execution instantly compared to MapReduce, which may take significant time to start processing larger SQL queries and this adds more time in processing.
Impala Query Planner uses smart algorithms to execute queries in multiple stages in parallel nodes to provide results faster, avoiding sorting and shuffle steps, which may be unnecessary in most of the cases.
Impala has information about each data block in HDFS, so when processing the query, it takes advantage of this knowledge to distribute queries more evenly in all DataNodes.
There exists Impala daemon, which runs on each DataNode. These are responsible for processing queries.When query submitted, impalad(Impala daemon) reads and writes to data file and parallelizes the query by distributing the work to all other Impala nodes in the Impala cluster.
Another key reason for fast performance is that Impala first generates assembly-level code for each query. The assembly code executes faster than any other code framework because while Impala queries are running natively in memory, having a framework will add additional delay in the execution due to the framework overhead.
Impala doesn’t provide fault-tolerance compared to Hive
so if there is a problem during your query then it’s gone.
Definitely for ETL type of jobs where failure of one job would be costly I would recommend Hive, but Impala can be awesome for small ad-hoc queries, for example for data scientists or business analysts who just want to take a look and analyze some data without building robust jobs. Also from my personal experience, Impala is still not very mature, and I’ve seen some crashes sometimes when the amount of data is larger than available memory.
This means if your join, sort, or group by didn’t fit in memory, Impala would just kill the query. No warning. Just dead. Hive would never do that because it’s underlying processing architecture has no problem doing that.
Impala uses MPP(massively parallel processing) unlike Hive which uses MapReduce under the hood, which involves some initial overheads (as Charles sir has specified). Massively parallel processing is a type of computing that uses many separate CPUs running in parallel to execute a single program where each CPU has it’s own dedicated memory. The very fact that Impala, being MPP based, doesn’t involve the overheads of a MapReduce jobs viz. job setup and creation, slot assignment, split creation, map generation etc., makes it blazingly fast.
But that doesn’t mean that Impala is the solution to all your problems. Being highly memory intensive (MPP), it is not a good fit for tasks that require heavy data operations like joins etc., as you just can’t fit everything into the memory. This is where Hive is a better fit.
In my current job we used to make all the querys with Impala, the biggest query (like 800 million rows after 8 joins) was taking from 2 to 20 mins (depending if the tables where already on memory or not) I migrate that Query to Hive, partitioned the tables and create buckets on them, now it takes 3–4 mins, It may be a few more seconds than the best 2 mins with Impala but it’s much more fast if we consider that most of the time Impala takes 12–18 mins.
Hypothesis If we have good enough column-oriented DBMS, we could store all our data in non-aggregated form (raw pageviews and sessions) and generate all the reports on the fly, to allow infinite customization.