使用 Docker 和 Nginx 打造高性能的二維碼服務
本文使用「署名 4.0 國際 (CC BY 4.0)」許可協議,歡迎轉載、或重新修改使用,但需要註明來源。 署名 4.0 國際 (CC BY 4.0)
本文作者: 蘇洋
創建時間: 2018年10月19日 統計字數: 7618字 閱讀時間: 16分鐘閱讀 本文鏈接: https://soulteary.com/2018/10/19/use-docker-and-nginx-to-build-high-performance-qr-code-services.html
使用 Docker 和 Nginx 打造高性能的二維碼服務
本文將演示如何使用 Docker
完整打造一個基於 Nginx
的高性能二維碼服務,以及對整個服務鏡像進行優化的方法。如果你的網路狀況良好,完整操作和體驗時間應不超過 15
分鐘。
動手前的腦洞
最近有一個小需求,需要在頁面中快速生成一些二維碼。
說到生成二維碼,方法很多,比如按照 QRCode
演算法進行計算之後:
- 使用各種服務端語言,然後調用
GD
繪圖庫在語言中的API
進行繪製,並生成圖片,然後配合能夠提供HTTP
服務的軟體對用戶提供圖片訪問地址。 - 使用服務端語言,然後使用
CSS
和HTML
生成可以識別的頁面圖案,然後配合能夠提供HTTP
服務的軟體對用戶提供圖片訪問地址。 - 使用客戶端腳本,使用
Canvas
生成二維碼圖片,或者和上一個方案一樣,生成DOM
圖案。 - …
但是只是為了一個功能,就去配置一套完整的語言環境,引入一堆三方依賴,總有一種殺雞用牛刀的感覺,並且在資源利用效率上來說,也不是最優解。
而使用客戶端進行生成,現在雖然不存在太多的兼容問題,但是需要額外引入腳本資源,圖片生成效率也相對較慢。
那麼有沒有什麼環保高效的方案呢?
自然是有的,還是選擇服務端生成,但是扔掉語言運行時,直接使用 Nginx
提供服務。
使用 Nginx 進行二維碼生成
這裡可以使用一個現成的開源模塊 ngx_http_qrcode_module 。
它通過將用戶請求參數進行轉換,並調用使用 C
實現的二維碼快速生成庫 libqrencode 的 QRcode_encodeString
實現二維碼快速生成,在未開啟緩存的情況下,測試平均生成圖片在 10ms
左右。
為了方便大家理解全部的安裝配置過程,我先提供一個「啰嗦」版本的 Dockerfile
:
FROM ubuntu:18.04
RUN cat /etc/apt/sources.list | sed -e "s/archive.ubuntu.com/mirrors.aliyun.com/" | sed -e "s/security.ubuntu.com/mirrors.aliyun.com/" | tee /etc/apt/sources.list
RUN apt update &&
apt install -y unzip wget
WORKDIR /data
# https://github.com/fukuchi/libqrencode
RUN apt install -y autoconf automake autotools-dev libtool pkg-config libpng-dev &&
cd /data && wget https://github.com/fukuchi/libqrencode/archive/master.zip && unzip master.zip && rm -rf master.zip &&
cd libqrencode-master && ./autogen.sh && ./configure && make && make install && ldconfig &&
cd .. && rm -rf libqrencode-master
RUN apt install -y libgd-dev
ADD ngx_http_qrcode /data/ngx_http_qrcode
ADD nginx-1.15.5.tar.gz /data
ADD nginx.conf /data
RUN apt install -y libpcre3 libpcre3-dev &&
cd nginx-1.15.5 && ./configure --add-module=../ngx_http_qrcode/ &&
make && make install && mv /data/nginx.conf /usr/local/nginx/conf/nginx.conf &&
cd .. && rm -rf ngx_http_qrcode
將上面的文件保存完畢。接下來我們來配置 Nginx
。
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
set $fg_color 000000;
set $bg_color FFFFFF;
set $level 0;
set $hint 2;
set $size 300;
set $margin 80;
set $version 2;
set $case 0;
set $txt "https://soulteary.com";
if ( $arg_fg_color ){
set $fg_color $arg_fg_color;
}
if ( $arg_bg_color ){
set $bg_color $arg_bg_color;
}
if ( $arg_level ){
set $level $arg_level;
}
if ( $arg_hint ){
set $hint $arg_hint;
}
if ( $arg_size ){
set $size $arg_size;
}
if ( $arg_margin ){
set $margin $arg_margin;
}
if ( $arg_ver ){
set $version $arg_ver;
}
if ( $arg_case ){
set $case $arg_case;
}
if ( $arg_txt ){
set $txt $arg_txt;
}
qrcode_fg_color $fg_color;
qrcode_bg_color $bg_color;
qrcode_level $level;
qrcode_hint $hint;
qrcode_size $size;
qrcode_margin $margin;
qrcode_version $version;
qrcode_casesensitive $case;
qrcode_urlencode_txt $txt;
qrcode_gen;
}
}
}
將上面的配置保存為 nginx.conf
,然後使用下面的命令進行鏡像構建。
docker build -t docker.lab.com/qrcode.lab.com .
如果你的網路通暢,5分鐘之內,這個鏡像就構建完畢了。接下來,我們對它進行一下可用性驗證。
將下面的配置文件保存為 docker-compose.yml
,然後使用 docker-compose up
命令啟動,一個支持 HTTP/HTTPS
,域名為 qrcode.lab.com
的網站就準備就緒了。
這裡我使用了 Traefik
進行服務發現,感興趣的童鞋可以參考我以前寫的文章: 使用服務發現改善開發體驗 、 更完善的 Docker + Traefik 使用方案 、使用 Traefik 的一些補充細節),一旦你開始使用並掌握了它,你會發現搭建高可擴展的 Web
服務變的更簡單了。
version: 3
services:
qrcode:
image: docker.lab.com/qrcode.lab.com:0.0.2
expose:
- 80
networks:
- traefik
labels:
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.frontend.rule=Host:qrcode.lab.com"
- "traefik.frontend.entryPoints=http,https"
networks:
traefik:
external: true
然後我們在瀏覽器中分別訪問,來驗證二維碼服務是否就緒:
https://qrcode.lab.com
https://qrcode.lab.com/?size=150&margin=20&txt=https%3A%2F%2Fsoulteary.com