简体   繁体   中英

azure function using pyodbc works fine on local machine, but not on azure cloud

I developed a simple python Azure function app using pyodbc to select a few rows from a public IP MS SQL server. My function app runs fine on my laptop, but it doesn't work when I publish it on Azure cloud (I used Consumption - serverless plan, linux environment). Thru the logging, I knows that it always gets stuck at the pyodbc.connect(...) command and time-out.

#...
conn_str = f'Driver={driver};Server={server},{port};Database={database};Uid={user};Pwd={password};Encrypted=yes;TrustServerCertificate=no;Connection Timeout=30'
sql_query = f'SELECT * FROM {table_name}'
try:
    conn = pyodbc.connect(conn_str) # always time-out here if running on Azure cloud!!!
    logging.info(f'Inventory API - connected to {server}, {port}, {user}.')
except Exception as error:
    logging.info(f'Inventory API - connection error: {repr(error)}.')
else:
    with conn.cursor() as cursor:
        cursor.execute(sql_query)
        logging.info(f'Inventory API - executed query: {sql_query}.')
        data = []
        for row in cursor:
            data.append({'Sku' : row.Sku, 'InventoryId' : row.InventoryId, 'LocationId' : row.LocationId, 'AvailableQuantity' : row.AvailableQuantity})
#...

The logging captured:

Inventory API - connection error: OperationalError('HYT00', '[HYT00] [Microsoft][ODBC Driver 17 for SQL Server]Login timeout expired (0) (SQLDriverConnect)').

I already include the pyodbc in the requirements.txt file. I also allows all outboundIpAddresses and possibleOutboundIpAddresses of my function app on my SQL server firewall. My function app does not have any network restriction on Azure cloud (or at least it said so on the network settings).

my config file:

driver={ODBC Driver 17 for SQL Server}
server=I tried both IP and full internet host name, both didn't work

Could someone give me a hint? Thanks.

Workarounds to fix the PYODBC connection Error

Try to use a below format

import pyodbc
server = 'tcp:myserver.database.windows.net'
database = 'mydb'
username = 'myusername'
password = 'mypassword'
conn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+ password)

If you are using Domain Name add TCP with domain name server = 'tcp:myserver.database.windows.net' otherwise use the IP server = '129.0.0.1'

If you are using port use like this 'tcp:myserver.database.windows.net,1233' or '129.0.0.1,1233'

Try to remove additional properties like Connection_Timeout , Trusted_certificate and all and check now.

Refer here

I put the following snippet into my function to check the outbound IP, and found out that Azure use a few outbound IPs that are not listed in the [outboundIpAddresses] and [possibleOutboundIpAddresses] ( documented in this MS link )

import requests
#...
outbound_ip_response = requests.request('GET', 'https://checkip.amazonaws.com')
logging.info(f'Inventory API - main()- outbound ip = {outbound_ip_response.text}')

So, I followed the instructions in this link to setup a static outbound IP for my function app and allowed this IP to access my SQL server. It worked.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM