無標題文檔

使用 Docker 部署 VPS 备忘

本 Blog 的代码也有很多的年头,当时使用的技术过了几年在目前看来有些的陈旧。同时,在 Vultr 的服务器空间也即将到期,所以考虑干脆做个迁移顺便将目前 VPS 上的服务也一起整理了下。

这一整理,发现了不少的巨坑,这在这里记录下。先说说在迁移前 VPS 目前的主要问题

  1. 部分代码老旧,同时又有新的代码,运行环境就有好几套;
  2. 尝试使用 Node 的工具进行开发,然而 Nginx 以及 php-fpm 独占了 80 端口,配置文件越来越复杂;
  3. 权限分配不合理,有部分的权限使用 root 运行有安全上的风险;
  4. 备份机制不合理,没有做到企业级的多点备份(虽然个人 VPS 没必要,但图个心安)。

其他情况不多说,重新整理以后的 VPS 应用架构图如下,相对来说还是不是很复杂:

https://files.gracecode.com/2017_10_12/1507794332@800.png

综合价格以及习惯的因素(可能是情怀更多?),大部分选择了阿里云的服务。同时针对以上的问题,这边的解决方案是:

  1. 使用不同的 Docker 集群将 php5 和 php7 的应用分别调用,相互不受影响。老旧的代码就让它们在 php5 环境中「颐养天年」;
  2. 最前端使用 Tengine 分发请求到每个对应的 Docker,方便管理;
  3. 使用 Docker 以后,权限这块就相对来说好控制很多,宿主机不受任何的影响;
  4. 配置文件使用 git 管理起来,并托管到 Bitbucket,方便部署;
  5. 备份使用阿里云的 OSS 存档服务,价格很便宜而且也是安心很多。

同时,在这里汇总下碰到的几个坑和心得,供参考

  1. 官方 Docker 的 php7-fpm 是没有带 gd 库的,所以要自己 build 一个版本(生产环境顺便把 debug 这些都去掉);
  2. 因为只是在最外面 Router 应用服务使用 https,所以 PHP 应用内部需要增加判断下,防止判断失败,详见这里。简单的说,就是加个判断
/**
 *  Handle SSL reverse proxy
 *  @see https://www.variantweb.net/blog/wordpress-behind-an-nginx-ssl-reverse-proxy/
 */
if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
    $_SERVER['HTTPS']='on';
}

if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
    $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
}
  1. Alpine Linux 的 apk 源有时候会不稳定,Docker build 的时候会有出错的几率,多重试就好。

--

补充下,有关 HTTPS 转发这块,khsing 提出了很好的建议,非常感谢:

刚才看了你的使用 Docker 那篇文,里面处理 WP 处理 https protocol
的方法还挺硬的,这事儿我之前在阿里云部署的适合也遇到了,不过我是在 nginx 上做了处理,这样就不用动 PHP 代码了。

map $http_x_forwarded_proto $forwarded_https { default off; https on; }
fastcgi_param HTTPS $forwarded_https;

-- eof --

自建基于 Linux 的 Time Capsule 服务

更改历史

前言

Apple 的 Time Machine 提供了非常完备的数据备份方案,但每次使用外接磁盘备份很 麻烦也很容易忘记备份。同时,个人对于 Time Capsule 「高昂的」售价(虽然它的确值那些钱)颇有微词。

其实,大部分管理员已经有数台 Linux 服务器,所以考虑能否安装类似 Time Capsule 的服务让 Linux 为 Mac 提供网络备份。

如果您和我一样有类似的需求,那么这篇文章可能就是你想要的 :^D

安装软件包

本人使用的 Linux 发行版为 Debian ,其他发行版的也应该类似。

首先,安装需要的软件包:

% sudo apt-get install netatalk
% sudo apt-get install avahi        # 通常这个包已经安装了的
% sudo apt-get install nss-mdns

注意:如果需要自己编译安装 netatalk 包,则需要加入 ssl 支持,具体看编译脚本参数。

配置

上面的软件包正常安装完毕以后,接下来就是配置了。

服务器端

1、编辑 /etc/default/netatalk 文件,找到对应的内容,更改为

ATALKD_RUN=yes
PAPD_RUN=no
CNID_METAD_RUN=yes
AFPD_RUN=yes
TIMELORD_RUN=no
A2BOOT_RUN=no

2、编辑文件 /etc/netatalk/afpd.conf 在最底部加入行:

- -tcp -noddp -uamlist uams_dhx.so,uams_dhx2.so -nosavepassword

3、编辑文件 /etc/nsswitch.conf 在最底部加入行:

hosts:  files mdns4_minimal [NOTFOUND=return] dns mdns4 mdns

4、新增文件 /etc/avahi/services/afpd.service,内容为:

<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
    <name replace-wildcards="yes">%h</name>
    <service>
        <type>_afpovertcp._tcp</type>
        <port>548</port>
    </service>
    <service>
        <type>_device-info._tcp</type>
        <port>0</port>
        <txt-record>model=Xserve</txt-record>
    </service>
</service-group>

这个时候 netatalk 协议已经配置完毕,我们要共享出个目录让 Mac 映射为磁盘。编辑文 件 /etc/netatalk/AppleVolumes.default 加入下面的行:

~/TimeMachine   "TimeMachine"   allow:mingcheng    cnidscheme:cdb options:usedots,upriv,tm

简单得说明下:

Tips:由于备份数据比较大,可以考虑 mount --bind 映射到 Linux 本地的其他合适的分区或目录( 详细 )。

至此,基本的 Linux 服务器端配置完毕,重启服务(重启需要花点时间)

% service netatalk restart
% service avahi-daemon restart

https://files.gracecode.com/2011_02_10/1297309091.png

https://files.gracecode.com/2011_02_10/1297309108.png

重启服务以后,在 Mac 端连接 Linux 服务器,输入对应的用户名和密码以后,即可挂载已经配置好的磁盘。

Mac 端

在 Mac 端,我们还需要做些配置。打开终端(Terminal),执行下面的命令使 Time Machine 能够使用网络磁盘作为备份盘:

defaults write com.apple.systempreferences TMShowUnsupportedNetworkVolumes 1

由于部分兼容性问题,还需要另外手工制作磁盘疏散镜像。打开「偏好设置」中的「共享」,可以看见「电脑名称」, 例如我的是「明城的 Macbook Pro」(注意大小写和空格),这里将其命名为 <computer_name>

https://files.gracecode.com/2011_02_10/1297309156.png

然后,打开终端粘贴如下面的命令获得本机的网卡 Mac 地址,这里将其命名为 <mac address>

ifconfig en0 | grep ether | awk '{print $2}' | sed 's/://g'

如图,例如我的是

https://files.gracecode.com/2011_02_10/1297309174.png

然后运行下面的命令,注意将上步骤获得的 <computer_name><mac address> 代入命令行:

sudo hdiutil create -size 320g -type SPARSEBUNDLE -nospotlight -volname "Backup of <computer_name>" \
    -fs "Case-sensitive Journaled HFS+" -verbose ~/Desktop/<computer_name>_<mac address>.sparsebundle

注意:-size 320g 参数是本机的硬盘容量,请根据实际情况更改。

最终在桌面会有个类似我本机的文件名(注意空格等字符):

明城的 Macbook Pro_0026bb6a1f40.sparsebundle

然后将这文件扔到上面配置好的 Linux 网络磁盘根目录。打开 TimeMachine 选择对应的磁 盘,即可以开始开始备份。

https://files.gracecode.com/2011_02_10/1297309244.png

https://files.gracecode.com/2011_02_10/1297309278.jpg

Tips:首次网络备份会比较缓慢,建议插入网线。

一般问题

问:这样做符不符合 Apple 的协议?

答:未知,如有明确结果的,请各位告知。

https://files.gracecode.com/2011_02_10/1297309298.jpg

问:为什么我选择网络磁盘以后,TimeMachine 一直在「正在准备磁盘」?

答:这是磁盘疏散镜像没有制作正确,或者你命名的文件名不正确。可以暂停备份,挂载网络磁盘看 TimeMachine 为你自己生成的文件名,然后在将上面步骤生成的文件替换。

问:TimeMachine 的备份数据是加密过的吗?

答:抱歉,保存在服务器上的数据是 没有加密 的(数据传输如有 SSL 是加密的)。

参考资源

-- EOF --

nginx_concat_module 安装和配置

简介

nginx_concat_module淘宝研发的针对 nginx 的文件合并模块 ,主要用于 合并前端代码减少 http 请求数 。如果你的应用环境中部署了 nginx,那么可以考虑尝试此模块减少请求数。

安装

安装 nginx_concat_module 需要重新编译 nginx。 可以从这里 checkout 最新的代码

svn checkout http://code.taobao.org/svn/nginx_concat_module/trunk/ $NGINX_CONCAT_MODULE

然后下载适合你自己版本的 nginx 源码包 ,在 ./configure 中增加参数

--add-module=$NGINX_CONCAT_MODULE

就可以继续 nginx 的编译安装过程。

Tips

顺便废话下,默认编译 nginx 的 gcc 参数带了 「-g」 开关。处于洁癖和性能考虑,可以考虑将其关闭。编辑文件

$NGINX_SOURCE_DIR/auto/cc/gcc

注释掉下面的行

CFLAGS="$CFLAGS -g"

如果觉得有必要,可以修改下面的编译参数(感觉性能提高不大)

NGX_GCC_OPT="-O2"

配置

新的 nginx 编译安装好以后,配置 nginx_concat_module 主要有如下的选项

# nginx_concat_module 主开关
concat on;

# 最大合并文件数
# concat_max_files 10;

# 只允许同类型文件合并
# concat_unique on;

# 允许合并的文件类型,多个以逗号分隔。如:application/x-javascript, text/css
# concat_types text/html;

(详细察看安装包下 INSTALL 和 README 文件)。其实不用那么复杂,简单的配置

location / {
     concat    on;
}

就可以合并 javascript、css 等文件了(顺便注意是否和 rewrite 规则冲突)。

使用

https://files.gracecode.com/2010_12_22/1293011346.png

上面的图可以说明如何使用 nginx_concat_module 。随着以后的深度使用, 如果感觉 url 过长, 那么就要考虑另一种优化了

ps,再罗嗦句,有关 nginx_concat_module 性能方面的忧虑,我想应该可以让人放心,尤其是看了淘宝首页的源代码以后 :^)

有关 nginx_concat_module 的任何意见和建议,可以联系其作者 Joshua Zhu <shudu[at]taobao.com>

-- EOF --

因闰秒造成的误差

项目中碰到 PHP 和数据库之间,计算存在时间计算误差。大致的情况为根据段时间字符串,例如

2012-12-14 00:00:00 UTC

使用 MySQL 的 UNIX_TIMESTAMP 函数以及 PHP 的 strtotime 计算得出的时间戳,大概有半分钟(差不多有28秒)的误差。

同时,比较‘诡异’的是直接使用当前时间(MySQL 中 UNIX_TIMESTAMP 不带参数,同时 PHP 直接使用 time 函数),却不存在误差( 测试脚本 )。

排除了 PHP 和 MySQL 之间因为时区设置造成的时间误差 -- 根据经验,如果是时区设置造成的时间误差,应该有几个小时不会那么少。

搜索解决问题期间扫了下 这篇帖子 ,觉得应该是 ‘闰秒’ 这玩意造成的问题。搜索 PHP 闰秒相关的配置似乎没有相关的, 不过在这里似乎找到了些答案

You also can experience this behavior if your system timezone
is with leap seconds. To avoid the problem in this case please
run query UPDATE mysql.time_zone SET Use_leap_seconds='N' 
and restart the server. Please inform us if this helps.

按照上述的步骤执行,解决了问题。

回过头来,我在工作机(Windows)上测试,发现并不起作用。研究了下, 原来闰秒也需要操作系统的支持

1、对于大多数新的 Linux 内核,在设计时它们都是支持闰
   秒的,这一点在 REHL4/5 的 2.6.x 内核中得到肯定。 
2、如果 Linux 系统没有配种某种时间同步机制(比如NTP),
   那么和闰秒无关,唯一导致的结果只是系统时间会比 UTC
   时间快一秒。 
3、Window Time Service 不支持闰秒,包括服务器和客户端。

回过头来考虑项目中碰到的这种情况,直接使用时间戳存储时间点会更精确些。最后, 提供下相关的测试脚本 ,看看你的环境是否也会有类似的问题。

-- EOF --

理解 Linux 的处理器负载均值(翻译)

原文链接: http://blog.scoutapp.com/articles/2009/07/31/understanding-load-averages

你可能对于 Linux 的负载均值(load averages)已有了充分的了解。负载均值在 uptime 或者 top 命令中可以看到,它们可能会显示成这个样子:

load average: 0.09, 0.05, 0.01

很多人会这样理解负载均值:三个数分别代表不同时间段的系统平均负载(一分钟、五 分钟、以及十五分钟),它们的数字当然是越小越好。数字越高,说明服务器的负载越 大,这也可能是服务器出现某种问题的信号。

而事实不完全如此,是什么因素构成了负载均值的大小,以及如何区分它们目前的状况是 「好」还是「糟糕」?什么时候应该注意哪些不正常的数值?

回答这些问题之前,首先需要了解下这些数值背后的些知识。我们先用最简单的例子说明, 一台只配备一块单核处理器的服务器。

行车过桥

一只单核的处理器可以形象得比喻成一条单车道。设想下,你现在需要收取这条道路的过桥 费 -- 忙于处理那些将要过桥的车辆。你首先当然需要了解些信息,例如车辆的载重、以及 还有多少车辆正在等待过桥。如果前面没有车辆在等待,那么你可以告诉后面的司机通过。 如果车辆众多,那么需要告知他们可能需要稍等一会。

因此,需要些特定的代号表示目前的车流情况,例如:

https://files.gracecode.com/2009_11_05/890367db9819.jpg

上面的情况和处理器的负载情况非常相似。一辆汽车的过桥时间就好比是处理器处理某线程 的实际时间。Unix 系统定义的进程运行时长为所有处理器内核的处理时间加上线程 在队列中等待的时间。

和收过桥费的管理员一样,你当然希望你的汽车(操作)不会被焦急的等待。所以,理想状态 下,都希望负载平均值小于 1.00 。当然不排除部分峰值会超过 1.00,但长此以往保持这 个状态,就说明会有问题,这时候你应该会很焦急。

「所以你说的理想负荷为 1.00 ?」

嗯,这种情况其实并不完全正确。负荷 1.00 说明系统已经没有剩余的资源了。在实际情况中 ,有经验的系统管理员都会将这条线划在 0.70:

那么多个处理器呢?我的均值是 3.00,但是系统运行正常!

哇喔,你有四个处理器的主机?那么它的负载均值在 3.00 是很正常的。

在多处理器系统中,负载均值是基于内核的数量决定的。以 100% 负载计算,1.00 表示单个处理器,而 2.00 则说明有两个双处理器,那么 4.00 就说明主机具有四个处理器。

https://files.gracecode.com/2009_11_05/556217db9819.jpg

回到我们上面有关车辆过桥的比喻。1.00 我说过是「一条单车道的道路」。那么在单车道 1.00 情况中,说明这桥梁已经被车塞满了。而在双处理器系统中,这意味着多出了一倍的 负载,也就是说还有 50% 的剩余系统资源 -- 因为还有另外条车道可以通行。

所以,单处理器已经在负载的情况下,双处理器的负载满额的情况是 2.00,它还有一倍的资源可以利用。

多核与多处理器

先脱离下主题,我们来讨论下多核心处理器与多处理器的区别。从性能的角度上理解,一台主 机拥有多核心的处理器与另台拥有同样数目的处理性能基本上可以认为是相差无几。当然实际 情况会复杂得多,不同数量的缓存、处理器的频率等因素都可能造成性能的差异。

但即便这些因素造成的实际性能稍有不同,其实系统还是以处理器的核心数量计算负载均值 。这使我们有了两个新的法则:

审视我们自己

让我们再来看看 uptime 的输出

~ $ uptime
23:05 up 14 days, 6:08, 7 users, load averages: 0.65 0.42 0.36

这是个双核处理器,从结果也说明有很多的空闲资源。实际情况是即便它的峰值会到 1.7,我也从来没有考虑过它的负载问题。

那么,怎么会有三个数字的确让人困扰。我们知道,0.65、0.42、0.36 分别说明上一分钟、最后五分钟以及最后十五分钟的系统负载均值。那么这又带来了一个问题:

其实对于这些数字我们已经谈论了很多,我认为你应该着眼于五分钟或者十五分钟的平均数 值。坦白讲,如果前一分钟的负载情况是 1.00,那么仍可以说明认定服务器情况还是正常的。 但是如果十五分钟的数值仍然保持在 1.00,那么就值得注意了(根据我的经验,这时候你应 该增加的处理器数量了)。

在 Linux 下,可以使用

cat /proc/cpuinfo

获取你系统上的每个处理器的信息。如果你只想得到数字,那么就使用下面的命令:

grep 'model name' /proc/cpuinfo | wc -l

我的照片

嗨!我叫「明城」,八零后、技术男、伪苹果粉、微软无脑黑、宁波佬,现居杭州。

除了我的博客,同时也欢迎您访问我的 GitHubTwitterInstagram 主页。

这个 Blog 原先的名字叫 Gracecode.com 、现在叫 「無標題文檔」 。 其实无所谓叫什么名字,因为我曾经为这个名字伤透了脑筋。最后想到的这个名字都没啥特别的,说到 底是因为我实在给它不了个非常酷的名字。

如果您想联系我,可以发我邮件 echo bWluZ2NoZW5nQG91dGxvb2suY29tCg== | base64 -d

注:本站点所持观点仅代表个人意见,不代表所服务公司的立场。

文章

项目

微信公众号