6.7 KiB
Подключение к Impala из Python
Инструкция описывает, как подключиться к корпоративному кластеру Impala через Python-библиотеку impyla. Используется в проекте metrics_audit.
Параметры кластера
| Параметр | Значение |
|---|---|
| Основной хост | bdas-worker-08.bdpak.telecom.kz |
| Резервный хост | bdas-utility-01.bdpak.telecom.kz |
| Порт | 21050 |
| База данных | drb |
| Аутентификация | PLAIN (логин + пароль) |
| SSL | включён (use_ssl=True) |
| Доступ | только из внутренней сети или через VPN |
Username и password хранятся в
config.yamlи не коммитятся в git.
Зависимости
impyla работает через протокол Thrift напрямую — Java-драйверы (JDBC .zip) не нужны, они только для DBeaver/Tableau.
# requirements.txt
impyla==0.19.0
thrift==0.16.0
thrift-sasl==0.4.3
pure-sasl>=0.6.2 # вместо sasl — не требует C++ компилятора на Windows
Важно: пакет
sasl==0.3.1на Windows не устанавливается без Microsoft C++ Build Tools.
Используйтеpure-sasl— он устанавливается автоматически как зависимостьthrift-sasl.
Установка:
python -m venv venv
venv\Scripts\activate
pip install impyla==0.19.0 thrift==0.16.0 thrift-sasl==0.4.3 pandas
Проблема с SSL и её решение
При подключении с use_ssl=True возникает ошибка:
ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure
Причина: сервер Impala использует устаревшие cipher suites, которые Python 3.10+ отклоняет по умолчанию (security level 2).
Решение: monkey-patch SSL-контекста библиотеки thrift перед подключением:
import ssl
import thrift.transport.TSSLSocket as _mod
def _patch_thrift_ssl():
_orig = _mod.TSSLSocket.__init__
def _patched(self, *a, **kw):
_orig(self, *a, **kw)
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
ctx.set_ciphers("DEFAULT:@SECLEVEL=0")
self._context = ctx
_mod.TSSLSocket.__init__ = _patched
# Вызвать ДО impyla_connect:
_patch_thrift_ssl()
Это нужно вызвать один раз перед первым подключением. Патч снижает проверку сертификата и разрешает старые шифры — приемлемо для внутренней сети за VPN.
Подключение
from impala.dbapi import connect
conn = connect(
host="bdas-worker-08.bdpak.telecom.kz",
port=21050,
database="drb",
user="<username>", # из config.yaml
password="<password>", # из config.yaml
use_ssl=True,
auth_mechanism="PLAIN", # AuthMech=3 в JDBC-терминологии
timeout=60,
)
С резервным хостом — оберните в try/except и переключитесь на bdas-utility-01.bdpak.telecom.kz при ошибке.
Выполнение запроса
cursor = conn.cursor()
cursor.execute("SELECT event_type, entry_date, count(*) AS cnt FROM drb.drb_iliyas_amplitude_metrics_full GROUP BY 1, 2")
import pandas as pd
rows = cursor.fetchall()
columns = [desc[0] for desc in cursor.description]
df = pd.DataFrame(rows, columns=columns)
Схема таблицы метрик
drb.drb_iliyas_amplitude_metrics_full
| Колонка | Тип | Описание |
|---|---|---|
metrics |
string | Платформа: TelecomKz или Aitu |
event_type |
string | Название метрики (событие Amplitude) |
entry_date |
string | Дата события (YYYY-MM-DD) |
event_time |
string | Полная метка времени |
event_properties |
string | JSON с параметрами события |
platform |
string | android / iOS / Web |
| ... | прочие поля пользователя и устройства |
Внимание: колонка
metricsсодержит платформу (TelecomKz/Aitu), а не название метрики.
Название метрики — в колонкеevent_type.
external_sources.amplitude_loyalty_program_logs
| Колонка | Тип | Описание |
|---|---|---|
event_type |
string | Название метрики |
event_time |
string | Полная метка времени (дата берётся через left(event_time, 10)) |
| ... | прочие поля |
Агрегирующий запрос проекта
-- TelecomKz (все метрики) + Aitu (только whitelist)
SELECT metrics AS platform, event_type AS metrics, entry_date, count(*) AS cnt
FROM drb.drb_iliyas_amplitude_metrics_full
WHERE event_type IS NOT NULL AND event_type != ''
AND (
metrics = 'TelecomKz'
OR (metrics = 'Aitu' AND event_type IN ('miniapp_opened', 'main_tab_selected', ...))
)
GROUP BY 1, 2, 3
UNION ALL
-- Loyalty (без временных акционных метрик)
SELECT 'Loyalty' AS platform, event_type AS metrics,
left(event_time, 10) AS entry_date, count(*) AS cnt
FROM external_sources.amplitude_loyalty_program_logs
WHERE event_type IS NOT NULL AND event_type != ''
AND event_type NOT LIKE 'detail_promo_%'
AND event_type NOT LIKE 'company_promo_%'
GROUP BY 1, 2, 3
Типичные ошибки
| Ошибка | Причина | Решение |
|---|---|---|
SSLV3_ALERT_HANDSHAKE_FAILURE |
Старые cipher suites на сервере | Применить _patch_thrift_ssl() (см. выше) |
ConnectionRefusedError / TSocket read 0 bytes |
VPN не подключён | Подключить VPN и повторить |
AuthenticationError |
Неверный логин/пароль | Проверить config.yaml |
sasl не устанавливается |
Нет C++ Build Tools | Использовать pure-sasl (устанавливается автоматически) |
ssl.PROTOCOL_TLS is deprecated |
Предупреждение thrift 0.16 | Некритично, патч перезаписывает контекст после |