facebook presto源码解读(part1)

本文介绍了Facebook Presto的源码解读第一部分,重点关注客户端与服务器的交互,包括Presto服务端代码的位置、PrestoServer启动、各种连接器模块的简介。详细阐述了客户端通过Presto类执行SQL语句,通过REST请求到服务端,服务端如何调度执行并分发任务到worker的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

facebook presto源码解读(part1)

——————原创文章,如有转载请说明出处

边学变卖,把代码查看结果汇报给各位读者,如有不对请指正。
part1主要是介绍整体的代码结构和大致的运行流程。

代码是在2016年8月从官网下载的。整体结构如下:

这里写图片描述

presto 客户端代码在presto-cli模块
但presto服务端代码不在presto-server,打开presto-server模块可以发现他采用maven的插件进行编译打包,改模块只有该规则文件。
presto服务端代码在presto-main模块。PrestoServer类启动服务器。

其他模块简述:
presto-base-jdbc 关系型数据库连接器的公共模块
presto-mysql mysql连接器用到了presto-base-jdbc
presto-jdbc jdbc客户端/另一种是cli
presto-hive-* hive连接器相关代码
presto-orc hive连接器读取hdfs的orc文件,并做了一些优化
presto-ml machine learning,未实现,打算ing
presto-kafka/cassadra/jmx 各种连接器

下面介绍客户端连接服务器进行sql语句的运行。主要运行ddl语句和Select语句,还有insert语句。
client入口代码在Presto类

package com.facebook.presto.cli;

import static io.airlift.airline.SingleCommand.singleCommand;

public final class Presto
{
   
    private Presto() {}

    public static void main(String[] args)
            throws Exception
    {
        Console console = singleCommand(Console.class).parse(args);

        if (console.helpOption.showHelpIfRequested() ||
                console.versionOption.showVersionIfRequested()) {
            return;
        }

        console.run();
    }
}

进入Console类的run方法,

 public void run()
    {
        ClientSession session = clientOptions.toClientSession();
        KerberosConfig kerberosConfig = clientOptions.toKerberosConfig();
        boolean hasQuery = !Strings.isNullOrEmpty(clientOptions.execute);
        boolean isFromFile = !Strings.isNullOrEmpty(clientOptions.file);

        if (!hasQuery || !isFromFile) {
            AnsiConsole.systemInstall();
        }

        initializeLogging(clientOptions.logLevelsFile);

        String query = clientOptions.execute;
        if (hasQuery) {
            query += ";";
        }

        if (isFromFile) {
            if (hasQuery) {
                throw new RuntimeException("both --execute and --file specified");
            }
            try {
                query = Files.toString(new File(clientOptions.file), UTF_8);
                hasQuery = true;
            }
            catch (IOException e) {
                throw new RuntimeException(format("Error reading from file %s: %s", clientOptions.file, e.getMessage()));
            }
        }

        try (QueryRunner queryRunner = QueryRunner.create(
                session,
                Optional.ofNullable(clientOptions.socksProxy),
                Optional.ofNullable(clientOptions.keystorePath),
                Optional.ofNullable(clientOptions.keystorePassword),
                Optional.ofNullable(clientOptions.krb5Principal),
                Optional.ofNullable(clientOptions.krb5RemoteServiceName),
                clientOptions.authenticationEnabled,
                kerberosConfig)) {
            if (hasQuery) {
                executeCommand(queryRunner, query, clientOptions.outputFormat);
            }
            else {
                runConsole(queryRunner, session);
            }
        }
    }

进入 executeCommand(queryRunner, query, clientOptions.outputFormat);方法:


  private static void executeCommand(QueryRunner queryRunner, String query, OutputFormat outputFormat)
    {
        StatementSplitter splitter = new StatementSplitter(query);
        for (Statement split : splitter.getCompleteStatements()) {
            if (!isEmptyStatement(split.statement())) {
                process(queryRunner, split.statement(), outputFormat, false);
            }
        }
        if (!isEmptyStatement(splitter.getPartialStatement())) {
            System.err.println("Non-terminated statement: " + splitter.getPartialStatement());
        }
    }

进入process方法,

    private static void process(QueryRunner queryRunner, String sql, OutputFormat outputFormat, boolean interactive)
    {
        try (Query query = queryRunner.startQuery(sql)) {
            query.renderOutput(System.out, outputFormat, interactive);

            ClientSession session = queryRunner.getSession();

            // update session properties if present
            if (!query.getSetSessionProperties().isEmpty() || !query.getResetSessionProperties().isEmpty()) {
                Map<String, String> sessionProperties = new HashMap<>(session.getProperties());
                sessionProperties.putAll(query.getSetSessionProperties());
                sessionProperties.keySet().removeAll(query.getResetSessionProperties());
                session = withProperties(session, sessionProperties);
            }

            // update transaction ID if necessary
            if (query.isClearTransactionId()) {
                session = stripTransactionId(session);
            }
            if (query.getStartedTransactionId() != null) {
                session = withTransactionId(session, query.getStartedTransactionId());
            }

            queryRunner.setSession(session);
        }
        catch (RuntimeException e) {
            System.err.println("Error running command: " + e.getMessage());
            if (queryRunner.getSession().isDebug()) {
                e.printStackTrace();
            }
        }
    }

进入Query query = queryRunner.startQuery(sql)方法发送rest请求到server端进行运行:


    public Query startQuery(String query)
    {
        return new Query(startInternalQuery(query));
    }
   public StatementClient startInternalQuery(String query)
    {
        return new StatementClient(httpClient, queryResultsCodec, session.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值