Linux中國

Python 內存資料庫 CyberDB 使用實例

概括

CyberDB 是一個輕量級的 Python 內存資料庫。它旨在利用 Python 內置數據結構字典、列表作數據存儲,通過 TCP 套接字高效通信,並提供了數據持久化。該資料庫的亮點在於它使用了 Pythonic 的方式編程,你可以像使用字典和列表一樣使用 CyberDB

現在我們把 CyberDB 帶到能發揮其作用的地方,在生產環境中將 CyberDB 作為 Flask 的內存資料庫,使用 Gunicorn 運行,並實現多進程間的通信。

這篇文章通過一個儘可能精簡的 Flask 實例講解,不會涉及複雜的 Web 知識。核心思路為 CyberDB + Gunicorn + Gevent + Flask(多進程 + 協程),啟動一個 CyberDB 伺服器,使用 Gunicorn 多進程運行 Flask 實例,每個進程的實例通過 Gevent 運行,進程中使用 CyberDB 客戶端連接至內存資料庫,由此實現對 CyberDB 資料庫的高並發訪問。

源碼解析

文章使用 PyPy 運行,同樣適用 CPython。

運行環境: Debian 10, Python 3.8.12, PyPy 7.3.7

此項目的目錄結構

.
├── app.py
├── cyberdb_init.py
├── cyberdb_serve.py
├── requirements.txt
└── venv

我們通過列舉每個文件的內容順序講解 CyberDB 的核心操作。

文件 requirements.txt

CyberDB>=0.7.1
Flask==2.1.1
gevent==21.12.0
gunicorn==20.1.0

這是此項目的依賴。這篇文章不是 Python 基礎教程,如果你不清楚,請查詢相關文檔創建虛擬環境 venv 目錄並安裝 requirements.txt 中的依賴。

生成 venv 目錄並安裝好依賴後,下面所有操作都在激活的虛擬環境中運行。

文件 cyberdb_init.py

功能:初始化 CyberDB 的表結構,只在第一次運行時使用,後續不再使用。

import time

import cyberdb

db = cyberdb.Server()
# 配置 CyberDB 服務端的 地址、埠、密碼。
db.start(host='127.0.0.1', port=9980, password='123456')

# 待服務端啟動後,連接 CyberDB 服務端。
time.sleep(3)
client = cyberdb.connect(host='127.0.0.1', port=9980, password='123456')
# 生成 proxy 對象。
with client.get_proxy() as proxy:
    # 創建類型為 CyberDict 的表 centre,並初始化內容。
    proxy.create_cyberdict('centre')
    centre = proxy.get_cyberdict('centre')
    centre['content'] = 'Hello CyberDB!'

# 將 CyberDB 保存至 data.cdb 。
db.save_db('data.cdb')

在項目根目錄執行

python cyberdb_init.py

以完成 CyberDB 資料庫表的初始化。

它會在 CyberDB 中創建了一個名為 centre、類型為 CyberDict 的表;初始化 content 鍵的值為 Hello CyberDB!;最後將 CyberDB 資料庫保存至硬碟(在項目根目錄生成了名為 data.cdb 的文件)。

文件 cyberdb_serve.py

功能:運行 CyberDB 服務端。

import cyberdb

def main():
    # 後台運行 CyberDB 服務端,設置相關信息。
    db = cyberdb.Server()
    # 從硬碟讀取 data.cdb 至 CyberDB。
    db.load_db('data.cdb')
    # 每 300 秒備份一次資料庫。
    db.set_backup('data.cdb', cycle=300)
    db.run(
        host='127.0.0.1', # TCP 運行地址
        port=9980, # TCP 監聽埠
        password='hWjYvVdqRC', # 資料庫連接密碼
        max_con=10000, # 最大並發數
        encrypt=True, # 加密通信
        print_log=False # 不列印日誌
    )

if __name__ == '__main__':
    main()

在項目根目錄執行

python cyberdb_serve.py

以運行 CyberDB 服務端。

此處設置了 encrypt=True ,CyberDB 會將 TCP 通信內容使用 AES-256 演算法加密。開啟 encrypt=True 後,CyberDB 僅允許白名單中的 IP 通信,默認白名單為 ['127.0.0.1'](查看白名單 設置方法)。一般,若只需在本地進程間通信,無需開啟 encrypt=True 和設置白名單,只有遠程通信時需要此操作。

文件 app.py

功能:運行 Flask 實例和 CyberDB 客戶端。

import cyberdb
from flask import Flask, g

# 連接 CyberDB 並生成客戶端實例。
client = cyberdb.connect(
    host='127.0.0.1', 
    port=9980, 
    password='hWjYvVdqRC',
    # 服務端若加密,客戶端必須加密,反之亦然。
    encrypt=True,
    # 每個連接若超過900秒無操作,將捨棄該連接。
    # 連接由連接池智能管理,無需關注細節。
    time_out=900
)

# 創建 Flask 實例,此部分請參考 
# Flask 文檔 https://flask.palletsprojects.com/
app = Flask(__name__)

@app.before_request
def before_request():
    # 每次請求執行前生成 proxy 對象。
    g.proxy = client.get_proxy()
    # 從連接池獲取連接。
    g.proxy.connect()

@app.get("/")
def hello_world():
    # 從資料庫獲取 centre 表。
    centre = g.proxy.get_cyberdict('centre')

    return {
        'code': 1,
        'content': centre['content']
    }

@app.teardown_request
def teardown_request(error):
    # 每次請求執行後歸還連接至連接池。
    g.proxy.close()

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=8000)

該模塊會在每次請求執行前(before_request())使用 client.get_proxy() 獲取 proxy 對象,每個獲取的 proxy 對象可以綁定一個 TCP 連接,此處使用 proxy.connect() 從連接池獲取連接。視圖函數 hello_world() 中,由 proxy 獲取的對象 centre,與 proxy 共用同一個連接,proxy 的連接釋放後,centre 也會失去連接。在每次請求後(teardown_request())使用 proxy.close() 方法釋放 proxy 綁定的連接,歸還至連接池。

cyberdb.connecttime_out 參數表示連接池中每個連接的超時時間,此處每個連接超過 900 秒無操作將被捨棄。若不設置該參數,連接池的每個連接會維持到失效為止。

使用 Gunicorn 運行 Flask 實例

Gunicorn 是一個用於 UNIX 的 Python WSGI HTTP 伺服器,通常在生產環境使用,可以利用多核 CPU 。

Gevent 是一個基於協程的 Python 網路庫。Gevent 會更改 CyberDB 客戶端的底層套接字通信,使之支持協程。

在項目根目錄運行

gunicorn -w 4 -b 127.0.0.1:8000 -k gevent app:app

使用 4 進程、Gevent 啟動 Flask 實例。

瀏覽器訪問 127.0.0.1:8000 ,得到如下響應:

{"code":1,"content":"Hello CyberDB!"}

參考信息

CyberDB 源碼: https://github.com/Cyberbolt/CyberDB

總結

通過此例,你可以把 CyberDB 部署到更複雜的 Web 環境中,充分享受內存的低延遲特性。CyberDB 的核心是以 Pythonic 的方式編程,你可以在任何 Python 代碼中將 CyberDB 作為內存資料庫。

作者簡介:

Cyberbolt:一個自由的 Python 開發者。

via: https://www.cyberlight.xyz/static/cyberdb-chn/tutorial/flask/

作者:Cyberbolt 編輯:wxy

本文由貢獻者投稿至 Linux 中國公開投稿計劃,採用 CC-BY-SA 協議 發布,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的電子郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國