Pensieve: 1845
2018-11-11 21:51
所观所读
手机上在重读全职高手, 目前进度30%. 肥皂剧小说, 填时间而已. 影视剧没怎么看, 倒是上班时又在听House of Cards的录音.
买了一个McEwan的Solar, 有时间慢慢看. 另外买了一本园艺书, 希望能帮助到前院的花花草草.
所玩
Diablo 3 目前PL过600, 大秘境78层, 赛季野蛮人排进前200名, 不过这个榜应该是为所有Switch玩家而设的, 所以成绩并不怎么样.
photoprism相关
我想在树莓派上跑photoprism. 我一开始看的是它的Dockerfile, 里面依赖了darktable, 所以一开始在darktable上花了好多时间. darktable没有arm版, 之前有篇博客宣称将要支持arm, 后面也不了了之了. 我尝试了一下编译, 放弃了.
既然photoprism跑不了, 只能找找替代品, 找了一圈, 实在没看到合适的. 又回头来看photoprism, 想知道它对darktable的依赖有多大, 结果发现darktable只是用来做RAW对JPEG的格式转换, 而且调用的时候会忽略所有错误. 那么我就完全可以不将darktable放进容器了, 直接在photoprism的配置里面将darktable的cli设置成/bin/false
就好了.
于是继续回头搞photoprism到树莓派的适配. 主要障碍是photoprism用了tensorflow的C binding(libtensorflow.so
和libtensorflow_framework.so
), 为此, 要编译tensorflow, 了解了下后发现, 要先编译bazel.
于是吐槽下bazel, 我之前还因为这货的口号{Fast, Correct} - Choose two
而关注过它. 这次编译这货, 坑是一个接一个:
- 在raspberry上编译bazel的资料不够多. 找到了这份文档成功编译出了一个旧版的bazel, 想着一个编译工具无论怎么样不会对上层的Tensorflow的编译造成太大影响. 根据经验, 我见过不少编译器版本影响代码编译结果的案例, 但是我真没见过make的版本能够影响make行为的案例. 当然, 我今天就见识到了. 编译器跑了好久后报了错, 一查, Tensorflow的作者们建议升级bazel解决. 于是我手贱搜素了下, 我也知道这个结果不代表什么东西: 截止到现在, Tensorflow里历史上所有的issue一共有14420个, 里面有bazel这个关键字的一共有6855个.
- 好嘛, 要新版, 又没文档, 于是我开始尝试官方文档, 官方没保证能在树莓派上编译成功, 事实上, 按照默认的配置, 也的确没编译成功. 因为按照默认配置编译时, 会报
java.lang.OutOfMemoryError
错误. 是, 我知道, 树莓派内存只有1G, 不够. 解决方案是用下面的命令来跑bazel里的compile.sh
:env BAZEL_JAVAC_OPTS="-J-Xms512m -J-Xmx768m" bash ./compile.sh
- 我是在Docker里面编译bazel的, 随手将压缩包解压到了/tmp, 事实上这也造成了一个异常, 因为bazel貌似会为依赖创建软链接, 而这会造成无限软链接的情况. 继续叹气.
目前进度是bazel已经编完可用, 开始折腾Tensorflow的编译, 这货在树莓派上编译一次要大半天, 叹气.
piwheels
折腾安装photoprism的时候, 我看到了piwheels这个项目, 这个项目为树莓派预编译了相当多的Python包. 这样pip安装二进制包时, 可以直接解压安装二进制而不需要编译了. raspbian里面已经默认应用了这个配置, 看了看作者的相关博客, 也真是心大, 直接在机器上跑陌生项目的setup.py…
顺便提一句, 这个服务默认在raspbian这个发行版上应用了:
pi@raspberrypi:~ $ cat /etc/pip.conf
[global]
extra-index-url=https://www.piwheels.org/simple
所以你在raspbian上用pip或pip3安装二进制包时, 不会有编译发生.
故障一例
上周, 我们组里的一个服务故障了, 影响了外部的用户登陆. 这边简单介绍下故障的原因, 并给一些个人的评论.
我们负责的是一个登陆系统, 每次有用户登陆时, 会去请求后台的另一个API服务, 校验这个请求是否合法. 由于涉及到玩家登陆这种核心要素, 我们的这个服务做了各种高可用处理, 应该说, 有一定的自愈能力.
上周面临运营高峰时, 后台的API服务挂了. 大量请求到我们组的这个服务来时, 我们的服务到后台的请求都超时了. 这意外着我们能处理的并发大大下降了. 同时, 由于大量请求无法处理, 我们内部的健康检测请求也没法正常处理完成了. 鉴于健康检测无法正常返回, 负载均衡器认为计算实例已经不健康, 于是逐一终止了实例们.
约二十分钟后, 后台的API服务恢复了. 但是我们的服务仍迟迟不能恢复, 原因是每次有实例起来接受请求时, 会有大量的流量冲击这台机器, 导致负载异常, 健康检测再次失败, 实例再次被终止. 最后, 我的同事们将负载均衡器上的健康检测类型由HTTP改为EC2健康检测, 这样服务才逐渐恢复.
我希望我已经将这个故障的大致情况介绍清楚了. 下面来说下我的几个看法:
*. 我们不应该做深度健康检测, 即服务不应该在被问询自己是否健康时请求其他接口, 再给出结论. 健康检测只应考虑自己是否健康, 不要考虑自己的依赖关系, 即使是强依赖关系, 是否健康. 这一点, 我们没做错. *. 在条件允许的情况下, 我们应将健康检测和主要业务逻辑解耦, 并尽力减少健康检测的复杂度, 保证即使面临大量负载, 健康检测也能正常完成. 事实上, 这一点我们已经有了一个方案, 即将健康检测的逻辑提取出来成为另一个独立的服务, 在另一个端口服务. 只可惜这个方案由于时间关系, 尚未上线. *. 我们这个服务故障的直接原因是大量请求因超时而挤占了系统资源. 对于这种情况, 我们应该在后台故障的时候直接在负载均衡器上直接返回503. 这样能有效保护后端服务器. 我们之前没有这样的设计, 经过内部讨论, 我们现在有了一个方案, 即当后端API检测有问题时, 通知一个lambda, 直接修改负载均衡器的设置, 将所有的请求传到默认的null节点, 从而给请求源返回503. 当故障恢复时, 运行类似的逻辑, 把正常的后端切回来, 提供服务. *. 对于可以预见的流量高峰, 除了提前预热负载均衡器外, 将均衡器上的健康检测类型改为EC2也是合情合理的.