[Python][JSON]SQL databaseとの連携、JSONの触り方

Azureと連携なんかをして遊んでみる

今回こんなことをしてみている。

Azure CDNのPOPリストを拾ってNginxのACLにぶち込む処理を超複雑にした

もともとは、Azure PaaSって具体的にどういう動きをしてるんだろう?というのをつかむのが目的であり、正直処理が完結すること自体にあまり興味はなかったわけなんですが、だんだんこれに固執するようになり、鬼の形相でコーディングしてる私が気づけばおりました。

やっとこさ一通りの処理が出来上がったので、そこで学んだことなんかを備忘録としてまとめてみることにしました。

Azure SQL databaseと連携をする

Linux+Python3.6環境でAzure SQL databaseとの連携を行う際は、SQL Server用ODBCドライバと、pythonモジュールである「pyodbc」「pandas」の導入が必要です。

そのうえで、以下のような処理を書く感じになります。

#ReadQueryを実行する関数
def ReadQueryBySQLServer(sql):
    #接続文字列の定義
    con = pyodbc.connect(r'DRIVER={ODBC Driver 13 for SQL Server};SERVER=;DATABASE=;UID=<ユーザ名>;PWD=<パスワード>;')
    #pandasライブラリを用いてSQL文を読み出し、データベースへ送り出す
    df = pd.io.sql.read_sql(sql,con,index_col=None)

   #接続セッション開放
    con.close()

    #DataFrame形式で返す
    return(df)

REST API的な部分のつくり

今回作る部分はGETメソッドに対する処理だけなので、比較的簡単かなぁなんて思ったわけですが、どうやら冒頭に適用するメソッドの定義を行い、その配下に関数を割り当てる形で対応するようです。

#GETメソッド発行時の動作を規定する
@api.route('/respCdn/<string:inputCode>', methods=['GET'])
def responseCdnList(inputCode):
(以下略)

これで、所定のURL/メソッドが受信されたら、配下のdefステートメント(?)が実行されるようです。URL上に指定したコードがinputCode変数に適用され、以降の処理が行われるようになるようです。

さらに応用することで、POSTやPUTへの対応もできる・・・という話で。

JSONデータの取り扱い

今回作った処理では、

  • SQL databaseからデータを取得し、DataFrameに格納する
  • DataFrameからデータの抽出を行い、JSON形式に変換する
  • JSON形式に変換したデータをJSON応答として成型し、アクセス元へ応答として返す。

ということをやっています。
このとき、DataFrame->JSONへの変換はpandasの機能を用いて変換しており、最終的な応答時のJSON操作はFlaskの機能を用いています。このため、若干のアンマッチが発生していることがわかりました。

というのも、pandasの機能(DataFrame.to_json関数)を用いて変換をしたJSONデータはstring型の状態で受け取っており、それをそのままjsonify関数に通すと、データがまるっと「一つの文字列」としてダブルクォートでくくられてしまうのです・・

というわけで、以下のような対処が必要でした。

    #取得したDataFrameをJSON形式に加工(ただし、型としてはString型)
    responseData = responseData.to_json(orient='index',force_ascii=True)
    #サブネットマスク長に余計な空白が入るため、削除する
    responseData = responseData.replace(' ','')
    #JSON応答に変換する。ただし、その前にString型のデータをJSON型に変換する
    respData = jsonify(json.loads(responseData))

string型で渡されたresponseDataに対して、json.loadsを使用して、まっとうなJSONデータとしてFlaskのjsonify関数に渡しています。これで誤って文字列としてまとめられる状況を回避しています。

jqコマンドにおける連番キーへの対処

REST APIのリクエストを送る側はbashで書いてるのですが、Azure VM側で処理して帰ってきたJSONをパースする際に使ってるのがjqコマンドです。以下の記事でもこのjqコマンドにはお世話になりました。
https://www.bluecore.net/2018/10/08/5754/

さて、今回応答が返ってきた内容はこんな感じになります。

{
  "108": {
    "Network_address": "5.104.64.0",
    "Network_prefixLength": "21"
  },
  "109": {
    "Network_address": "46.22.64.0",
    "Network_prefixLength": "20"
  },
  "110": {
    "Network_address": "61.49.62.128",
    "Network_prefixLength": "25"
  },

はい、キーが連番になってるのです。これが固定文字列だと楽なんだけど、連番だとどうしたらいいのだろう?と。これが連番になるのは、ある意味DataFrameの宿命みたいなもので、どうしても出力結果にindexがまとわりついてくるようでして・・・・その際、こういう形で値を取り出せばいいということを知りました。

#Get IPv4 address list from POP server list
cat ${JSONDATA} |jq -r '.[]| [.Network_address, .Network_prefixLength]|@csv' > ${TRANS_TEMP}

すると、こんな風になりまして、思う通りのデータがとれるようになったと。めでたしめでたし。

"65.199.146.192","26"
"65.200.151.160","27"
"65.200.157.192","27"
"68.130.128.0","24"
"68.130.136.0","21"
"65.200.46.128","26"

あとは基本的に先に掲示した記事と考え方は同じで、sed使って文字列置換をすれば無事ACLが完成し、nginxをReloadすることで反映が出来ました。

感想

結局のところ、思い立ってから出来上がるまでに3-4週間もかかりました。しかも一部の機能は途中までC#で作ってましたが、どうしても理解が追い付かずに挫折し、Pythonで作り直したりした経緯もありまして、なんでこんなに苦しんでやってるんだろうか・・・?と思い悩みもしました。

今回Azure PaaSを触ってみたわけですが、正直言って面白かったです。同時に、クラウド要素とIDE間の連携と言うところがここまでできるようになってんのかと驚きの連続でした。

ちょっぴりだけ私も開発に携わったことがありましたが、その頃は正直Terapad(テキストエディタ)でコード書いてるほうが楽だわーと思ってましたが、今どきの例えばVisualStudio2017とかは、ホントに何でもかんでも生成してくれますね。コードもそんなに汚くはないし。

同時に、時代についていけてないとこりゃ大変なんだなーということを痛感しました。世界がまるっきり違いすぎて、15年の隔たりってスゲーなーとか思ったりもしました。

PaaSで感じたところは主に以下のような感じです。

  • 基本的に、IDEとPaaS間の通信経路はインターネットを通る
    • それゆえ、IP制限機能やファイアウォール機能に対する配慮は十二分に行う必要がある
    • SQL databaseとの通信なんて、もろに1433/tcpを通る
    • ファイアウォールの穴を下手に放置すると、恐らく確実に死ぬ
  • なんと、一部IaaSサービスもPaaSアクセスにはグローバルアドレスで通信をする
    • IaaSと連携できる部分は有効にしたほうが良い。
    • サービスエンドポイントに対応しているコンポーネントについては、これを有効にすることでインターネットに出ることなく、VNETの内部アドレスで通信するようになり、セキュリティレベルが向上する
  • Functionsなどのコンポーネントでは、環境変数の定義ができる
    • 私はうまくいかなかったんだけど、環境変数を隠蔽・引用する仕組みを組むことで、コード埋め込みを避けることができるみたい
  • VisualStudio超便利
    • 特にデプロイ。びっくりするほど簡単。
    • SQL Management Studioもこれまた便利。最新版では、普通にSQL databaseへ接続する際、IP制限がかかっている場合にファイアウォールの穴あけを代行してくれる機能がある
      • ただし、それがやれてしまうことはなかなか問題だと思うので、きちんとセキュリティ設計に気を配らないと死ぬと思う。

今後も継続して、言語のおさわりはやってみたいと思います。JSONデータのやり取りに関しても、公開API使って気象データを拾ったりとかやれるみたいだし。ネタが増えてよかったなと感じる今日この頃でした。

PAGE TOP