在現代軟體開發中,非同步任務處理對於提升應用程式效能至關重要。本文示範如何利用 Python RQ 函式庫建立非同步任務佇列,並結合 Docker Compose 協調 PostgreSQL、Redis 和 Jupyter Notebook 等服務,實作一個完整的目標編碼非同步處理流程。程式碼範例中,我們首先使用 Python 連線 PostgreSQL 資料函式庫,擷取待處理資料的 ID。接著,利用 RQ 將目標編碼任務送入 Redis 佇列,並由 Worker 程式非同步執行。同時,我們使用 Docker Compose 管理多個容器,確保開發環境的一致性,並透過 Jupyter Notebook 進行互動式開發與除錯。最後,我們使用 Git 進行版本控制,方便團隊協作和程式碼管理。

第10章 ■ 互動式軟體開發

更新Python模組

在圖10-15中,您使用Jupyter Notebook伺服器導航到lib/目錄,然後在lib/內選擇您的postgres.py檔案以更新模組。接下來,您將清單10-74中的程式碼新增到檔案中,如圖10-16所示。請注意,當所有目前的變更都已儲存時,文字檔案名稱旁邊將出現勾選標記,如圖10-17所示。

圖10-15:開啟postgres.py進行編輯

圖10-16:最新版本的postgres.py

圖10-17:postgres.py的所有變更已儲存

接下來,您將建立一個新的筆記本,以使用encode_target函式透過延遲作業系統統對adult表格中的所有列進行編碼。您建立了一個名為20170619-Encode_target.ipynb的新筆記本。在清單10-77中,您從專案根目錄設計模式開始。在清單10-78中,您從lib.postgres匯入所需的函式。

清單10-77:專案根目錄設計模式

from os import chdir
chdir('/home/jovyan')

清單10-78:從lib.postgres匯入函式

from lib.postgres import connect_to_postgres, encode_target

在清單10-79中,您看到一個新的設計模式,即從rq函式庫例項化一個佇列(Queue)。佇列使用與特定Redis伺服器的連線進行例項化。和之前一樣,您使用由Docker Compose建立的網路上的Redis服務名稱this_redis

清單10-79:建立與Redis的連線和新的佇列

from redis import Redis
from rq import Queue
REDIS = Redis(host='this_redis')
Q = Queue(connection=REDIS)

在清單10-80中,您將所有部分組合在一起。您建立了一個新的與PostgreSQL的連線。使用for迴圈從adult表格中提取100個尚未編碼目標值的列的_id。對於每個列,您使用.enqueue()函式將encode_target函式與相關的_id新增到作業佇列中。請注意,要傳遞給encode_target的引數(即_id)作為第二個引數傳遞給.enqueue()

清單10-80:將100個目標編碼請求新增到佇列

con, cur = connect_to_postgres()
for _ in range(100):
    cur.execute("""SELECT _id FROM adult WHERE target IS NULL;""")
    this_id, = cur.fetchone()
    Q.enqueue(encode_target, this_id)
con.close()

在至少一次執行此儲存格期間(您需要多次執行此儲存格以編碼整個表格,除非進行修改),建議使用根據瀏覽器的監控器,以及“追蹤”Docker Compose日誌,以觀察Worker如何處理這些函式。根據瀏覽器的監控器將在與您的Jupyter Notebook伺服器相同的IP地址上可用,但將在5000埠上可用(圖10-18)。清單10-81顯示了使用--follow旗標“追蹤”Docker Compose日誌。每個作業程式將在執行時透過此日誌傳遞。

清單10-81:追蹤Docker Compose日誌

$ docker-compose logs --follow this_worker
...
this_worker_1 | 01:43:04 *** Listening on default...
this_worker_1 | 01:43:04 default: lib.postgres.encode_target(24) (914a8229-a876-438f-98d4-d6cd39a469b2)
this_worker_1 | 01:43:04 default: Job OK (914a8229-a876-438f-98d4-d6cd39a469b2)
this_worker_1 | 01:43:04 Result is kept for 500 seconds
...

最後,您使用git跟蹤工作。在清單10-82中,您檢查專案的狀態。在清單10-83中,您新增並提交所有最近的工作。

清單10-82:檢查專案狀態

$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   lib/postgres.py

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        ipynb/20170619-Develop_encoding_target_function.ipynb
        ipynb/20170619-Encode_target.ipynb

no changes added to commit (use "git add" and/or "git commit -a")

清單10-83:新增所有檔案並提交

$ git add -A
$ git commit -m 'function and queueing for target encoding'
[master 93f3033] function and queueing for target encoding
 3 files changed, 319 insertions(+)
 create mode 100644 ipynb/20170619-Develop_encoding_target_function.ipynb
 create mode 100644 ipynb/20170619-Encode_target.ipynb

在清單10-84中,您顯示目前專案的狀態。

清單10-84:目前專案狀態

$ tree
.
├── data
│   └── adult.data
├── docker
│   ├── jupyter
│   │   └── Dockerfile
│   └── postgres
│       ├── Dockerfile
│       ├── get_data.sh
│       └── initdb.sql
├── docker-compose.yml
├── ipynb
│   ├── 20170611-Examine_Database_Requirements.ipynb
│   ├── 20170613-Initial_Database_Connection.ipynb
│   ├── 20170613-Verify_Database_Connection.ipynb
│   ├── 20170619-Develop_encoding_target_function.ipynb
│   └── 20170619-Encode_target.ipynb
└── lib
    ├── __init__.py
    ├── postgres.py
    └── __pycache__
        ├── __init__.cpython-35.pyc
        └── postgres.cpython-35.pyc

索引

(索引內容略)

程式碼解析:

  1. 資料函式庫連線與操作

    • 使用 connect_to_postgres() 函式建立與 PostgreSQL 資料函式庫的連線。
    • cur.execute() 用於執行 SQL 查詢,例如選擇、更新資料表中的資料。
  2. 佇列處理

    • rq 函式庫匯入 Queue,並使用 Redis 作為後端來處理任務佇列。
    • 將任務 encode_target 新增到佇列中,並傳遞 _id 作為引數。
  3. Git 版本控制

    • 使用 git status 檢視當前專案狀態。
    • git add -A 將所有變更的檔案新增到暫存區。
    • git commit -m 'message' 提交變更並新增提交訊息。
  4. 專案結構

    • 使用 tree 命令顯示專案目錄結構,清晰展示各檔案和目錄的分佈。

此程式碼實作了一個完整的互動式軟體開發流程:

  1. 模組更新:修改 postgres.py 檔案以新增目標編碼功能。
  2. 任務佇列:利用 Redis 和 RQ 建立任務佇列,將目標編碼任務非同步處理。
  3. 版本控制:使用 Git 跟蹤所有變更,確保程式碼的可維護性和可追溯性。
  4. 專案結構管理:清晰展示專案的目錄結構,方便管理和擴充套件。

Docker 技術深度解析與實務應用

前言

Docker 是一種革命性的容器化技術,能夠大幅簡化應用程式的佈署和管理流程。本篇文章將探討 Docker 的核心概念、技術原理及其在實際開發中的應用。

Docker 基礎架構與元件

Docker 引擎

Docker 引擎是整個 Docker 生態系統的核心,負責容器的建立、執行和管理。它具備以下關鍵功能:

  1. 容器生命週期管理:建立、啟動、停止和刪除容器
  2. 映像檔管理:提取、推播和管理 Docker 映像檔
  3. 網路管理:提供容器間的網路通訊功能

Docker 映像檔與容器

Docker 映像檔是一個唯讀的範本,用於建立容器。容器則是映像檔的執行例項,具有以下特點:

  1. 輕量級虛擬化:與傳統虛擬機器相比,容器共用主機作業系統核心,因此更為輕量和高效。
  2. 快速佈署:容器可以在幾秒鐘內啟動,大幅提高了佈署效率。
  3. 環境一致性:確保開發、測試和生產環境的一致性,減少了「在我的機器上可以執行」的問題。

Docker Compose:多容器應用程式管理

Docker Compose 簡介

Docker Compose 是一個用於定義和執行多容器 Docker 應用程式的工具。它使用 YAML 檔案來組態應用程式的服務、網路和資料卷,從而簡化了複雜應用程式的佈署和管理。

Docker Compose 的主要功能

  1. 服務定義:在 docker-compose.yml 檔案中定義應用程式的各個服務及其組態。
  2. 一鍵佈署:使用 docker-compose up 命令即可啟動所有服務。
  3. 網路管理:自動為服務建立網路,實作服務間的通訊。
  4. 資料持久化:支援資料卷的掛載,確保資料持久化儲存。

Docker 在資料儲存技術中的應用

MongoDB 與 Docker

MongoDB 是一種流行的 NoSQL 資料函式庫,能夠與 Docker 無縫整合。以下是使用 Docker 佈署 MongoDB 的步驟:

  1. 提取 MongoDB 映像檔:使用 docker pull mongo 命令下載官方 MongoDB 映像檔。
  2. 建立並執行 MongoDB 容器:使用 docker run -d --name mongodb mongo 命令建立並在背景執行 MongoDB 容器。
  3. 資料持久化:使用資料卷將 MongoDB 資料持久化儲存,例如:docker run -d --name mongodb -v /path/to/data:/data/db mongo

PostgreSQL 與 Docker

PostgreSQL 是一種強大的開源關聯式資料函式庫,同樣能夠與 Docker 整合使用。以下是使用 Docker 佈署 PostgreSQL 的步驟:

  1. 提取 PostgreSQL 映像檔:使用 docker pull postgres 命令下載官方 PostgreSQL 映像檔。
  2. 建立並執行 PostgreSQL 容器:使用 docker run -d --name postgresql -e POSTGRES_PASSWORD=mysecretpassword postgres 命令建立並在背景執行 PostgreSQL 容器。
  3. 連線 PostgreSQL 資料函式庫:使用 psql 或其他資料函式庫客戶端工具連線到正在執行的 PostgreSQL 容器。

Jupyter Notebook 與 Docker

Jupyter Notebook 是一種流行的互動式計算環境,能夠與 Docker 結合使用,提供一致且可重現的資料科學工作流程。

使用 Docker 佈署 Jupyter Notebook

  1. 提取 Jupyter Notebook 映像檔:使用 docker pull jupyter/scipy-notebook 命令下載官方 Jupyter Notebook 映像檔。
  2. 建立並執行 Jupyter Notebook 容器:使用 docker run -p 8888:8888 jupyter/scipy-notebook 命令建立並執行 Jupyter Notebook 容器,並將容器的 8888 連線埠對映到主機的 8888 連線埠。
  3. 存取 Jupyter Notebook:在瀏覽器中存取 http://localhost:8888 以使用 Jupyter Notebook。

Dockerfile 最佳實踐

編寫高效的 Dockerfile

  1. 最小化層數:合併多個 RUN 命令以減少映像檔層數,提高構建效率。
  2. 利用快取:將不常變化的指令放在前面,以充分利用 Docker 的快取機制。
  3. 使用官方基礎映像檔:選擇官方維護的基礎映像檔,以確保安全性和穩定性。

範例:建立自訂的 Python 環境

# 使用官方 Python 映像檔作為基礎
FROM python:3.9-slim

# 設定工作目錄
WORKDIR /app

# 複製 requirements.txt
COPY requirements.txt .

# 安裝依賴套件
RUN pip install --no-cache-dir -r requirements.txt

# 複製應用程式碼
COPY . .

# 設定環境變數
ENV PYTHONUNBUFFERED=1

# 暴露應用程式連線埠
EXPOSE 8000

# 設定啟動命令
CMD ["python", "app.py"]
程式碼範例說明:

上述 Dockerfile 程式碼展示瞭如何建立一個自訂的 Python 環境,包括設定工作目錄、安裝依賴套件、複製應用程式碼以及設定環境變數和啟動命令。這種方法確保了應用程式在不同環境中的一致性和可重現性。

隨著雲原生技術的發展,Docker 將繼續演進,提供更多創新功能和最佳實踐,以滿足不斷變化的軟體開發需求。開發人員應持續關注最新的 Docker 功能和技術趨勢,以充分利用其強大的容器化能力。