Подключите Oracle от AWS Lambda - PullRequest
4 голосов
/ 04 октября 2019

У меня есть лямбда-функция, которая должна использовать pandas, sqlalchemy и cx_Oracle.

Установка и упаковка всех этих библиотек вместе превышает предел пакета развертывания 250 МБ для AWS Lambda .

Я бы хотел включить только .zip Oracle Basic Light Package , затем извлечь и использовать его во время выполнения.

Что я пробовал

Мой проект структурирован следующим образом:

cx_Oracle-7.2.3.dist-info/
dateutil/
numpy/
pandas/
pytz/six-1.12.0.dist-info/
sqlalchemy/
SQLAlchemy-1.3.8.egg-info/
cx_Oracle.cpython-36m-x86_64-linux-hnu.so
instantclient-basiclite-linux.x64-19.3.0.0.0dbru.zip
main.py
six.py
template.yml

В main.py я запускаю следующее:

import json, traceback, os

import sqlalchemy as sa
import pandas as pd

def main(event, context):
    try:
        unzip_oracle()
        return {'statusCode': 200,
                'body': json.dumps(run_query()),
                'headers': {'Content-Type': 'application/json', 'Access-Control-Allow-Origin':'*'}}
    except:
        em = traceback.format_exc()
        print("Error encountered. Error is: \n" + str(em))
        return {'statusCode': 500,
                'body': str(em),
                'headers': {'Content-Type': 'application/json', 'Access-Control-Allow-Origin':'*'}}  



def unzip_oracle():
    print('extracting oracle drivers and copying results to /var/task/lib')
    os.system('unzip /var/task/instantclient-basiclite-linux.x64-19.3.0.0.0dbru.zip -d /tmp')
    print('extraction steps complete')
    os.system('export ORACLE_HOME=/tmp/instantclient_19_3')


def get_db_connection():
    return sa.engine.url.URL('oracle+cx_oracle', 
        username='do_not_worry', password='about_any', 
        host='of_these', port=1521, 
        query=dict(service_name='details')
    )


def run_query():
    query_text = """SELECT * FROM dont_worry_about_it"""
    conn = sa.create_engine(get_db_connection())
    print('Connected')
    df = pd.read_sql(sa.text(query_text), conn)
    print(df.shape)
    return df.to_json(orient='records')

Это возвращает ошибку:

sqlalchemy.exc.DatabaseError: (cx_Oracle.DatabaseError) DPI-1047: не удается найти 64-битную клиентскую библиотеку Oracle: «libclntsh.so: невозможно открыть общий объектный файл: такого файла или каталога нет». См. https://oracle.github.io/odpi/doc/installation.html#linux для справки (Справочная информация об этой ошибке на: http://sqlalche.me/e/4xp6)

Что я также пробовал

Я пробовал:

  • Добавление
Environment: 
    Variables: 
      ORACLE_HOME: /tmp 
      LD_LIBRARY_PATH: /tmp 

к template.yml и повторное развертывание. Та же ошибка, что и выше.

  • Добавление os.system('export LD_LIBRARY_PATH=/tmp/instantclient_19_3') в питонскрипт. Та же ошибка, что и выше.
  • Многие cp и ln вещи, которые были запрещены в Lambda вне папки /tmp. Та же ошибка, что и выше.

Один способ, который работает, но плохо

Если я сделаю папку с именем lib/ в пакете Lambda и включу нечетный ассортимент файлов libaio.so.1, libclntsh.so и т. Д. , функция будет работать должным образом, по некоторым причинам . Я закончил с этим:

<all the other libraries and files as above>
lib/
-libaio.so.1
-libclntsh.so
-libclntsh.so.10.1
-libclntsh.so.11.1
-libclntsh.so.12.1
-libclntsh.so.18.1
-libclntsh.so.19.1
-libclntshcore.so.19.1
-libipc1.so
-libmql1.so
-libnnz19.so
-libocci.so
-libocci.so.10.1
-libocci.so.11.1
-libocci.so.12.1
-libocci.so.18.1
-libocci.so.19.1
-libociicus.so
-libons.so

Однако я выбрал эти файлы методом проб и ошибок и не хочу идтиснова через это.

Есть ли способ разархивировать instantclient-basiclite-linux.x64-19.3.0.0.0dbru.zip в Lambda во время выполнения и заставить Lambda увидеть / использовать его для подключения к базе данных Oracle?

1 Ответ

1 голос
/ 11 октября 2019

Я ни в коем случае не эксперт по python, но эта строка кажется очень странной

print('extracting oracle drivers and copying results to /var/task/lib')
os.system('unzip /var/task/instantclient-basiclite-linux.x64-19.3.0.0.0dbru.zip -d /tmp')
print('extraction steps complete')
os.system('export ORACLE_HOME=/tmp/instantclient_19_3')

Обычно у вас очень ограниченный доступ к API уровня ОС с Lambda. И даже когда вы это делаете, Он может вести себя так, как вы этого не ожидаете. (Подумайте так: кому принадлежит функция «разархивировать»? Файл, созданный этой командой, будет виден / вызван кем?)

Я вижу, вы упомянули, что у вас нет проблем с извлечением файлов, что тоже немногостранно

Мой единственный ответ для вас заключается в том, что

1 / Попробуйте "принести свои собственные" инструменты (распаковать и т. д.)

2 / Никогда не пытайтесь делать ОСУровень звонков. Как и os.system ('export ...'), всегда используйте полный путь

Снова глядя на ваш вопрос, похоже, что способ указания переменной среды конфликтует

ORACLE_HOME: /tmp 

следует

Environment: 
    Variables: 
      ORACLE_HOME: /tmp/instantclient_19_3
      LD_LIBRARY_PATH: /tmp/instantclient_19_3

Также см .: Как получить доступ к переменной среды AWS Lambda из Python

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...