Presto Task 执行


向Presto集群提交的所有查询最终都会转化成为一个个单独的Task在每个Worker节点上执行。每个task的作用就是处理一个或者多个Split,然后将处理的结果输送给下游Stage中的task。

一、创建Task

创建Task主要是调用HttpRemoteTask类的构造方法创建一个对象,并调用其start方法,而start方法最终又会调用封装在HttpRemoteTask内部的httpClient,向特定的Worker Node上的TaskResource服务发起RESTful请求,从而在特定的Worker Node上启动一个对应的SqlTaskExecution进行数据处理和计算。因此创建Task分为两部分:

Client端

在Client端创建Task的过程分为两步:创建HttpRemoteTask对象和调用该对象的start方法。启动Task的主要代码都集中在方法sendUpdate中。

// HttpRemoteTask.java
private synchronized void sendUpdate()
{
    TaskStatus taskStatus = getTaskStatus();

	// 将当前Task需要处理的所有Split都封装成TaskSource列表
    List<TaskSource> sources = getSources();
	// 将执行计划序列化以通过http发送给worker节点
    Optional<byte[]> fragment = sendPlan.get() ? Optional.of(planFragment.toBytes(planFragmentCodec)) : Optional.empty();
    Optional<TableWriteInfo> writeInfo = sendPlan.get() ? Optional.of(tableWriteInfo) : Optional.empty();
	// 使用TaskSource列表、outputBuffers创建request请求
    TaskUpdateRequest updateRequest = new TaskUpdateRequest(
            session.toSessionRepresentation(),
            session.getIdentity().getExtraCredentials(),
            fragment,
            sources,
            outputBuffers.get(),
            writeInfo);
    byte[] taskUpdateRequestJson = taskUpdateRequestCodec.toBytes(updateRequest);

	// 生成一个Post请求
    HttpUriBuilder uriBuilder = getHttpUriBuilder(taskStatus);
    Request request = setContentTypeHeaders(isBinaryTransportEnabled, preparePost())
            .setUri(uriBuilder.build())
            .setBodyGenerator(createStaticBodyGenerator(taskUpdateRequestJson))
            .build();

    ResponseHandler responseHandler;
    if (isBinaryTransportEnabled) {
        responseHandler = createFullSmileResponseHandler((SmileCodec<TaskInfo>) taskInfoCodec);
    }
    else {
        responseHandler = createAdaptingJsonResponseHandler(unwrapJsonCodec(taskInfoCodec));
    }

    updateErrorTracker.startRequest();

    ListenableFuture<BaseResponse<TaskInfo>> future = httpClient.executeAsync(request, responseHandler);
    currentRequest = future;

    Futures.addCallback(
            future,
            new SimpleHttpResponseHandler<>(new UpdateResponseHandler(sources), request.getUri(), stats.getHttpResponseStats(), REMOTE_TASK_ERROR),
            executor);
}

需要将当前Task处理的数据都封装成TaskSource的列表,其中一个TaskSource代表一个Task处理的数据源,而Task处理的数据源又分为两类:Stage的输出和直接的数据源。对于Stage输出类型的数据源,TaskSource类封装了一个Stage的PlannodeId和根据该Stage上的TaskLocation生成的ScheduledSplit列表;对于直接的数据源,TaskSource类封装了一个数据源的PlannodeId和根据该数据源上的所有数据分片生成的ScheduledSplit列表。方法getSources会将两种数据源都封装成TaskSource,然后合并到一起。

Resource端

Coordinator向特定的Worker节点发送请求以启动一个SqlTaskExecution对象,用于执行Task计算任务,请求的处理均由类TaskResource完成。

// TaskResource.java
@POST
@Path("{taskId}")
@Consumes({APPLICATION_JSON, APPLICATION_JACKSON_SMILE})
@Produces({APPLICATION_JSON, APPLICATION_JACKSON_SMILE})
public Response createOrUpdateTask(@PathParam("taskId") TaskId taskId, TaskUpdateRequest taskUpdateRequest, @Context UriInfo uriInfo)
{
    Session session = taskUpdateRequest.getSession().toSession(sessionPropertyManager, taskUpdateRequest.getExtraCredentials());
    TaskInfo taskInfo = taskManager.updateTask(session,
            taskId,
            taskUpdateRequest.getFragment().map(planFragmentCodec::fromBytes),
            taskUpdateRequest.getSources(),
            taskUpdateRequest.getOutputIds(),
            taskUpdateRequest.getTableWriteInfo());

    if (shouldSummarize(uriInfo)) {
        taskInfo = taskInfo.summarize();
    }

    return Response.ok().entity(taskInfo).build();
}

对新建Task的RESTful的处理主要是由方法taskManager.updateTask来完成的,其实就是

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值