本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或从新修改使用,但须要注明来源。 署名 4.0 国际 (CC BY 4.0)javascript
本文做者: 苏洋html
建立时间: 2018年10月19日 统计字数: 7618字 阅读时间: 16分钟阅读 本文连接: soulteary.com/2018/10/19/…java
本文将演示如何使用 Docker
完整打造一个基于 Nginx
的高性能二维码服务,以及对整个服务镜像进行优化的方法。若是你的网络情况良好,完整操做和体验时间应不超过 15
分钟。linux
最近有一个小需求,须要在页面中快速生成一些二维码。nginx
说到生成二维码,方法不少,好比按照 QRCode
算法进行计算以后:git
GD
绘图库在语言中的 API
进行绘制,并生成图片,而后配合可以提供 HTTP
服务的软件对用户提供图片访问地址。CSS
和 HTML
生成能够识别的页面图案,而后配合可以提供 HTTP
服务的软件对用户提供图片访问地址。Canvas
生成二维码图片,或者和上一个方案同样,生成 DOM
图案。可是只是为了一个功能,就去配置一套完整的语言环境,引入一堆三方依赖,总有一种杀鸡用牛刀的感受,而且在资源利用效率上来讲,也不是最优解。github
而使用客户端进行生成,如今虽然不存在太多的兼容问题,可是须要额外引入脚本资源,图片生成效率也相对较慢。算法
那么有没有什么环保高效的方案呢?docker
天然是有的,仍是选择服务端生成,可是扔掉语言运行时,直接使用 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
看来服务是正常运行的,本文的基础需求到这里就解决了,而且,为了这个服务可以更好的被使用,咱们能够在书签中输入下面的脚本代码:
javascript:(function(){document.location.href='https://qrcode.lab.com/?size=150&txt='+encodeURIComponent(document.location.href);})()
复制代码
当你点击书签的时候,会将当前页面自动转换为一个能够扫描的二维码。
虽然上面的内容已经知足了咱们的基础需求,可是做为一个有追求的开发者,咱们不光是要追求执行效率,还要追求储存效率。
虽然 Nginx
的运行资源占用很少。
top - 09:50:29 up 21 days, 19 min, 0 users, load average: 0.03, 0.05, 0.05
Tasks: 4 total, 1 running, 3 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.3 us, 0.3 sy, 0.0 ni, 99.4 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 6101684 total, 332268 free, 3649484 used, 2119932 buff/cache
KiB Swap: 998396 total, 936632 free, 61764 used. 2122020 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8 nobody 20 0 72352 4792 3124 S 0.7 0.1 0:00.02 nginx
1 root 20 0 70800 4996 4240 S 0.0 0.1 0:00.01 nginx
复制代码
可是使用 docker images
命令查看镜像详情,咱们能够看到这个镜像仍是挺大的,有 400+MB
。
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.lab.com/qrcode.lab.com 0.0.1 d98376b43ae9 About a minute ago 454MB
复制代码
这里咱们修改一下上面的镜像 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
WORKDIR /tmp
RUN apt update && apt install -y unzip wget autoconf automake autotools-dev libtool pkg-config libpng-dev libgd-dev libpcre3 libpcre3-dev && \
wget https://nginx.org/download/nginx-1.15.5.tar.gz && tar -zxvf nginx-1.15.5.tar.gz && rm -rf nginx-1.15.5.tar.gz && \
wget https://github.com/dcshi/ngx_http_qrcode_module/archive/master.zip && unzip master.zip && mv ngx_http_qrcode_module-master ngx_http_qrcode_module && rm -rf master.zip && \
wget https://github.com/fukuchi/libqrencode/archive/master.zip && unzip master.zip && mv libqrencode-master libqrencode && \
cd libqrencode && ./autogen.sh && ./configure && make && make install && ldconfig && \
cd /tmp/nginx-1.15.5 && ./configure --add-module=../ngx_http_qrcode_module/ && make && make install && \
apt remove -y unzip wget autoconf automake autotools-dev libtool pkg-config && \
rm -rf /tmp/* && rm -rf /var/cache/
ADD nginx.conf /usr/local/nginx/conf/nginx.conf
EXPOSE 80
ENTRYPOINT [ "/usr/local/nginx/sbin/nginx", "-g", "daemon off;" ]
复制代码
再次构建完毕,咱们会发现镜像只是减小了 35MB
,相比较 400MB
多的总体体积,优化部分杯水车薪。
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.lab.com/qrcode.lab.com 0.0.1 a24ffc73121a 1 minutes ago 420MB
复制代码
那么优化就到此为止了么?显然不是。
这里咱们选择使用体积更小的 Linux
镜像,Alpine
来进行一样功能的二维码服务的容器镜像。
由于 Alpine
和 Ubuntu
不是一个社区进行维护,因此软件包不少名称是不一样的,这里我直接提供我已经查找修改完毕的镜像文件。
若是你也有相似的需求,须要将不一样系统的软件进行迁移安装,能够在 https://pkgs.alpinelinux.org/packages
查找你所须要的软件包的名称。
FROM alpine:3.8
RUN cat /etc/apk/repositories | sed -e "s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/" | tee /etc/apk/repositories && \
apk --update add openssl-dev pcre-dev zlib-dev wget build-base autoconf automake libtool libpng-dev libgd pcre pcre-dev pkgconfig gd-dev && \
cd /tmp && \
wget https://nginx.org/download/nginx-1.15.5.tar.gz && tar -zxvf nginx-1.15.5.tar.gz && rm -rf nginx-1.15.5.tar.gz && \
wget https://github.com/dcshi/ngx_http_qrcode_module/archive/master.zip && unzip master.zip && mv ngx_http_qrcode_module-master ngx_http_qrcode_module && rm -rf master.zip && \
wget https://github.com/fukuchi/libqrencode/archive/master.zip && unzip master.zip && mv libqrencode-master libqrencode && \
cd libqrencode && ./autogen.sh && ./configure && make && make install && ldconfig || true && \
cd /tmp/nginx-1.15.5 && ./configure --add-module=../ngx_http_qrcode_module/ && make && make install && \
apk del build-base autoconf automake pkgconfig && \
rm -rf /tmp/* && rm -rf /var/cache/apk/*
ADD nginx.conf /usr/local/nginx/conf/nginx.conf
EXPOSE 80
ENTRYPOINT [ "/usr/local/nginx/sbin/nginx", "-g", "daemon off;" ]
复制代码
当镜像打包完毕,咱们再次查看镜像体积,能够看到体积有了明显的优化效果。
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.lab.com/qrcode.lab.com 0.0.2 d236b96c8950 1 minutes ago 79.1MB
复制代码
还记得本文标题中的关键词“高性能”嘛,虽然说我我的测试单实例的响应时间都在 10ms
左右,可是若是你真的考虑使用它作对外服务的话,可使用下面的命令,根据本身状况对节点进行动态扩容,成倍提升服务响应能力。
docker-compose scale qrcode=4
复制代码
或者使用
docker-compose up --scale qrcode=2 -d
复制代码
若是你也是 Traefik
用户,你将会看到你的实例被成功进行挂载以及流量负载均衡。
另外,为了不被恶意利用,还须要考虑使用 Nginx
/ iptable
的 req_limit
等模块限制访问频率,以及适当修改 ngx_http_qrcode_module
生成内容和图片尺寸的判断。
—EOF
我如今有一个小小的折腾群,里面汇集了一些喜欢折腾的小伙伴。
在不发广告的状况下,咱们在里面会一块儿聊聊软件、HomeLab、编程上的一些问题,也会在群里不按期的分享一些技术沙龙的资料。
喜欢折腾的小伙伴欢迎扫码添加好友。(请注明来源和目的,不然不会经过审核) 关于折腾群入群的那些事