Best Practices for using Lambda@Edge to process images on AWS

Github Provides docker environment and code which process image. Welcome to star, fork or PR to improve the practice. Repo:Click The Link What’s this For the same image link, we may response different sizes of thumbnails according to different pages. Unfortunately, AWS does not directly provide such services. But it provides lambda@edge with CloudFront to handle this kind of demand. Therefore, I designed a set of solutions to achieve the requirements of image processing. This article contains instructions, design solutions and practical steps. ...

2020-08-30 · 8 分钟 · 1548 字

在AWS使用Lambda@Edge处理图片的最佳实践

Github 提供了docker环境和简单的图片处理代码;欢迎star、fork或提交pr以改善该实践。仓库:点我 这是什么 类似阿里云OSS的图片处理服务、腾讯云的数据万象。 因为AWS并没有单独将图片处理单独发布服务,只提供了lambda配合CloudFront用于处理这类需求。因此我设计了一套方案用于实现图片处理的需求,本文档包含使用说明、设计方案。 有了本方案,前端可以在原有的cdn图片链接后面拼接参数,获取对应的缩略图、加水印等图片处理需求。 本方案涉及到的几个角色 CloudFront Amazon的CDN服务,在本方案用于缓存缩略图。下面简称CF Lambda@edge Lambda是Amazon的云函数,就是serverless那一套。 Lambda@edge则是可以运行在CloudFront边缘的函数,比Lambda支持的能力要弱一些。例如runtime只支持Node.js和Python;不支持Layer,导致使用的图片库无法部署在layer,只能全部打包到源码。 对图片的处理逻辑在这一层运行,是本方案的重点对象。下面简称Lambda S3 Amazon的对象存储服务,类似阿里的OSS。在本方案扮演 存储原图、缩略图;cdn回源的角色 工作流程 Image Generate WOrkflow 注意:只有在CF行为规则配置了规则(例如 .jpg@ ),才会触发lambda。直接访问原图的不经过lambda,不必担心过度计费问题。 请参考上图,流程为: 步骤0:用户请求图片链接:链接形如:http://cdn.com/image/abc.jpg@250w_60q.webp。其中 http://cdn.com/image/abc.jpg 是原图链接,@后面是处理参数,具体含义请参看使用手册 步骤1:请求先到达CF,检查CF有缓存则直接返回给用户,并且etag与客户端一致时响应304 Not Modified 步骤2:若CF未命中,则回源到S3获取图片。 步骤3:S3响应后,CF事件会触发给lambda,函数逻辑会对response进行判断: 如果http code为正常值,说明缩略图在S3已存在,那么不进行其它处理,直接将response返回 步骤5:如果http code为异常值,说明S3没有该图,我们需要做以下处理: 将URI从@开始剥离,前面的为原图KEY,后面的为处理参数。我们使用原图KEY从S3桶(CF事件的request链接可以提取到桶名)获取原图,然后使用处理参数对图片进行处理。这里使用sharp图片处理库(底层使用libvips,比ImageMagic性能要好)。 将处理好的图片存储到S3,以便下次CF失效时,直接回源到S3获取。这里存储到S3时,给图片打了标签(createByLambda:1),方便在S3根据标签制定淘汰规则,避免过多缩略图长期存在S3造成浪费。 将图片以base64编码返回到CF,content-encoding为base64。这里之所以使用base64是因为lambda只支持接收json 步骤4:CF将源头的图片存储起来并响应给用户 前端使用说明 url构成:https://cdn域名/文件名@<参数值1><参数名1>_<参数值2><参数名2>.期望转换的文件格式 例子:https://d1xxxxxxxx.cloudfront.net/foamzou/image/4951f0e35a37e5190e78798dcfcad984.jpg@1020w_160h_0e_1l_70q.webp 参数 w: 指定目标缩略图的宽度。1-4096 h: 指定目标缩略图的高度。1-4096 e: 缩放优先边。0:长边优先,1:短边优先,2:强制按指定宽高缩放。默认为0 l: 目标缩略图大于原图是否处理。如果值是1, 即不处理;是0,表示处理。默认为0 p: 比例百分比。 小于100,即是缩小,大于100即是放大。1-1000。如果参数p跟w、h合用时,p将直接作用于w、h (乘以p%)得到新的w、h,例如100w_100h_200p的作用跟200w_200h的效果是一样的。默认为100 q: 质量百分比。1-100。默认为80 r: 是否使用渐进式jpeg。0:不使用,1使用。默认为0。只有在输出格式为jpg时,该参数才会生效。注意:1. 小尺寸图片不建议使用,因为渐进式jpeg会比原图大;2. 能够使用webp尽量使用webp;3. 渐进式展示图片的最佳方案应当是前端同时渲染小图和大图,动画过度到大图 .format 格式转换。目前支持jpg, png, webp。若保留原文件格式,那么 .format 可以不添加 ...

2020-08-30 · 2 分钟 · 239 字

使用netcat能够做什么

楔子 [admonition] 今天朋友找我解决一个问题,他的java服务在阿里服务器里监听了某端口(使用的TCP),但通过公网无法连接。我尝试在本地telnet那个端口(跨公网),不通。在他服务器里telnet 127.0.0.1 端口,是通的。说明服务正常监听了端口。但由于我不熟悉他的java服务,无法判断该java服务是否只监听了本地回环地址。 因此公网无法访问大概有两种可能,一,java服务只监听了本地回环地址; 二、防火墙限制了端口 排除第二种情况对我来说比较简单,我通过netcat在服务器监听端口,然后在本地telnet,不通!说明问题的确出在防火墙身上。该服务器为Ubuntu,使用ufw status查看防火墙状态,显示为inactive,也就是关闭状态。再查看阿里云安全组规则,已经开放了tcp/udp的所有端口(-1/-1)。后面我再次执行ufw disable,端口就通了。所以这是ufw的bug? [/admonition] 引子有点长了。主要是为了说明,如果想知道与服务器之间的tcp连接是否通,可以使用netcat工具去判断。下面介绍下netcat ~ netcat是什么 是一种计算机网络实用程序,用于使用TCP或UDP读写网络连接,号称 TCP/IP 的瑞士军刀。大家一般简写为nc。总之,涉及到网络的事儿,它几乎都能做。为什么叫瑞士军刀,因为它体积很小,不同版本的nc可执行文件只有几十k到300多k,而且大部分linux发行版都有预安装。 各种版本 netcat有许多版本,能力从弱到强为:GUN、BSD、Ncat。基础功能三者都一样,不同的是一些版本额外内置了些高级/有趣的功能(例如Ncat有个参数--chat,可以创建匿名聊天室)。 大部分centos6内置的是BSD版本的nc,我的Centos7里边内置的nc是Ncat(属于nmap工具集里边) 使用man nc,拉到最下边可以看到你的nc版本。(使用man你基本能够查阅所有的用法了,其它软件也是如此,只要是标准安装的) ps. socat号称是更为强大的nc,有兴趣的小伙伴可以自己去看看。 用途 检查端口通不通 以往我一直使用telnet来判断某个端口是否通,但telnet是基于tcp协议的,如果要判断udp端口就无能为力了。这时可以使用nc来判断。为了方便实验,本文统一使用同一台机器模拟服务端和客户端。 # 咱们使用nc创建一个tcp协议监听的端口。-l为listen,默认协议为tcp nc -l 8088 # 使用nc连上该端口。-v(verbose)用于显示更多信息,-z(zero I/O)表示不发送数据包,仅显示连接状态。 # 下面succeed表示端口是通的 nc -vz 127.0.0.1 8088 Connection to 127.0.0.1 8088 port [tcp/radan-http] succeeded! # 创建一个udp端口。-u指使用udp协议 nc -lu 8088 # 同样,加一个u表示使用udp连接该端口,同时你会看到服务端打印出若干个X。 # 不是说加了z参数就不会发数据包吗,为什么服务端收到了报文?我认为udp是无连接状态的,通过系统调用write # 往该套接字发数据,通过返回值才知道包发出去没有,从而判断udp端口是否通 nc -vzu 127.0.0.1 8088 Connection to 127.0.0.1 8088 port [udp/radan-http] succeeded! 端口扫描 # 扫描tcp端口。-w(wait)指定连接超时时间,单位秒。 # 连接成功的端口将作为标准输出 nc -v -w3 -z 127.0.0.1 1-65535 | tee succeed_port.log # 下面摘抄部分连接成功的端口 Connection to 127.0.0.1 22 port [tcp/ssh] succeeded! Connection to 127.0.0.1 25 port [tcp/smtp] succeeded! Connection to 127.0.0.1 80 port [tcp/http] succeeded! Connection to 127.0.0.1 443 port [tcp/https] succeeded! Connection to 127.0.0.1 1100 port [tcp/mctp] succeeded! Connection to 127.0.0.1 1111 port [tcp/lmsocialserver] succeeded! Connection to 127.0.0.1 2255 port [tcp/vrtp] succeeded! Connection to 127.0.0.1 3001 port [tcp/*] succeeded! Connection to 127.0.0.1 3306 port [tcp/mysql] succeeded! Connection to 127.0.0.1 4300 port [tcp/corelccam] succeeded! Connection to 127.0.0.1 4369 port [tcp/epmd] succeeded! Connection to 127.0.0.1 5672 port [tcp/amqp] succeeded! Connection to 127.0.0.1 6553 port [tcp/*] succeeded! # 扫描udp端口。nc -v -zu 127.0.0.1 1-65535 # 以下为我本地扫描结果 Connection to 127.0.0.1 636 port [udp/ldaps] succeeded! Connection to 127.0.0.1 35157 port [udp/*] succeeded! Connection to 127.0.0.1 54890 port [udp/*] succeeded! 文件传输 归根到底都是创建一个tcp/udp连接,通过连接收发数据而已。所以,无论数据是ascii字符串,二进制文件都可以发送/接收。 为了加快传输速率/加密,你甚至还可以在发送之前对数据进行压缩/加密。 对于大文件,个人认为还是scp、rsync这类专业的工具靠谱。小文件可以试试这种方法,毕竟简单,不需要ssh认证。 ...

2020-05-11 · 2 分钟 · 283 字

恢复数据库快照xb文件到新实例

背景 背景就是我把线上某张表的某个字段给清空了。用的是腾讯云的数据库实例,运维配置的快照是每天早上备份一次,因此可以通过快照文件恢复数据。直接恢复到线上实例是不现实的,所以想法是将快照恢复到本地实例,然后用脚本/工具把数据导出来,再写入线上实例。当时恢复过程比较曲折,这里记录下比较好的操作步骤。 获取xb文件 从云服务商或你自行备份的xb文件中获取。腾讯云 这里 可找到备份列表 安装xbstream和qpress工具 腾讯云使用qpress压缩文件,再通过xbsteam打包为xb文件。[参考腾讯云文章] 安装xbstream 下载并安装 XtraBackup 工具。 下载地址请参见 Percona XtraBackup 官网,请选择 Percona XtraBackup 2.4.6 及以上的版本,安装介绍请参见 Percona XtraBackup 2.4。 支持的实例版本:MySQL 5.5、5.6、5.7 高可用版和金融版。 启用数据加密功能的实例,不支持使用物理备份恢复数据库。 我使用的是mac,使用brew进行安装 brew install percona-xtrabackup 安装qpress 从quicklz下载编译好的二进制文件。 我的mac无法直接使用linux的可执行文件,所以从上面网站下载源码,编译安装。 mac编译qpress时报错 qpress.cpp:1040:18: error: use of undeclared identifier 'isatty' tty_stderr = isatty(fileno(stderr)); ^ 1 error generated. make: *** [g++] Error 1 qpress.cpp 添加头文件 #include <unistd.h> 重新编译成功。将编译好的qpress拷贝到 /usr/local/bin 。必须放到该目录下,因为xbstream工具调用qpress是用的绝对路径(为啥这样设计 ̄□ ̄||) 对xb文件进行解包&解压缩 xbstream -x -C /tmp/新建的目录 < ~/你的xb文件.xb # 使用 xbstream 命令将备份文件解包到目标目录 xtrabackup --decompress --target-dir=/tmp/新建的目录 # 将目标目录下所有以.qp结尾的文件都解压出来 将解压出来的frm、ibd文件附到本地mysql实例 腾讯云的方法 腾讯云文档的方法是起一个mysqld_safe实例将data配置为刚刚那个新建的目录 ...

2020-04-29 · 1 分钟 · 147 字

用php对象,简化Json Schema的定义

Github地址 使用php对象,描述Json-Schema变得更容易(支持draft-07 和 draft-06) 使用opis/json-schema作为校验器 好处 定义容易,不用写复杂的json 定义更有可读性 安装 composer require "foamzou/easy-json-schema" 基本使用 use Foamzou\EasyJsonSchema\Manager\Validator; use Foamzou\EasyJsonSchema\Manager\Parser; use Foamzou\EasyJsonSchema\Type\{ Str, Integer }; // 定义一个schema $schema = new Obj([ 'name' => (new Integer)->min(2)->max(5), 'age' => (new Str)->max(120), ]); $data = [ 'name' => 'foam', 'age' => 18, ]; // 生成json-schema $jsonSchema = Parser::run($schema); //校验数据合法性,如果校验失败,errorMessage将返回具体信息 $bool = Validator::getInstance()->isValid($jsonSchema, $data, $errorMessage); Schema的定义 下面是与json-schema的对比,可以看到使用php对象的定义会更简单、更有可读性且更容易维护 php版 ...

2019-07-28 · 2 分钟 · 416 字

nginx proxy_pass后gzip不生效

有一台服务器只能对外开80端口,但该服务器有几个项目同时共用。因此做了一个方案,使用不同的url前缀,proxy_pass到对应项目监听的端口。 如default.conf配置如下 server { listen 80 default_server; location /a/ { rewrite ^/a/(.*)$ /$1 break; # 剥掉 /a 这一层 proxy_pass http://127.0.0.1:8083; } location /b/ { rewrite ^/b/(.*)$ /$1 break; proxy_pass http://127.0.0.1:8084; } location /c/ { rewrite ^/c/(.*)$ /$1 break; proxy_pass http://127.0.0.1:8085; } } a项目配置里开启了gzip server { listen 8083; root /path/to/a; gzip on; gzip_comp_level 3; .... } 但发现gzip未生效。 后面把gzip配置放到default.conf的location部分就正常运行了。 ...

2019-07-26 · 1 分钟 · 82 字

编译安装php7.3

最近在一台CentOS6.2的机器上部署php7.3,系统有点旧,稍微折腾点。 安装需要的依赖 sudo yum install libxml2 libxml2-devel openssl openssl-devel bzip2 bzip2-devel libjpeg libpng freetype libjpeg-devel libpng-devel freetype-devel gmp-devel readline-devel libxslt-devel libmemcached libmemcached-devel -y 编译安装 到官网下载最新的稳定版本 注意用户组最好与nginx的保持一致,例如我这里设置与nginx一致的nobody ./configure --prefix=/usr/local/php7 --with-config-file-path=/usr/local/php7/etc --enable-fpm --with-fpm-user=nobody --with-fpm-group=nobody --enable-inline-optimization --disable-debug --disable-rpath --enable-shared --enable-soap --with-libxml-dir --with-xmlrpc --with-openssl --with-mhash --with-pcre-regex --with-sqlite3 --with-zlib --enable-bcmath --with-iconv --with-bz2 --enable-calendar --with-curl=/usr/local/include/curl/ --with-cdb --enable-dom --enable-exif --enable-fileinfo --enable-filter --with-pcre-dir --enable-ftp --with-gd --with-openssl-dir --with-jpeg-dir --with-png-dir --with-zlib-dir --with-freetype-dir --enable-gd-jis-conv --with-gettext --with-gmp --with-mhash --enable-json --enable-mbstring --enable-mbregex --enable-mbregex-backtrack --with-onig --enable-pdo --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-zlib-dir --with-pdo-sqlite --with-readline --enable-session --enable-shmop --enable-simplexml --enable-sockets --enable-sysvmsg --enable-sysvsem --enable-sysvshm --enable-wddx --with-libxml-dir --with-xsl --enable-zip --enable-mysqlnd-compression-support --with-pear --enable-opcache make sudo make install 编译期间遇到的问题汇总 checking for cURL 7.15.5 or greater… configure: error: cURL version 7.15.5 or later is required to compile php with cURL support 实际上我本地已经安装了最新的版本。–with-curl不指定路径的话,会在/usr/include/curl下找头文件。但我本机已有的libcurl貌似没有这些头文件。尝试`yum install curl curl-devel`,报了一个多版本冲突的问题。所以最后还是从curl官网下载了最新的tar包,手动编译安装后,--with-curl指定路径为/usr/local/include/curl/ ...

2019-03-28 · 1 分钟 · 189 字

用lockf保证同一时间只有一个进程运行

安装 参见github 使用场景 保证同一时间只有一个进程运行。 例如 crontab 设定每分钟跑一次 1.php ,但如果超过1分钟该脚本还没执行完,就会出现多个php脚本同时运行的情况,在某些场景下可能会有问题。 为了满足上述需求,我们可能会在脚本里添加一段代码,创建锁,执行完后删除锁,若锁文件存在则直接return。 还有另一种解决方案就是用 lockf 使用例子: lockf -s -t 0 /tmp/xx.lock /usr/local/bin/php -f 1.php

2019-02-25 · 1 分钟 · 21 字

给你的Mac/Linux的rm装一个回收站

作为程序员,在工作中经常用到rm。我在不久前用vscode写代码,在底下的终端里想删掉没用的文件,手抖把未提交到git的代码文件删了。还好代码量不多,否则会崩溃。毕竟重写代码是很痛苦的~ 因此本文标题提上了日程 选择一款安全的删除脚本 Github看到一个脚本满足需求。 github地址,里边有多种安装方式。我选择的是npm全局安装。 npm i -g safe-rm 安装后,safe-rm命令就可以用了~ 将安装好的脚本设置为rm的别名 vim编辑~/.bash_profile(或其他bash启动时会执行的文件)。添加 alias rm='safe-rm' 由于我使用了fish-shell,因此还需要在fish启动时会执行的config文件里添加别名:vim编辑~/.config/fish/config.fish。添加 alias rm='safe-rm' Done 添加完之后别忘了重新打开终端窗口哦(或者source刚刚的配置文件)。至此,rm后文件的被mv到~/.Trash。即使是重名的文件也会在文件尾添加时间后缀,保证文件不被覆盖。

2018-10-09 · 1 分钟 · 19 字

HTTPS原理解析

HTTP是什么 超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)是互联网上应用最为广泛的一种网络协议。是一个基于请求与响应模式的、无状态的、应用层的协议,常基于TCP的连接方式,绝大多数的Web开发,都是构建在HTTP协议之上的Web应用。 为了方便通信就必须统一约定好双方的数据协议,如果每个人都搞一套自己的规则,这玩起来就很麻烦了。因此IETF (互联网工程任务组) 推动了HTTP的统一和发展。现在大家用得最多的还是1999年收录于RFC 2616的1.1版本,2015年发布的2.0版本在推广道路上任重道远。 HTTP[S]报文 最直观上的差异,HTTP协议用明文传输报文,HTTPS用密文。 HTTP的缺陷 窃听风险(eavesdropping):明文传输,第三方可以获知通信内容。 篡改风险(tampering):第三方可以修改通信内容。 冒充风险(pretending):第三方可以冒充他人身份参与通信。 HTTPS是什么 超文本传输安全协议(英语:Hypertext Transfer Protocol Secure,缩写:HTTPS,常称为HTTP over TLS,HTTP over SSL或HTTP Secure) 是一种透过计算机网络进行安全通信的传输协议。HTTPS经由HTTP进行通信,但利用SSL/TLS协议来加解密数据包。 HTTPS开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性; HTTPS并不是一个单独的协议,而是对工作在一加密连接(TLS/SSL)上的常规HTTP协议的称呼。因此HTTPS被称之为身披SSL外壳的HTTP。 SSL/TLS协议 传输层安全性协议(Transport Layer Security,缩写作 TLS),及其前身安全套接层(Secure Sockets Layer,缩写作 SSL)是一种安全协议,目的是为互联网通信,提供安全及数据完整性保障 网景公司(Netscape)在1994年推出首版网页浏览器,网景导航者时,推出HTTPS协议,以SSL进行加密,这是SSL的起源。后面,IETF将SSL进行标准化,称为TLS。在浏览器、电子邮件、即时通信、VoIP、网络传真等应用程序中,广泛支持这个协议 协议 年份 描述 SSL 1.0 N/A 从未公开过,因为存在严重的安全漏洞 SSL 2.0 1995 因为存在数个严重的安全漏洞而被3.0版本替代 SSL 3.0 1996 2014年10月Google发现该版本的严重漏洞,建议全面禁用SSL版本 TLS 1.0 1999 IETF标准化后的第一个版本。包括可以降级到SSL 3.0的实现,这削弱了连接的安全性 TLS 1.1 2006 - TLS 1.2 2008 删除了对SSL的兼容。目前使用最广泛的版本 TLS 1.3 2018 截至本文撰写,为建议标准的互联网草案 在TCP/IP模型的位置:介于传输层与应用层之间 ...

2018-08-23 · 3 分钟 · 440 字