使用 Docker 和 Nginx 打造高性能的二维码服务
使用 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.04RUN 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.listRUN apt update && \apt install -y unzip wgetWORKDIR /data# https://github.com/fukuchi/libqrencodeRUN 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-masterRUN apt install -y libgd-devADD ngx_http_qrcode /data/ngx_http_qrcodeADD nginx-1.15.5.tar.gz /dataADD nginx.conf /dataRUN 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.2expose:- 80networks:- traefiklabels:- "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.comhttps://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.05Tasks: 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 stKiB Mem : 6101684 total, 332268 free, 3649484 used, 2119932 buff/cacheKiB Swap: 998396 total, 936632 free, 61764 used. 2122020 avail MemPID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND8 nobody 20 0 72352 4792 3124 S 0.7 0.1 0:00.02 nginx1 root 20 0 70800 4996 4240 S 0.0 0.1 0:00.01 nginx
但是使用 docker images 命令查看镜像详情,我们可以看到这个镜像还是挺大的,有 400+MB。
REPOSITORY TAG IMAGE ID CREATED SIZEdocker.lab.com/qrcode.lab.com 0.0.1 d98376b43ae9 About a minute ago 454MB
这里我们修改一下上面的镜像 Dockerfile,尝试重新进行镜像构建。
FROM ubuntu:18.04RUN 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.listWORKDIR /tmpRUN 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.confEXPOSE 80ENTRYPOINT [ "/usr/local/nginx/sbin/nginx", "-g", "daemon off;" ]
再次构建完毕,我们会发现镜像只是减少了 35MB,相比较 400MB 多的整体体积,优化部分杯水车薪。
REPOSITORY TAG IMAGE ID CREATED SIZEdocker.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.8RUN 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.confEXPOSE 80ENTRYPOINT [ "/usr/local/nginx/sbin/nginx", "-g", "daemon off;" ]
当镜像打包完毕,我们再次查看镜像体积,可以看到体积有了明显的优化效果。
REPOSITORY TAG IMAGE ID CREATED SIZEdocker.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 生成内容和图片尺寸的判断。
使用 Docker 和 Nginx 打造高性能的二维码服务的更多相关文章
- spring boot高性能实现二维码扫码登录(中)——Redis版
前言 本打算用CountDownLatch来实现,但有个问题我没有考虑,就是当用户APP没有扫二维码的时候,线程会阻塞5分钟,这反而造成性能的下降.好吧,现在回归传统方式:前端ajax每隔1秒或2秒发 ...
- spring boot高性能实现二维码扫码登录(下)——订阅与发布机制版
前言 基于之前两篇(<spring boot高性能实现二维码扫码登录(上)——单服务器版>和<spring boot高性能实现二维码扫码登录(中)——Redis版>)的基础, ...
- 用lua nginx module搭建一个二维码
用lua nginx module搭建一个二维码(qr code)生成器 作者 vinoca 發布於 2014年10月31日 如果有VPS,或者开源的路由器,安装一个nginx,添加lua-nginx ...
- spring boot高性能实现二维码扫码登录(上)——单服务器版
前言 目前网页的主流登录方式是通过手机扫码二维码登录.我看了网上很多关于扫码登录博客后,发现基本思路大致是:打开网页,生成uuid,然后长连接请求后端并等待登录认证相应结果,而后端每个几百毫秒会循环查 ...
- 【thinkphp5.1】 endroid/qrcode 二维码生成
composer 链接: https://packagist.org/packages/endroid/qrcode 注意:PHP版本 要求 7.1+ 1. 使用 composer 安装 endroi ...
- 一次使用Python连接数据库生成二维码并安装为windows服务的工作任务
最近有一个需求,在现有生产系统上的人员库中增加一个此人员关键信息的二维码,支持文字版和跳转版两种方式,与报表工具关联,可打印.以windows服务方式,定时检查,只要发现某人员没有此二维码信息,就生成 ...
- tornado zbar 二维码识别 ,配合nginx 反向代理,supervisord 监控
tornado zbar 二维码识别 ,配合nginx 反向代理,supervisord 监控 1.zbar识别二维码程序,python2.6.6 #!/usr/bin/env python # co ...
- netcore程序部署 docker 异常 --生成图片二维码缺少libdl
最近因业务需求需要在程序中实现二维码图片生成,于是就用到QRCoder开发库.最终在windows环境下部署运行没问题,但切换到docker(centos7.0)后发现是有问题的. 错误信息提示:Th ...
- 基于nginx实现二维码下载安装apk文件
将apk文件置于nginx目录下 <!--进入nginx安装路径--> /usr/local/nginx <!--新建放apk的目录--> mkdir -p resources ...
随机推荐
- desc和show
desc只能查看表结构 查看zx1表结构 desc zx1; mysql> desc zx1 -> ; +---------+---------+------+-----+-------- ...
- CSS 导入-选择器-权重
CSS 导入-选择器 Cascading Style Sheets 层叠样式表 它用来控制网页样式,并允许将样式代码与网页内容分离的一种标记性语言 CSS语法结构 选择器 声明{} 属性名:属性值 c ...
- 2019-2020-12 20199317 《Linux内核原理与分析》 第十二周作业
SET-UID程序漏洞实验 1 实验简介 Set-UID 是 Unix 系统中的一个重要的安全机制.当一个 Set-UID 程序运行的时候,它被假设为具有拥有者的权限.例如,如果程序的拥有者是roo ...
- [开源] 基于Layui组件封装的后台模版,HG-Layui-UI通用后台管理框架V1.0版
HG框架简介 HG-Layui-UI框架,是基于layui最新版UI搭建的一套通用后台管理框架,借鉴了市面上各大主流框架风格,采用iframe标签页实现,保留了传统开发模式的简单实用性. 为快速开发减 ...
- 【nodejs原理&源码赏析(5)】net模块与通讯的实现
[摘要] Node.js net模块的原理及使用 示例代码托管在:http://www.github.com/dashnowords/blogs 一. net模块简介 net模块是nodejs通讯功能 ...
- linux实用小命令--查看文本内容
一.cat命令 $ cat [参数]filename 这还有一些可以和cat命令一起用的参数,可能对你有所帮助. 1.-n 参数会所有的行加上行号: $ cat -n test1 2.这个功能在检查脚 ...
- CSU OJ2151 集训难度
小L正在组织acm暑假集训,但众所周知,暑假集训的萌新中有OI神犇,也有暑假才开始学算法的萌新,如果统一集训的难度,无法很好地让萌新们得到训练,所以小L想了一个办法,根据每次测试的情况,改变萌新们的集 ...
- 了解一下Mysql分布式事务及优缺点、使用案例(php+mysql)
在开发中,为了降低单点压力,通常会根据业务情况进行分表分库,将表分布在不同的库中(库可能分布在不同的机器上),但是一个业务场景可能会同时处理两个表的操作.在这种场景下,事务的提交会变得相对复杂,因为多 ...
- 重排数列-Java实现(2018网易校招研发岗)
题目: 链接:https://www.nowcoder.com/questionTerminal/6c184566ecff4d3baff3536449d4a3e2 来源:牛客网 小易有一个长度为N的正 ...
- pyplot概述
matplotlib.pyplot 是命令行风格的函数集,让matplotlib看起来像MATLAB.Each一样工作.pyplot函数能够对画布(figure)进行一些改变,例如:创 ...