Доступ к MatrixGate с помощью языков программирования

В этом документе описывается, как использовать API-интерфейс для подключения к MatrixGate и обеспечить высокоскоростной импорт данных.


1 API MatrixGate

MatrixGate предоставляет внешнему миру HTTP API, позволяя различным языкам программирования импортировать данные в базу данных YMatrix через HTTP-интерфейс.

Формат протокола и коды ответов MatrixGate приведены ниже:

Формат протокола HTTP MatrixGate

Тип протокола Формат протокола Использование и примеры
URL http://\:\ Указывает URL-адрес подключения mxgate
PATH / В настоящее время поддерживаются только /, все, что следует после /, игнорируется
HTTP-метод POST Поддерживается только POST для загрузки данных
HTTP-заголовок Content-Encoding: gzip Поддерживается сжатие содержимого тела запроса gzip
Content-Type: text/plain Поддерживается формат text/plain
Тело HTTP SchemaName.TableName
Timestamp|ID|C1|C2|..|Cn
Формат тела: первая строка — целевая таблица для загрузки данных. Имя схемы (SchemaName) можно опустить, по умолчанию используется Public. Имя таблицы (TableName) обязательно. Начиная со второй строки — строки временных рядов. Каждая строка соответствует одной строке целевой таблицы. Столбцы разделяются символом |, строки — символом \n. Первое поле каждой строки — временная метка (timestamp), формат UNIX-времени с точностью до секунд (см. описание параметра --time-format). Второе поле — TagID, целое число. Поля с третьего до последнего соответствуют столбцам целевой таблицы. Рекомендуется, чтобы DDL-определение целевой таблицы также следовало порядку столбцов (Timestamp, TagID, C1, C2,…, Cn)

Коды ответов HTTP MatrixGate

Код ответа Значение кода ответа Примечания
200 StatusOK Часть данных имеет неправильный формат. В теле ответа будет указан номер строки с ошибкой и сообщение об ошибке, например:
At line: 2
missing data for column "c3"
204 StatusNoContent Данные успешно загружены в MatrixGate
400 StatusBadRequest Ошибка запроса данных, например: неверный формат тела POST, отсутствие целевой таблицы, несоответствие формата сжатия данным в HTTP-заголовке и т.д.
405 StatusMethodNotAllowed Запрос не является POST
408 StatusTimeout Таймаут запроса
500 StatusIntervalServerError Ошибка базы данных, неудачная загрузка данных. В теле ответа содержится подробная информация об ошибке
503 StatusServiceUnavailable MatrixGate отклоняет запросы, например: превышено максимальное количество подключений или MatrixGate завершает работу


2 Пример командной строки HTTP API MatrixGate

  • Сначала создайте таблицу testtable в базе данных demo.
    CREATE TABLE testtable (time TIMESTAMP WITH TIME ZONE, tagid INT, c1 INT, c2 INT, c3 INT)
    DISTRIBUTED BY (tagid);
  • Создайте конфигурационный файл mxgate.conf.
    mxgate config --db-database testdb \
                --db-master-host localhost \
                --db-master-port 5432 \
                --db-user mxadmin \
                --db-password 123123 \
                --target public.testtable \
                --format csv \
                --time-format unix-second \
                --delimiter '|' \
                --parallel 256 \
                --stream-prepared 3 \
                --interval 250 \
                --transform plain \
                > mxgate.conf
  • Отредактируйте файл загрузки данных data.txt со следующим содержанием:
    public.testtable
    1603777821|1|101|201|301
    1603777822|2|102|202|302
    1603777823|3|103|203|303
  • Запустите mxgate и укажите созданный конфигурационный файл mxgate.conf.
    $ mxgate --config mxgate.conf
  • Отправьте HTTP-запрос для загрузки данных.
    $ curl http://localhost:8086/ -X POST -H 'Content-Type: text/plain' --data-binary "@data.txt"
  • Подключитесь к базе данных и проверьте, успешно ли загружены данные.
    demo=# SELECT extract(epoch FROM "time"), * FROM testtable;
    date_part  |          time          | tagid | c1  | c2  | c3
    ----------------------------------------------------------------------------------------------------------------------------------
    1603777821 | 2020-10-27 13:50:21+08 |     1 | 101 | 201 | 301
    1603777822 | 2020-10-27 13:50:22+08 |     2 | 102 | 202 | 302
    1603777823 | 2020-10-27 13:50:23+08 |     3 | 103 | 203 | 303
    (3 rows)


3 Подключение к MatrixGate с помощью языков программирования

3.1 Подключение к MatrixGate на Java

3.1.1 SDK MatrixGate для Java

SDK (Software Development Kit) — это комплект инструментов разработки программного обеспечения, который позволяет разработчикам сосредоточиться на бизнес-логике, значительно повышая эффективность и удобство разработки.

  1. Подключение зависимостей SDK

Вы можете добавить JAR-пакет SDK одним из следующих способов:

(1). Получить напрямую из удалённого репозитория Maven
(2). Получить напрямую из удалённого репозитория Gradle
(3). Вручную скачать JAR-файл локально и затем импортировать его

Примечание!
Выберите любой из вышеперечисленных способов. Рекомендуется использовать (1) или (2) для прямого подключения SDK из удалённых репозиториев Maven или Gradle — это эффективно и удобно. Для способа (3) см. MatrixGate FAQ: 21. Рекомендуется выполнить поиск по ключевому слову JAVA SDK, так как этот способ используется редко, здесь он подробно не рассматривается.

(1). Вызов удалённого репозитория Maven для автоматической загрузки пакетов SDK

Настройте следующие зависимости в файле pom.xml вашего Java-проекта.

<dependencies>
    <dependency>
        <groupId>cn.ymatrix</groupId>
        <artifactId>mxgate-sdk-java</artifactId>
        <version>1.1.2</version>
    </dependency>
</dependencies>

(2). Использование удалённого репозитория Gradle для подключения зависимостей SDK

repositories {
    mavenCentral()
}

dependencies {
    implementation 'cn.ymatrix:mxgate-sdk-java:1.0.20'
}
  1. Запуск mxgate

YMatrix поддерживает запись данных через gRPC и HTTP. Подробности приведены ниже:

  • Запуск mxgate (источник gRPC)

Примечание!
Необходимо использовать версию YMatrix, поддерживающую gRPC, то есть v4.6.1 и выше.

Создайте конфигурационный файл mxgate_grpc.conf на Master-узле и запустите mxgate.

Примечание!
Перед использованием mxgate необходимо предварительно создать таблицы в базе данных. В примере хост Master — mdw, база данных — demo, таблица данных — test_table_transfer.

Код приведён ниже:

# Create mxgate config file
[mxadmin@mdw ~]$ mxgate config \
    --source grpc \
    --db-database demo \
    --target public.test_table_transfer \
    --time-format raw \
    --grpc-port 8087 \
    --format csv \
    > mxgate_grpc.conf

# Start mxgate
[mxadmin@mdw ~]$ mxgate start --config mxgate_grpc.conf

Как показано в примере, для записи данных в mxgate с помощью SDK необходимо указать, что параметр source mxgate — grpc, а format — csv. Кроме того, поскольку SDK должен знать, куда записывать данные, необходимо указать номер порта grpc-port в конфигурационном файле (в примере — 8087).

  • Запуск mxgate (источник HTTP)

Примечание!
При запуске mxgate через HTTP всё равно необходимо указывать номер порта gRPC mxgate, поскольку SDK по-прежнему получает метаинформацию о таблицах базы данных из mxgate по протоколу gRPC, но способ записи данных переключается на HTTP.

Создайте конфигурационный файл mxgate_http.conf на Master-узле и запустите mxgate. В примере имя хоста Master — mdw, код приведён ниже:

# Create the mxgate config file.
[mxadmin@mdw ~]$ mxgate config \
    --source http \
    --db-database demo \
    --target public.test_table_transfer \
    --time-format raw \
    --grpc-port 8087 \
    --format csv \
    > mxgate_http.conf

# Start mxgate
[mxadmin@mdw ~]$ mxgate start --config mxgate_http.conf
  1. Отправка данных в mxgate с помощью SDK

На этом этапе будут рассмотрены два метода передачи: асинхронный и синхронный. Выберите подходящий в зависимости от ваших потребностей.

Структура примера таблицы:

            Partitioned table "public.test_table_transfer"
 Column |            Type             | Collation | Nullable | Default
--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 ts     | timestamp without time zone |           |          |
 tag    | integer                     |           | not null |
 c1     | double precision            |           |          |
 c2     | double precision            |           |          |
 c3     | double precision            |           |          |
 c4     | double precision            |           |          |
 c5     | text                        |           |          |
 c6     | text                        |           |          |
 c7     | text                        |           |          |
 c8     | text                        |           |          |
Partition key: RANGE (ts)

Сначала выполните глобальную инициализацию:

// Set the log level, default INFO.
MxLogger.loggerLevel(LoggerLevel.INFO);
// The log will be output to stdout by default. If you do not want to output, you can pass false in the following API.
MxLogger.enableStdout(true);
// The default log file path and naming format of SDK is /tmp/mxgate_sdk_java_2022-08-26_133403.log,
// Users can customize the file path and file name of the output log file.
MxLogger.writeToFile("/tmp/mxgate_sdk_java.log");
  • Асинхронная отправка данных с помощью SDK

Асинхронная отправка: кортеж (Tuple) помещается во внутреннюю очередь SDK, а затем данные отправляются по асинхронному HTTP-запросу.
Сначала необходимо запустить MxBuilder, который работает в режиме одиночки (singleton) и является глобально уникальным.

Примечание!
Создавайте MxBuilder только один раз в проекте. Соответствующую конфигурацию можно выполнить до инициализации MxBuilder.

MxBuilder builder = MxBuilder.newBuilder()
.withDropAll(false) // If used for testing, set to true to drop data instead of sending to mxgate; set to false to send data to mxgate
.withCacheCapacity(100000) // Size of the queue for temporarily storing tuples in batches
.withCacheEnqueueTimeout(2000) // Timeout for tuples to be enqueued if the queue is full. Throws IllegalStateException if exceeded
.withConcurrency(10) // Number of threads writing data to mxgate concurrently
.withRequestTimeoutMillis(3000) // Timeout for each data write request (in milliseconds)
.withMaxRetryAttempts(3) // Number of retries for each write request if an issue occurs
.withRetryWaitDurationMillis(3000) // Interval between retries (currently fixed)
.withRequestType(RequestType.WithHTTP) // SDK supports sending data to mxgate via HTTP and gRPC. Corresponding configurations are: RequestType.WithHTTP, RequestType.WithGRPC
.withCircuitBreaker() // Use the built - in circuit breaker. If the failure rate or slow request rate reaches the threshold, it will be activated. After activation, data sending to mxgate will be paused for 30 seconds, and tuples cannot be appended
.withMinimumNumberOfCalls(1) // Minimum number of calls for the circuit breaker to take effect (must be >= 1, default is 10)
.withSlidingWindowSize(10) // Size of the sliding window for calculating the failure rate (must be >= 1, default is 100)
.withFailureRateThreshold(60.0f) // Failure rate threshold (must be >0 and <= 100). If the failure rate reaches this threshold, the circuit breaker will be activated
.withSlowCallDurationThresholdMillis(1000) // Threshold for slow request duration (milliseconds). Requests exceeding this duration are considered slow (note that this duration should be less than the request timeout)
.withSlowCallRateThreshold(80.0f) // Slow request rate threshold. If the slow request rate reaches this threshold, the circuit breaker will be activated
// .withRequestAsync(true) // Uncomment this line to enable asynchronous mode for sending data to mxgate (optional)
// .withConcurrency(20) // Typically, asynchronous mode only requires tens of concurrency to achieve the same or even higher throughput as synchronous mode (optional)
// MxBuilder's builder pattern has added the following API to adjust the concurrency of CSV parallel transformation (at the MxClient Group level)
// .withCSVConstructionParallel(100) // (Supported from v1.1.0, uncomment this line to use)
.build();
// MxBuilder has added a singleton API. After MxBuilder is successfully built, you can obtain the globally unique singleton instance of MxBuilder at any location using the following API (supported from v1.1.2)
// MxBuilder.instance(); // (Supported from v1.1.2, uncomment this line to use)
// builder.getTupleCacheSize(); // Uncomment this line to get the number of remaining Tuples in the SDK's internal Tuple cache in real - time (optional)

Метод connect объекта Builder принимает четыре параметра:

(1). Имя хоста (IP-адрес) и номер порта процесса mxgate, где предоставляется конкретная служба, используется для получения данных и метаинформации о таблицах базы данных.
Например, при использовании HTTP-метода это http://localhost:8086/; при использовании gRPC-метода — localhost:8087.
(2). Схема.
(3). Имя таблицы.
(4). Коллбэк. Если Builder успешно подключается к mxgate, вызывается метод onSuccess и возвращается экземпляр MxClient для записи данных. При неудачном подключении вызывается onFailure, а failureMsg содержит причину сбоя.

Пример кода приведён ниже. Не забудьте заменить номер порта, имя схемы и имя таблицы на фактические значения.

// Asynchronous method (this feature is supported starting from v1.0.13)
builder.connect("http://localhost:8086/", "localhost:8087", "public", "test_table", new ConnectionListener() {
    @Override
    public void onSuccess(MxClient client) {
        sendData(client);
    }

    @Override
    public void onFailure(String failureMsg) {

    }
});

Через функцию обратного вызова onSuccess() интерфейса ConnectionListener можно получить экземпляр MxClient, а затем использовать API MxClient для реализации записи данных в mxgate.

// Synchronization method (this feature is supported starting from v1.0.13)
MxClient client = builder.connect(httpHost, gRPCHost, schema, table);
/* 
 * v1.1.0 improves the scalability of MxClient, and MxBuilder provides several new APIs. The MxClient obtained through this API belongs to a MxClient Group.
 * You can freely define the concurrency parameters of MxClient Group Number, Tuples cache capability, and TuplesConsumer through these APIs.
 * (This feature is supported starting from v1.1.0)
 */
// MxClient client = builder.connectWithGroup(dataSendingHost, metadataHost, schema, table, 10);
// MxClient client = builder.connectWithGroup(dataSendingHost, metadataHost, schema, table, 1, 1000, 3000, 10);// (This function starts with v1.1.0, if you use to remove the comment content of this line)

/* 
 * For APIs starting with skip, the process of connecting to back-end services to obtain database table meta information will be skipped when calling.
 * This type of MxClient can only obtain lightweight Tuples through generateEmptyTupleLite().
 * (This feature is supported starting from v1.1.0)
 */
// MxClient client = mxBuilder.skipConnectWithGroup(dataSendingHost, metadataHost, schema, table, delimiter, 1);
// MxClient client = mxBuilder.skipConnectWithGroup(dataSendingHost, metadataHost, schema, table, delimiter, 1, 1000, 3000, 1);

Примечание!
MxClient потокобезопасен, однако при использовании в многопоточной среде для достижения оптимальной производительности рекомендуется иметь отдельный MxClient в каждом потоке, то есть возвращать несколько экземпляров MxClient через несколько вызовов connect MxBuilder.


private void sendData(MxClient client) {
if (client != null) {
/*
* MxClient will accumulate a batch of Tuples as a micro batch and send them to mxgate.
* This API sets the waiting time accumulated for each microbatch, with a default of 2000 million seconds.
* That is, each 2s will try to send a batch of data to mxgate if the 2s time period is
* No data is written, no sending
*/
client.withIntervalToFlushMillis(5000);
    /*
     * Set how many Tuple bytes accumulated to be sent as a microbatch, even if the time has not been reached
     * The set flush interval, the accumulated micro-batch bytes will also be sent if it reaches the number of micro-batch bytes.
     * The time of flush interval has reached, and the number of bytes that are not accumulated enough to be set will also be sent
     */
    client.withEnoughBytesToFlush(500);

    /*
     * Compared withEnoughBytesToFlush, when appendTuple
     * Performance is improved because it avoids calculating the number of bytes.
     * Depending on the specific use scenario, if withEnoughBytesToFlush
     * It can also meet the performance requirements, so each flush, the data volume will be more uniform.
     * withEnoughLinesToFlush will have higher priority than withEnoughBytesToFlush
     */
    client.withEnoughLinesToFlush(10000);

    /*
     * MxClient has added the following API to adjust the number of Tuples for each CSV conversion subtask.
     * For example, there are 10,000 Tuples in Flush at a time. Set BatchSize = 2000 through the following API.
     * Then the CSV conversion of these 10,000 Tuples will be divided into 5 subtasks, each subtask handles 2,000 Tuples and executes concurrently.
     * (This feature is supported starting from v1.1.0)
     */
    client.withCSVConstructionBatchSize(2000);

    /*
     * Each MxClient has a private object pool.
     * When using it, you need to set the size of the object pool according to the number of Tuples in each MxClient flush.
     */
    // client.useTuplesPool(poolSize);

    /*
     * MxClient supports compression and needs to be used with mxgate v4.7.6 and higher
     */
    // client.withCompress();

    /* 
     * For HTTP requests, you can not use base64 encoding, and gRPC needs to do base64 encoding
     */
    // client.withBase64Encode4Compress();

    /*
     * MxClient can register a DataPostListener, and the success and failure of each batch of data are sent.
     * They will all callback in onSuccess and onFailure. You can understand which Tuple writes succeed and which Tuple writes fail
     */
    client.registerDataPostListener(new DataPostListener() {
        @Override
        public void onSuccess(Result result) {
            System.out.println(CUSTOMER_LOG_TAG + "Send tuples success: " + result.getMsg());
            System.out.println(CUSTOMER_LOG_TAG + "Succeed lines onSuccess callback " + result.getSucceedLines());
        }

        @Override
        public void onFailure(Result result) {
            /* 
             * result.getErrorTuplesMap() key-value pair containing the line of error and the cause of the error Tuple -> String
             * Key is the wrong line, value is the wrong reason
             */
            for (Map.Entry<Tuple, String> entry : result.getErrorTuplesMap().entrySet()) {
                l.error(CUSTOMER_LOG_TAG + "error tuple of table={}, tuple={}, reason={}", entry.getKey().getTableName(), entry.getKey(), entry.getValue());
                for (Column c : entry.getKey().getColumns()) {
                    l.error(CUSTOMER_LOG_TAG + "error entry columns {} = {}", c.getColumnName(), c.getValue());
        }
    }
    System.out.println(result.getSuccessLines());
}

});


Возвращает пустой объект Tuple, который можно заполнить с помощью API generateEmptyTuple объекта MxClinet.

Tuple tuple1 = client.generateEmptyTuple(); Tuple tuple2 = client.generateEmptyTuple();


Заполнение пустого Tuple в формате «ключ -> значение». Ключ — имя столбца в таблице базы данных; значение — соответствующее значение поля. Если некоторые поля могут быть null или имеют значения по умолчанию, их можно не указывать — SDK автоматически заполнит значениями по умолчанию или пустыми значениями.  
Метаинформация о таблицах базы данных, полученная через этот API, больше не хранится внутри Tuple. Это более легковесный Tuple. Поэтому при вызове MxClient.appendTuple() для добавления в MxClient исключается проверка легитимности данных внутри Tuple на основе метаинформации таблицы базы данных, что позволяет максимально быстро отправлять данные.

// Tuple tuple = client.generateEmptyTupleLite();// (This function starts with v1.1.0, if you use it to remove the comment content of this line)


> **Примечание!**  
При добавлении столбцов в этот легковесный Tuple необходимо вручную поддерживать порядок пар `addColumn() key -> value`, чтобы он соответствовал порядку столбцов в таблице базы данных.

Например, порядок столбцов в таблице данных:

Column | Type | Collation | Nullable | Default --------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ts | timestamp without time zone | | | tag | integer | | not null | c1 | double precision | | | c2 | double precision | | | c3 | double precision | | | c4 | double precision | | | c5 | text | | | c6 | text | | | c7 | text | | | c8 | text | | |


Тогда порядок добавления столбцов должен соответствовать порядку столбцов в таблице базы данных. В данном примере это:
    tuple1.addColumn("ts", "2022-05-18 16:30:06");
    tuple1.addColumn("tag", 102020030);
    tuple1.addColumn("c1", 1.1);
    tuple1.addColumn("c2", 2.2);
    tuple1.addColumn("c3", 3.3);
    tuple1.addColumn("c4", 4.4);
    tuple1.addColumn("c5", "中文字符测试-1");
    tuple1.addColumn("c6", "lTxFCVLwcDTKbNbjau_c6");
    tuple1.addColumn("c7", "lTxFCVLwcDTKbNbjau_c7");
    tuple1.addColumn("c8", "lTxFCVLwcDTKbNbjau_c8");

    tuple2.addColumn("ts", "2022-05-18 16:30:06");
    tuple2.addColumn("tag", 102020030);
    tuple2.addColumn("c1", 1.1);
    tuple2.addColumn("c2", 2.2);
    tuple2.addColumn("c3", 3.3);
    tuple2.addColumn("c4", 4.4);
    tuple2.addColumn("c5", "中文字符测试-2");
    tuple2.addColumn("c6", "lTxFCVLwcDTKbNbjau_c26");
    tuple2.addColumn("c7", "lTxFCVLwcDTKbNbjau_c27");
    tuple2.addColumn("c8", "lTxFCVLwcDTKbNbjau_c28");

Наконец, добавьте заполненный Tuple в MxClient.

client.appendTuples(tuple1, tuple2);


> **Примечание!**  
MxClient предоставляет несколько API: можно добавлять один Tuple за раз, несколько Tuple за раз или список Tuples. Например: `client.appendTuple();`, `client.appendTupleList();`; также можно вызвать метод flush() объекта MxClient для ручной отправки данных, независимо от количества записанных Tuple, например: `client.flush();`.

- Синхронная отправка данных с помощью MxClient

Синхронная отправка означает синхронную передачу Tuple в mxgate, что упрощает последующую обработку (например, фиксацию смещения Kafka).

Tuple tuple1 = client.generateEmptyTuple(); tuple1.addColumn("ts", "2022-05-18 16:30:06"); tuple1.addColumn("tag", 102020030); tuple1.addColumn("c1", 1.1); tuple1.addColumn("c2", 2.2); tuple1.addColumn("c3", 3.3); tuple1.addColumn("c4", 4.4); tuple1.addColumn("c5", "lTxFCVLwcDTKbNbjau_c5"); tuple1.addColumn("c6", "lTxFCVLwcDTKbNbjau_c6"); tuple1.addColumn("c7", "lTxFCVLwcDTKbNbjau_c7"); tuple1.addColumn("c8", "lTxFCVLwcDTKbNbjau_c8");

/*

  • appendTupleBlocking returns the return value of boolean type:
  • true: The MxClient is already full of the set bytes size, and the request can be sent;
  • false: The set bytes size has not been fully written yet / try { if (client.appendTupleBlocking(tuple1)) { l.info("append tuples enough"); // Manual trigger tuples flush client.flushBlocking(); } /
  • If the flushBlocking throws an exception as follows, it means that the entire batch of Tuples cannot be written to mxgate, and the caller can handle the exception accordingly / } catch (AllTuplesFailException e) { l.error("Tuples fail and catch the exception return.", e); for (Map.Entry<Tuple, String> entry : result.getErrorTuplesMap().entrySet()) { l.error(CUSTOMER_LOG_TAG + "error tuple of table={}, tuple={}, reason={}", entry.getKey().getTableName(), entry.getKey(), entry.getValue()); for (Column c : entry.getKey().getColumns()) { l.error(CUSTOMER_LOG_TAG + "error entry columns {} = {}", c.getColumnName(), c.getValue()); } }
    /
  • If the flushBlocking throws an exception as follows, it means that some Tuples cannot be written to mxgate, and the caller can handle the exception accordingly */ } catch (PartiallyTuplesFailException e) { for (Map.Entry<Tuple, String> entry : result.getErrorTuplesMap().entrySet()) { l.error(CUSTOMER_LOG_TAG + "error tuple of table={}, tuple={}, reason={}", entry.getKey().getTableName(), entry.getKey(), entry.getValue()); for (Column c : entry.getKey().getColumns()) { l.error(CUSTOMER_LOG_TAG + "error entry columns {} = {}", c.getColumnName(), c.getValue()); } } }

3.1.2 Пример HTTP API MatrixGate на Java

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class MxgateExample {
    public static void main(String[] args) throws Exception {
        MxgateExample http = new MxgateExample();
        http.sendingPostRequest();
    }

    /* 
     * HTTP Post request
     */
    private void sendingPostRequest() throws Exception {

        /* 
         * mxgate listens on port 8086 of localhost
         */
        String url = "http://localhost:8086/";
        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();

        /* 
         * Setting basic post request
         */
        con.setRequestMethod("POST");
        con.setRequestProperty("Content-Type","text/plain");
        String postJsonData = "public.testtable\n1603777821|1|101|201|301\n1603777822|2|102|202|302\n1603777823|3|103|203|303";

        con.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(con.getOutputStream());

        /*
         * When the data is in Chinese, it can be encoded by postJsonData.getBytes("UTF-8")
         */
        wr.write(postJsonData.toString().getBytes("UTF-8"));
        wr.flush();
        wr.close();

        int responseCode = con.getResponseCode();
        System.out.println("Sending 'POST' request to URL : " + url);
        System.out.println("Post Data : " + postJsonData);
        System.out.println("Response Code : " + responseCode);

        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String output;
        StringBuffer response = new StringBuffer();

        while ((output = in.readLine()) != null) {
            response.append(output);
        }
        in.close();

        System.out.println(response.toString());
    }
}


3.2 Пример HTTP API MatrixGate на Python

import http.client

class MxgateExample(object):
    def __init__(self):

        /*
         * mxgate listens on port 8086 of localhost
         */
        self.url = "localhost:8086"

        self.postData = "public.testtable\n/" \
                        "1603777821|1|101|201|301\n/" \
                        "1603777822|2|102|202|302\n/" \
                        "1603777823|3|103|203|303"
        self.headers = {"Content-Type": "text/plain"}

    /* 
     * HTTP Post request
     */
    def sending_post_request(self):

        conn = http.client.HTTPConnection(self.url)
        conn.request("POST", "/", self.postData, self.headers)

        response = conn.getresponse()
        response_code = response.getcode()
        print(f"Sending 'POST' request to URL : {self.url}")
        print(f"Post Data : {self.postData}")
        print(f"Response Code : {response_code}")

        output = response.read()
        print(output)

if __name__ == '__main__':
    gate_post = MxgateExample()
    gate_post.sending_post_request()


3.3 Пример HTTP API MatrixGate на C

Рекомендуется использовать среду разработки C# Core


using System;
using System.IO;
using System.Net;
using System.Text;

namespace HttpPostTest { class Program { static void Main(string[] args) { var url = "http://10.13.2.177:8086/"; var txt = "public.dest\n2021-01-01 00:00:00,1,a1\n2021-01-01 00:00:00,2,a2\n2021-01-01 00:00:00,3,a3";

       HttpPost(url,txt);
    }

public static string HttpPost(string url, string content){ string result = ""; HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url); req.Method = "POST"; req.ContentType = "text/plain";

/*
 * region Add Post parameters
 */
byte[] data = Encoding.UTF8.GetBytes(content);
req.ContentLength = data.Length;
using (Stream reqStream = req.GetRequestStream()){
    reqStream.Write(data, 0, data.Length);
    reqStream.Close();
}

HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Stream stream = resp.GetResponseStream();

/* 
 * Get the response content
 */
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)){
    result = reader.ReadToEnd();
    }
    return result;
}

} }


> Если при подключении возникает ошибка "***** body size exceeds the given limit", необходимо увеличить значение `max-body-bytes` в разделе `mxgate.conf`.

### 3.4 Пример HTTP API MatrixGate на Golang

package main

import ( "bytes" "net/http" )

func PostDataToServer(URL string) error { data := public.testtable 1603777821|1|101|201|301 1603777822|2|102|202|302 1603777823|3|103|203|303 resp, err := http.Post(URL, "application/text", bytes.NewBuffer([]byte(data))) if err != nil { return err } if resp.StatusCode != 200 { /*

  • Обработка тела ответа. */ return nil }
/*
 * Обработка тела ответа.
 */
return nil

}

func main() { err := PostDataToServer("http://127.0.0.1:8086") if err != nil{ panic(err) }

}



> **Примечание!**  
Дополнительные возможности MatrixGate см. в [Руководстве по инструментам — mxgate](/ru/doc/5.0/tools/mxgate/feature).