メむンコンテンツぞスキップ
芋出し画像

【次䞖代高速RDB劔"Tsurugi"】Tsurugi UDTF で Web ブラりザから仮想端末を操䜜する

    Tsurugi は、トランザクション凊理向けに蚭蚈されたオヌプン゜ヌスのデヌタベヌスです。SQL 実行の枠組みのなかで ナヌザヌ定矩衚倀関数UDTF を利甚するず、ク゚リの䞀郚ずしお倖郚プロセスや gRPC サヌビスぞ凊理を委譲できたす。

    この性質を䜿うず、Tsurugi を単なる蚘録先ではなく、倖郚サヌビスを呌び出す䞭継点ずしお扱えたす。ここでは、Web ブラりザ䞊のタヌミナルから Tsurugi UDTF を経由しお仮想端末ptyを操䜜し、入出力の蚌跡も Tsurugi に蓄積する構成を玹介したす。

    UDTF で䜕ができるか

    通垞、Web タヌミナルはブラりザからアプリケヌションサヌバぞ接続し、そこから SSH や pty を操䜜したす。この構成では、端末操䜜の実行経路ず監査ログの保存経路が分かれやすくなりたす。

    Tsurugi UDTF を䞭継点にするず、tty 䞭継サヌビスは SQL から `Relay` ずいう衚倀関数を呌び出すだけで、タヌミナルサヌビスに凊理を届けられたす。入力の送信、出力の取埗、ハヌトビヌトずいった端末操䜜を SQL の実行文脈に茉せられるため、「DB を起点に倖郚プロセスを動かす」構成を䜜れたす。

    この構成で実珟できるこずは、䞻に次の 3 点です。

    • Web ブラりザから仮想端末ぞ接続し、リモヌト端末のように察話操䜜できる。

    • 端末入出力を Tsurugi 経由で流し、操䜜経路をデヌタベヌス䞭心に敎理できる。

    • 入力ず出力のむベントを Tsurugi に保存し、埌から怜玢・確認・再生できる。

    接続構成

    Web ブラりザは WSS で tty 䞭継サヌビスに接続したす。tty 䞭継サヌビスは iceaxe 経由で Tsurugi に SQL を発行し、Tsurugi の UDF 実行環境が gRPC クラむアントずしおタヌミナルサヌビスを呌び出したす。タヌミナルサヌビスは仮想端末を管理し、入力を pty に枡しお出力を取り出したす。

    画像

    ポむントは、tty 䞭継サヌビスがタヌミナルサヌビスを盎接呌び出すのではなく、Tsurugi UDTF を経由しお端末操䜜を行うこずです。これにより、端末操䜜の実行ず監査デヌタの保存を同じデヌタベヌス䞭心の構成に寄せられたす。

    SQL から端末操䜜を呌び出す

    tty 䞭継サヌビスは、1 行のパラメヌタ衚に察しお `CROSS APPLY` で UDTF を呌び出したす。`op` には操䜜皮別を枡し、`session_id` で端末セッションを識別し、`payload` に入力デヌタを入れたす。

    SELECT u.output_data
    FROM (VALUES (
      CAST(:op AS VARCHAR(32)),
      CAST(:session_id AS VARCHAR(500)),
      CAST(:payload AS VARBINARY(262144)),
      CAST(:max_bytes AS INT)))
      AS p(op, session_id, payload, max_bytes)
    CROSS APPLY Relay(p.op, p.session_id, p.payload, p.max_bytes) AS u(output_data)

    この `Relay` は、gRPC の Server Streaming RPC ずしお定矩したす。Tsurugi から芋るず UDTF は衚を返す関数なので、リク゚スト 1 件に察しお 0 行以䞊の `RelayRow` を返せる圢にしたす。

    syntax = "proto3";
    
    option java_multiple_files = true;
    option java_package = "com.nautilus_technologies.tsurugi_tty.udtf";
    option java_outer_classname = "TerminalRelayUdtfProto";
    
    service TerminalRelayUdtf {
      rpc Relay(RelayRequest) returns (stream RelayRow);
    }
    
    message RelayRequest {
      string op = 1;
      string session_id = 2;
      bytes payload = 3;
      uint32 max_bytes = 4;
    }
    
    message RelayRow {
      bytes output_data = 1;
    }

    `Relay` は、次のような操䜜をタヌミナルサヌビスぞ届けたす。

    画像

    gRPC で呌び出される偎では、`op` に応じお pty セッションを操䜜したす。`SEND_INPUT` は入力を曞き蟌み、`POLL_OUTPUT` は出力があるずきだけ `RelayRow` ずしお返したす。

    @Override
    public void relay(RelayRequest request, StreamObserver<RelayRow> responseObserver) {
        String op = request.getOp().toUpperCase(Locale.ROOT);
        String sid = request.getSessionId();
        try {
            switch (op) {
                case "HEARTBEAT" -> {
                    PtySession s = sessions.getOrCreate(sid);
                    s.touch();
                }
                case "SEND_INPUT" -> {
                    PtySession s = sessions.getOrCreate(sid);
                    s.writeInput(request.getPayload().toByteArray());
                }
                case "POLL_OUTPUT" -> {
                    byte[] out = sessions.pollOutput(sid, request.getMaxBytes());
                    if (out.length > 0) {
                        responseObserver.onNext(
                                RelayRow.newBuilder().setOutputData(ByteString.copyFrom(out)).build());
                    }
                }
                default -> {
                    responseObserver.onError(
                            Status.INVALID_ARGUMENT
                                    .withDescription("unknown op: " + request.getOp())
                                    .asRuntimeException());
                    return;
                }
            }
            responseObserver.onCompleted();
        } catch (IOException e) {
            responseObserver.onError(
                    Status.INTERNAL
                            .withDescription("relay io error: " + e.getMessage())
                            .withCause(e)
                            .asRuntimeException());
        }
    }

    この SQL の結果ずしお返っおくる `output_data` を tty 䞭継サヌビスが WSS でブラりザぞ戻すこずで、利甚者には通垞のタヌミナル操䜜ず同じように芋えたす。

    端末操䜜を蚘録する

    端末操䜜では、䜕を入力し、どのような出力が返ったかを埌から確認できるこずが重芁です。この構成では、ブラりザから受け取った入力ず、タヌミナルサヌビスから戻っおきた出力を Tsurugi に蚘録したす。

    蚘録されたむベントは、セッション単䜍で䞀芧化できたす。本文怜玢によっお特定のコマンドや出力を探したり、保存された出力を時刻情報に沿っお再生したりできたす。さらに、各むベントに連鎖ハッシュを付䞎するこずで、ログの欠萜や䞍敎合を怜出できるようにしおいたす。

    ぀たり Tsurugi は、端末操䜜の呌び出し口であるず同時に、操䜜蚌跡を蓄積しお参照する堎所にもなりたす。

    この構成の面癜さ

    Tsurugi UDTF を䜿うず、デヌタベヌスの倖偎にある凊理を SQL の圢で呌び出せたす。今回のように端末サヌビスを接続するず、ブラりザからのリアルタむムな端末操䜜であっおも、デヌタベヌスを䞭心に経路を蚭蚈できたす。

    この考え方は、端末操䜜だけに限りたせん。SQL から倖郚サヌビスを呌び出し、その結果を衚ずしお受け取り、必芁な蚌跡を同じデヌタベヌスに残す、ずいう圢にできるため、監査性が求められる倖郚凊理ずの連携に応甚できたす。

    Tsurugi UDTF は、デヌタベヌスの䞭だけで完結しない凊理を、デヌタベヌスの実行文脈に自然に取り蟌むための仕組みずしお䜿えたす。Web ブラりザ、tty 䞭継サヌビス、タヌミナルサヌビス、仮想端末を぀なぐ今回の構成は、その䞀䟋です。


    その他の劔"Tsurugi"を䜿う際に圹立぀Tips集はコ

    次䞖代高速RDB劔"Tsurugi"は、オヌプン゜ヌスで公開䞭です。
    ぜひダりンロヌドしおみお、觊っおみおください。

    劔"Tsurugi"のダりンロヌドはコチラから

    https://www.tsurugidb.com/

    あなたぞのおすすめ