我的2017

谈笑风生又一年

过去一年也没有什么别的,大概下面几件事

  1. 抽中了美帝的工作签证,纯粹历史的进程,和自我奋斗没什么关系
  2. 在公司搞了两个稍大的项目,忽悠公司涨了工资,公司自己多给了我一堆股票,没上市,没价值
  3. 小公司穷得很,从没有年终奖,自己买买基金股票给自己发了一个月的税前工资当奖金了
  4. 在 Coursera 上拿了两个证书,一个关于算法的,一个关于数据科学入门的,现在在上一门前端的课,还有一周结课,看来在今年是拿不到了
  5. 通过康奈尔的课程入门了 OCaml 这门语言,通过它学习了从一些新的角度来看待问题,还没写过什么实战类的代码。它的静态强类型我很喜欢,希望在新的一年里能用一个项目来练习
  6. 应经理建议开坑 Clojure ,语言很强大,现成的函数很多,唯一的缺点大概就是括号太多( Lisp 系的通病)。不过也算是在公司的代码库里写了几行,同样需要多练习,功能强大了意味着要熟练掌握的难度就更大( Python 也是这样,用了四年多还是不敢自称“精通”)
  7. 不知怎么的,我一个搬砖码农突然就觉得给别人打工纯粹是浪费时间,于是在圣诞假期简单开了一个 side project ,正在学习的前端算是有了用武之地
  8. 据豆瓣统计,过去一年看了24本书,70部影视作品(包含电影,动漫等)

很惭愧,就做了一点微小的工作,谢谢大家。

DynamoDB 中遇到的“坑”

DynamoDB 的优势无需赘言,在亚麻的 paperAWS 的技术文档中已经讲了无数遍,大量的工业实践经验也证明了 DynamoDB 确实是一款非常优秀的数据库。所以这篇文章的重点放在了个人使用 DynamoDB 的过程中遇到的坑。其实严格来讲很多不应该算“坑”,只是因为之前没有接触过,所以用起来多少感到些许不适应,简单起见,也归为了“坑”的一类。在使用中,我的环境是 Python 2.7.14 ,连接数据库的 driver 使用的是 boto3 。

  1. DynamoDB 不支持 Python 中的 tuple 类型,需要将其转换为 list 再进行写入。这样做可以理解,虽然在 Python 中两种数据结构不同,但在存储的角度来看并无区别,的确没有必要实现两种同样的数据类型。
  2. DynamoDB 不支持空字符串,但是支持 None ,因此实际生产中要么把空字符串的域(列)删掉,要么用 None 来代替空字符串,要么用某个特殊字符来代替空字符串。推荐第一种方式。DynamoDB 作为一种 NoSQL 数据库,本身对每条数据的格式不作要求,所以如果某个域(列)为空的话,简单舍弃即可,若采用替换的方式,可能会出现意想不到的问题,比如说可能混淆的替换的 None 和原本值为 None 的域。
  3. 很难对 DynamoDB 中的查询进行计数。DynamoDB 没有提供现成的计数操作,所以统计符合某个查询的结果数无异于全表扫描,这在时间上是无法忍受的(数据量很小的情况除外)。
  4. 批量读写受限。文档中写道,读操作一次可以处理最多100条请求,返回最多 16 MB 的数据;写操作一次可以处理最多25条请求,写入最多 16 MB 的数据,同时每条数据的大小不得超过 400 KB。不过也不好说这就是个坑,因为目前已知的只有 DynamoDB 的文档把这个限制明确告诉我们了,之前看其他数据库的文档并没有发现类似的说明,也有可能是我看的不仔细吧。
  5. 奇怪的 json 格式。DynamoDB 的数据结构采用的他们独家定义的一种 json 结构,具体。。不太好说明,总之和 Python 由 json.dumps 一个字典生成的不一样,还是直接查看文档好了。这种 json 格式导致其难以与整个系统中其他部分兼容,好在发现了一个叫做 dynamodb-json 的库,可以将 dynamodb json 转换为平时常见的 json。不过这个库本身也有问题,它无法正确的转换负浮点数,我已经帮它打了补丁,希望能包含在下一次版本发布中。
  6. 将 Python 浮点数写入 DynamoDB 前需要转换为 decimal.Decimal 类型,如
    >>> import decimal
    >>> decimal.Decimal('123.123')
    Decimal('123.123')

    这个锅主要是因为浮点数无法精确地用二进制表示,而 DynamoDB 要求浮点数精确表示。

以上是目前我的一些使用经验,可能还有其他各种不适应的地方有待去发现。虽然 DynamoDB 对初次接触它的人来说有很多看起来“奇怪”的地方,但用习惯了并没有太多的槽点,并且对我而言,还有它最大的优势——运维方便,不需要人工去维护一个数据库集群包含多少机器,它会自动的根据数据量扩展;也不需要我们自己去写一个复杂的配置文件及一个日志系统去监控它的运行,一切都可以通过 AWS 控制台中点鼠标实现,在生产环境中,可以称为理想。

如何用 Python Flask 和 ngrok 快速搭建一个可用的 web 服务

昨天公司为了让全体工程师测试即将发布的开发者平台,组织了一次 Hackathon ,平台主要支持移动开发(iOS 和安卓),我没多大兴趣,但也支持集成自己的 API endpoint ,通过摸索,用了不到半个小时的时间用 Python Flask 框架和 ngrok 在服务器上搭了一个简单的 web 服务,支持 https(这个功能当然是 ngrok 提供的),GET/POST 请求。今天趁着卧病在床,简单整理一下昨天做了些啥,以备后用。

简单步骤如下
1. 在 DigitalOcean 上开一个最便宜的服务器,这个每人喜好不同,但关键是便宜,毕竟只是一个 Hackathon
2. 把 Flask 首页 上的代码抄到服务器上,以如下方法将 Flask 进程运行在后台

export FLASK_APP=hello.py
export FLASK_DEBUG=1
nohup flask run &

运行在后台是为了使 web 服务不会因为 ssh 断开而中断,开 debug 模式是保证每次对代码的修改都能及时更新。
3. Flask 服务默认绑定 5000 端口,运行 ngrok

./ngrok http 5000 > /dev/null &

这样就能保证 ngrok 运行在后台,同时分配的 url 不会因为多次启动而随机变化。然后查看 localhost:4040/status 获得 ngrok 自动分配的 url 。

这样一个简单的 web 服务就搭好了。

如何给 DigitalOcean 一键安装的 WordPress 加 https

Https 的重要性不言而喻,开了博客之后就寻思着怎样去弄一个证书,后来发现了方便易用的 Let’s Encrypt 。限于我还是建站新手,从发现这个工具到弄明白怎么用再到真正把网站挂上 Https 还是费了一番功夫的,为了表示我还要学习一个,随便记录一下过程。

  1. 为避免以后 DigitalOcean 可能的更新,导致版本不符令人迷惑,截图说明我安装的 WordPress 是如下这个版本
  2. 该版本的 WordPress 运行在 Apache 上,在 Let’s Encrypt 的 Getting Started 链接中提到,在 shell 中可以用一个叫 Certbot 的工具来获得证书,选项如下图所示
  3. 把网页上自动生成的脚本抄一遍就好了

因为这样生成的证书只有90天的有效期,所以 Certbot 建议设置一个定时任务来自动更新。

将博客转移到了WordPress

在天愿作比翼鸟,人生经验还太少

搬砖两年,之前的博客也荒了两年,接触的东西一多,就想着还是得有个地方写点啥,记录一下有用的人生经验,防止以后掉到同一个坑里去。

之前那个博客是用hexo建在GitHub Pages上的,hexo差不多已经几乎忘记怎么用,GitHub Pages也不太愿意继续折腾,虽然免费,但总觉得还是用个现成的,久经考验的博客框架来得稳妥,并且我也不是Node.js党,再次花时间精力去把hexo搞明白也并无太大裨益,虽然我挺感兴趣。博客网站考察了一些,但总感觉是寄人篱下,如果用国内的服务搞不好还要去猜测屏蔽关键字是哪些,毕竟微博的“JavaScript事件”相去不远。上个周六的时候用wordpress.com搭建了一个,也买了一年的个人套餐,因为我有个独立域名,但好像wordpress.com对个人域名的https支持不是很稳定,导致Chrome时不时报告证书无效,同时如果不是企业版的话各种插件也装不了,无奈只好退款。最后还是跑到DigitalOcean上搞了个WordPress一键安装,所有的事都能省了,掏钱就行,好在很便宜。

大概就是这个样子。