Chúng tôi có một số tùy chọn để truyền dữ liệu theo thời gian thực trong các ứng dụng web. Chúng tôi có thể sử dụng bỏ phiếu, bỏ phiếu dài, Sự kiện do máy chủ gửi và WebSockets. Hai cái cuối cùng có thể được sử dụng cho các tình huống đẩy máy chủ trong đó chúng tôi muốn gửi dữ liệu tới trình duyệt mà không có bất kỳ yêu cầu cụ thể nào từ máy khách. Tất cả các giải pháp này đều có ưu điểm và nhược điểm, vì vậy chúng tôi cần đảm bảo rằng một phương pháp cụ thể là tốt nhất cho ứng dụng của chúng tôi
Hôm nay, chúng ta sẽ xem việc bắt đầu truyền dữ liệu đến trình duyệt từ ứng dụng Python phụ trợ bằng cách sử dụng WebSockets đơn giản như thế nào. Có nhiều khung web Python có khả năng làm điều đó, nhưng đối với việc hủy bỏ này, chúng tôi sẽ sử dụng FastAPI, một khung không đồng bộ hiện đại đang đạt được động lực trong không gian mới của các khung không đồng bộ Python
Truyền phát trong WebSockets về cơ bản có nghĩa là gửi các gói dữ liệu nhỏ qua kết nối mở giữa máy chủ và máy khách. Chúng tôi có thể gửi cả gói dữ liệu văn bản hoặc nhị phân và những gì chúng tôi đặt bên trong là hoàn toàn tùy thuộc vào chúng tôi. Vì JSON là một định dạng dữ liệu phổ biến [mặc dù không thực sự hiệu quả về bộ nhớ], chúng tôi sẽ sử dụng nó để cấu trúc các gói dữ liệu của mình và gửi chúng dưới dạng văn bản để dễ dàng gỡ lỗi
Dữ liệu mẫu sẽ chỉ là một dãy số mà chúng tôi sẽ hiển thị thành biểu đồ tự cập nhật trên trang web của khách hàng, mô phỏng dữ liệu chuỗi thời gian. Với mục đích này, tôi đã chọn một thư viện JavaScript TimeChart đơn giản vì nó dễ sử dụng, được xây dựng trên WebGL để tăng hiệu suất và hỗ trợ cập nhật liên tục cho dữ liệu chuỗi thời gian [dữ liệu trong biểu đồ sẽ tự động chuyển từ phải sang trái, luôn hiển thị mới . Có những thư viện biểu đồ khác có thể làm điều này, nhưng TimeChart rất tối giản và có dung lượng nhỏ, hoàn hảo cho ví dụ này
Để chạy chương trình, chúng ta sẽ cần cài đặt một vài phụ thuộc. FastAPI [khuôn khổ web], Uvicorn [máy chủ ASGI] và jinja2 [để hiển thị các mẫu phía máy chủ] cho phần phụ trợ và TimeChart và các phần phụ thuộc của nó cho phần đầu. Như thường lệ, bạn có thể tìm thấy toàn bộ ví dụ trên Github dưới dạng truyền dữ liệu thời gian thực của Python bằng FastAPI và WebSockets, bao gồm tất cả mã nguồn cũng như các phần phụ thuộc được xác định bằng Thơ
Trước tiên hãy bắt đầu với mã Python của chúng tôi
import json
import asyncio
from fastapi import FastAPI
from fastapi import Request
from fastapi import WebSocket
from fastapi.templating import Jinja2Templatesapp = FastAPI[]
templates = Jinja2Templates[directory="templates"]with open['measurements.json', 'r'] as file:
measurements = iter[json.loads[file.read[]]]@app.get["/"]
def read_root[request: Request]:
return templates.TemplateResponse["index.htm", {"request": request}]
@app.websocket["/ws"]
async def websocket_endpoint[websocket: WebSocket]:
await websocket.accept[]
while True:
await asyncio.sleep[0.1]
payload = next[measurements]
await websocket.send_json[payload]
Như bạn có thể thấy, đoạn mã này khá ngắn. Về cơ bản chúng tôi đang làm một vài điều ở đây
- tạo đối tượng FastAPI
app
mà sau này chúng ta sẽ chạy bằng máy chủ uvicorn - đang tải tệp JSON đo lường của chúng tôi có chứa tập dữ liệu mẫu về các giá trị mà chúng tôi sẽ truyền trực tuyến tới máy khách
- xác định tuyến đường trang chủ của chúng tôi trả về mẫu jinja2 được hiển thị chứa ứng dụng JavaScript phía máy khách của chúng tôi
- xác định điểm cuối WebSocket của chúng tôi [trên
/ws
] sẽ liên tục gửi từng giá trị của chúng tôi dưới dạng cấu trúc dữ liệu JSON tới bất kỳ máy khách nào sẽ kết nối với nó
Tôi đã sử dụng hàm iter[]
khi tải tập dữ liệu mẫu của mình để tạo trình lặp Python để chúng ta có thể chỉ cần lấy một giá trị tiếp theo trong danh sách, tạo cho chúng ta cảm giác có một luồng dữ liệu liên tục
Ngoài ra, asyncio.sleep[]
được gọi để làm cho luồng dữ liệu chậm hơn một chút
Bây giờ, hãy xem mẫu
Real time streaming
0 của chúng tôi, nơi chúng tôi cũng lưu trữ mã JavaScript của mình
Real time streaming
Lúc đầu, chúng ta chỉ cần thêm một số tấm nồi hơi. liên kết đến thư viện TimeChart và tất cả các phần phụ thuộc của nó, tạo kiểu cho trình giữ chỗ biểu đồ của chúng tôi và tạo trình giữ chỗ biểu đồ HTML của chúng tôi [dưới dạng div đơn giản với id
Real time streaming
1]Phần còn lại của mã là ứng dụng JavaScript nhỏ của chúng tôi, nơi chúng tôi tạo đối tượng TimeChart biểu thị biểu đồ của mình, tạo đối tượng WebSocket và xác định trình nghe sẽ nhận luồng dữ liệu của chúng tôi [hàm
Real time streaming
2]Có một số điều cần suy nghĩ khi sử dụng thư viện TimeChart
3 phải chứa một mảng các đối tượng ở định dạng
Real time streaming
0 cho các giá trị x và y
Real time streaming
- mảng này có thể được cập nhật bất cứ lúc nào, nhưng sau khi cập nhật, chúng ta cần gọi
1 để các thay đổi được phản ánh trong biểu đồ
Real time streaming
2 đang yêu cầu Biểu đồ thời gian cập nhật phạm vi hiển thị khi dữ liệu mới được thêm vào
Real time streaming
3 xác định phạm vi hiển thị cho biến X [bạn nên chọn phạm vi này theo chiều rộng của trình duyệt hoặc chiều rộng của vùng chứa để kéo dài dữ liệu sao cho thuận mắt]
Real time streaming
- chúng ta chỉ đơn giản là sử dụng gia số +1 đơn giản trên trục X, nhưng khi phát triển biểu đồ chuỗi thời gian thực, chúng ta cần xem xét nên đặt giá trị nào ở đây [Biểu đồ thời gian yêu cầu trình tự gia tăng lý tưởng dựa trên dữ liệu thời gian của
Việc sử dụng luồng dữ liệu WebSockets cũng đơn giản về phía JavaScript. Chúng tôi chỉ cần chỉ định địa chỉ của luồng [là điểm cuối ws của chúng tôi] và xác định điều gì sẽ xảy ra khi chúng tôi nhận dữ liệu. Vì chúng tôi đang sử dụng luồng dưới dạng văn bản, chúng tôi chỉ cần chuyển đổi từng khung dữ liệu thành JSON để lấy giá trị của chúng tôi
Tin hay không, đây là nó. Chúng tôi vừa tạo một luồng dữ liệu thời gian thực của dữ liệu chuỗi thời gian giả và hiển thị dưới dạng biểu đồ tự cập nhật động trong trình duyệt