Browsed by
标签:code

好烂啊有点差凑合看看还不错很精彩 (No Ratings Yet)
Loading...
309 views
让大家在InfoQ上听见你的声音

让大家在InfoQ上听见你的声音

投稿

InfoQ由社区推动,这里的内容源自像你一样的专业技术人。对于社区而言,你是最重要的。

你是否热衷于软件开发?你是否热衷于与他人分享你的知识与经验?InfoQ一直在寻找优秀的作者与热情的编辑加入我们的内容贡献队伍中,跟社区里的其他成员一起,促进软件开发领域知识与创新的传播。

为InfoQ贡献内容的方式有两种,联系方式均为editors@cn.infoq.com:

深度文章投稿

深度文章不是简单的How-to。
作者需要对某个领域有十分深入的理解,
或非常丰富的实战经验。
详情见InfoQ中文站投稿须知

成为社区编辑

InfoQ社区编辑能够在自己关注的领域挖掘热点新闻和人物,并直观的将事实表述出来分享给读者。社区编辑分为翻译组、原创新闻组、专家审校组等,详见:
InfoQ编辑团队加盟指南

InfoQ编辑的核心价值观

InfoQ.com是由实践者驱动的社区媒体,我们的目标是: 推进和传播软件开发领域的知识和创新。 作为编辑兼实践者,我们参与成员驱动的编辑过程,向着这个共同目标努力前进,具体工作方式包括:翻译和撰写新闻,并以文章、采访、录制技术大会视频等多种形式分享知识。

我们恪守并践行下列核心价值观:

做信息的罗宾汉。我们的主要职能就是从少数拥有信息的精英那里寻找信息,并将其发布给广大群众。当我们发现一些很棒的信息,并且认为值得让整个社区知道时,我们应该将发布它视为我们必须承担的职责。

做最好的,而不是最快的。我们不是发布突发新闻的网站,当某件事情发生后,过上几天再发布也是可以的,只要我们收集到足够的材料,并能提供更深度的内容。

做推进者,而不是领导者。我们会编写各种内容,展现社区中的新人老将、各种活动、各种想法,以此推进社区的成长,而不是关注我们自己。作为推进者,我们与社区协作,产生有价值的内容,而不是只考虑推行我们的想法;我们能够而且应该辅助现有的各种业界活动和趋势。

提供可信赖的内容。我们的内容将会不带偏见,不会偏向个人或是厂商,除非能够明确表明属于某种“意见”。用户可以期望InfoQ的内容有所裨益,而且源于事实。我们努力坚持媒体工作的原则,并体现在我们的新闻写作活动中,同时也要认识到:我们不是全职的权威媒体工作者,而是试图做正确之事的实践者。

来源: 让大家在InfoQ上听见你的声音

好烂啊有点差凑合看看还不错很精彩 (No Ratings Yet)
Loading...
399 views
湾区日报是如何运作的

湾区日报是如何运作的

Updated April 17, 2016

这篇文章第一版是2015年5月份写的,现在看来有点“过时”了。是的,几个月的时间是能改变很多事情的。所以我决定每隔一段时间把这篇文章更新一次。


湾区日报是什么?

湾区日报是一个在旧金山工作的工程师运营的个人博客。该博客每天挑选5篇他主观认为高质量的文章,针对每篇文章拟一个中文标题写一两句简单评论,通过将近10个渠道(比如网站iOS app微博微信Twitter等)推荐给读者们。

写这篇文章的“我”就是这个工程师。湾区日报不是一个公司,也不是一个创业项目。只是我的一个 side project。从 2014年8月6日发第一期以后,运营至今。

看上去很简单,对吧?我一开始做的时候也觉得很简单,很没技术含量,任何有高中文凭具有简单电脑知识的人都能运营这种博客。但为什么同一道命题作文,每个人写的内容不一样,有人能写离题有人能写满分作文?为什么大家都会写字,有人“竟然”能成为作家并靠写字为生?

每天的内容是如何发出的?

我在每天利用零散时间发现新文章,然后直觉认为是好文章的就收藏在Pocket 里。发现新文章的渠道很多,排名不分先后:Hacker NewsMediumQuora,我订阅的很多博客的RSS,各种社交网络上看到的文章,头脑中突然对某个主题感兴趣临时搜来的文章,与同事交谈中得知的文章等。

我也利用白天的各种零散时间读一两篇文章。但一般都是晚上回家吃完晚饭后,再开始用完整的时间专心读。每天读的文章数量不一定,有时候一天读20几篇,勉强挑出5篇;有时候一天读了5篇,但都觉得很不错,就不读其他的了。这个过程一般要花1到3个钟头。

我一般用 iPad 读文章,然后多任务打开 Slack,在里面跟我的小机器人(wanqu-ops)对话,有点像程序员工作的时候敲命令行一样。我会告诉小机器人,这是一篇文章的链接,然后它会自动提取文章的标题,url的slug,图片等信息,最后插入到后台数据库;每5篇文章自动生成新的一期,自动生成当天的日期(北京时间)以及当天的期号(比如第502期)。总之,我只要把链接扔给这个小机器人,它就能帮我做这些繁琐的事情了 --一个普通网站的小编会怎么做?会用CMS,然后一项一项手动输入,这个过程不会花太多时间,可能每天十几分钟吧;但我实在太懒了,连每天花这十几分钟都不舍得。

下一步要写简评。我也是跟小机器人对话,比如 “wq post 2672 title 这是一篇好文章” ,就是告诉它:我要把编号 2672 的文章标题改成 “这是一篇好文章”。同理,可以录入文章简评等内容。下图是我在 iPad 上读文章然后用 Slack 写简评:

凑足5篇文章后,我最后给小机器人下达命令:把这期的内容发出。然后它就自动把内容更新到网站,消息推送给 iOS app 的用户,自动发布到微博TwitterFacebook等社交平台。

总之,手动操作的部分主要是读文章与写简评。剩下的繁琐的操作,都是由程序自动完成的。同一道命题作文,程序员的写法是和普通网站小编不一样的;不同程序员的写法也会不同。

背后的技术

我为湾区日报这个 side project 写了一些代码。由于只是 side project,我对它的期望不高,力求用最简单的做法,花最少的时间,用最“快糙猛”的方法实现我想要的功能。

网站与后台架构

2014年8月份,湾区日报只是处于”闹着玩”的阶段,没有严肃要做的意思。所以那个时期的湾区日报网站只是一些静态网页,用 Pelican 生成的。

之后的网站换成了 WordPress。换了几个不同的主题。甚至还花了些钱买了 Product Hunt 的主题。

到了2015年3月份的某个周末,我也不知道哪根筋接错了,就宅在家里一天,从头写了现在的这个网站。主要用 Python/Django,Celery,RabbitMQ,Postgres 以及 Redis 搭建的。

为什么用Django?为什么能在一天做一个网站?很简单,我在过去两三年自己写了大大小小10几个 Web App,都是写着玩的 side project,都是用 Django/Postgres 搭建的,只是一个套路而已。将自己以前写的代码复制粘贴,当然可以很快拼凑一个网站出来了。况且,第一版的网站远比现在大家看到的这个网站简单得多;现在这个版本的网站是经过1年多时间不断改进的成果。

所有网站基本都能简化成这个架构:Web App,Datastore,Async Worker,Task Queue,以及 Scheduler。其中,Web App就是跑网站代码接受用户的访问请求,所有耗时间的task(比如发邮件,发微博,数据统计等)都扔到Task Queue上,然后Async Worker从Task Queue抓task过来离线处理;而Scheduler就是定时跑程序,很多网站直接用的Cron。

对于湾区日报,Web App就是Django App,用uwsgi跑N个进程,用supervisord 来管理进程,前面挂一个 nginx 当 load balancer。Database用的是PostgresRedis 。其中,大部分需要永久存储的数据都在Postgres中,而Redis存的是文章的访问数与一些只需保留一两天的数据。Task Queue是用RabbitMQ。Scheduler用的是Celery Beat。而Async Worker是Celery。下图是湾区日报后台简单的架构:

湾区日报的所有这些后台的大大小小20几个进程是跑在3台 DigitalOcean 的虚拟机上(每个月花$50多)。按照访问量的增长速度,这样的架构估计至少可以支撑到2020年 — 大家整天在科技媒体上看到每天动辄几百万几千万访问量,可能都忘了世界上大部分的网站其实访问量都非常非常少的吧。当然,我在这3台虚拟机上也跑了其他的 side project,也不算浪费计算资源。我自己还有一些简单的小项目放在Bluehost上,与别人共享主机(没有root权限),就是图个便宜(每月低于$5)。

iOS App

2015年5月份的时候,用了一个周末写了 iOS App。完完全全用 Swift 写的,很不错的体验。前面说了,这只是一个 side project,所以期望不高,我是可以厚着脸皮上线质量低劣的一个周末写的 app 的,反正也没什么人用,以后慢慢改进就是了。

后台的 Api 也是 Django App(抽象出一些通用的内部 api 与网站共用),也是跑了 个 uwsgi 进程然后用 nginx 做 load balancer。

在开发第一版 App 的那个周末,除了完成基本的功能(浏览文章)外,还加入:

  • Crash report(用 Crashlytics),第一时间通知我用户的 app crash 了,方便我调试;
  • Google Anlytics,监测用户使用 app 的情况,比如多少人在线,哪个页面比较多人访问,哪个按钮比较多人点击等;
  • Appirater,提醒那些使用了几次 App 的用户去 App Store 给个好评;
  • PSUpdateApp,提醒用户有新版本了,快及时更新。

这些都只是套路而已。尽管不是 iOS 开发人员,但至少要有这么一个意识。上线一个产品,最基本的东西都要有:收集 metrics,收集 crash 的信息,更新提醒等 --开始做 app 之前有跟同事打听了一下应该用哪些工具,少走了不少弯路。详见这篇博文:两天四夜上线一个 App

发布系统

湾区日报这个博客有很多推送的渠道。现代博客与10年前的博客不同:10年前的博客就是一个网站,而现代的博客形式多样,同一份内容会以不同的形式通过不同的渠道出现在读者面前。

前面介绍到我用 Slack 与机器人对话。这机器人就是 Hubot -- 它解析我发出的命令,然后调用我在 Django App 里提供的 REST api 发布文章;当文章的状态由 pending 变成 published后,将触发一些 Celery tasks;每个 task 负责一个渠道的发布任务,比如一个task发布到微博,一个task发布到reddit等。

微博:调用微博 api 发布。凡是微博的帖子底部有 “来自 湾区日报BayArea” 字样的,都是由发布系统自动发布的。

微信:理论上,成为认证用户后,可以调用 api 自动发消息给订阅者们。但我没有成为认证用户,只能手动发布。Hubot会生成每期需要发布的文字,我只要复制粘贴就能发出消息了。对于微信,我基本是放弃了,完全不上心;因为湾区日报这种分享链接的模式很不适合在微信这种平台做。

Twitter:调用 Twitter 的 api 发布。Twitter 的 api 做得不错。

Facebook:调用 Facebook 的 Graph API 发布。

Reddit:调用 Reddit 的 api 发布的。难道有中文用户上 Reddit?我不确定。我只是把 Reddit 当作一种 SEO 的手段而已。

Google+:Google提供的api很难用,我不愿意花时间研究,于是就用 Buffer自动同步 Twitter 上发的内容。

邮件订阅:用 MailChimp 自动读取 RSS,每天定时自动发布。

iOS App 推送:没什么好说的,就是 APNS。每隔2个钟头,会有一个 Celery Beat 的 job 清理掉那些已经失效的 device token(比如有用户关掉了 push notification 或者已经把湾区日报的 app 卸载了);这就是为什么打开消息推送的用户数字有时候会变小。定期清除失效的 device token 可以避免浪费服务器计算资源白白发送无效的 push notification。

RSS:老旧的,但仍然很有用的 RSS。你会很惊讶,现在很多线上媒体不提供 RSS订阅。

为了避免同一篇文章在短时间内不小心被多次发到以上渠道,我会针对每篇文章生成一个 uuid 存到 Redis 里;每次修改文章简评的时候,会查一下这个 uuid 是否存在,如果不存在,就推送到以上渠道;反之就不推送。

很多读者注意到了,湾区日报在各个社交媒体上不断炒冷饭,重复发布几个月前发过的文章。我在 FAQ 里有详细说明原因。简单说,半年后,湾区日报的读者数量翻倍,将有一半的读者没有读过我以前推荐过的文章,“旧”的文章对他们而言是“新”的。

怎么炒冷饭呢?每天推荐新文章时,我会判断这篇文章是不是 evergreen content,半年后来看是否依然适用;如果是的话,我就把该文章扔到一个队列中(存在 Postgres 里);然后 Celery Beat 每个钟头会有一定概率(不同时段的概率不同)从队列里取出文章发到微博,Twitter,Facebook等社交媒体上,比如这条微博。队列里的这些旧文我会定期清理;有的文章真的发了好几次了,老读者们是在看腻了或者已经不再适用了(比如关于 Apple Watch即将发布的相关文章;现在 Apple Watch已经发布了,就不能再发这类文章),那就得从队列里删除。

数据统计

如果你经常使用湾区日报的 iOS app 或者网站,你就会发现我竟然公开了湾区日报的运营数字:访问量,app下载量,app打开消息推送的用户数,app的付费用户数等。下图告诉你在哪里可以找到湾区日报的各种运营数据:

湾区日报毕竟不是一个公司,我也不跟任何人合作,所以我说的算。我觉得中文的互联网上能找到运营网站的实战案例很少。一个对互联网感兴趣的人,当然希望能看到一个真实的运营案例以及真实的数据,作为一个学习材料 -- 有点像教科书上的案例分析。

这些数据分别从 App Annie 的 api,Google Analytics 的 api,以及我自己的后台数据库去抓去。Celery Beat 每小时开启一个 job 更新一下这些数据。

对于湾区日报的 iOS App,我最关心的数字是有多少用户开启了 push notification;只有开启了 push notification,用户才能及时得知当天的湾区日报的更新。每当有一个新用户开启了 push notification 或付费了,我的 Slack 就得到通知。下图是我 iWatch 上来自 Slack 的通知,告诉我此刻有一个新用户下载了 App 并且打开了 push notification:

关于 Slack 与 Hubot,详见这篇博文:湾区日报的第一个“员工”:Slack/Hubot

湾区日报分享的每篇文章都有一个访问量的统计,这个统计数字是存在 Redis 上,这比存在 Postgres 上每次访问都要写数据库的 cost 要小得多;存在 Redis 上即使失去了1小时的数据也无所谓,这个统计数字不是那么 critical。

搜索功能

网站与 iOS app 上都可以关键词搜索往期的文章。我原来想用 ElasticSearch 来做一下,但想着要多管理一个ElasticSearch就不爽,这样就多了一个 failure point,运维上可能得多花点时间,不划算。

后来受到这篇文章的启发,用一个晚上的时间直接利用 Postgres 做全文索引,并实现了网站与 app 的搜索功能,真是快糙猛的做法。

运维

我一般每星期发布一次新版本的 iOS App。每次的更新其实很有限。我每星期一般只能花不到一小时来写 app 的代码。

网站后台代码的更新主要通过 Slack。仍然是与小机器人对话:“wq deploy”。它就会 checkout 网站的 Git repo 的最新 master branch,然后重启相关进程。我用 symlink 做了版本控制,所以如果发现严重的bug,要 rollback 到前一个版本的话,只需要切换一下 symlink,几秒钟的事情。

发布代码变得轻松愉快,且充满自信,这就鼓励了开发人员(我)勇于尝试各种新奇的 idea,勇于快速迭代,快速部署小更新。所以湾区日报一直在进化。湾区日报的今天没有比昨天好多少,但这个季度肯定比上个季度改进了不少。

监控网站是否挂了,我用的是 Pingdom;如果网站挂了,我会收到短信提醒。监控服务器各种计算资源的使用情况,我用的是 Datadog(2年前去开Dockercon 的时候,在他们摊位聊了很久,才知道有这么个东西)--理论上,monitoring 与 alerting 都可以自己用开源软件搭建,但是,湾区日报只是一个 side project 而已,有现成可以凑活着用的SaaS方案,就不必花时间自己做了;而且自己做的肯定不如人家专业的。

对于网站与app后台的详细监控,我用的是Datadog。可以方便地看到不同 endpoint 在特定时间段内的请求次数以及latency。详情请见:湾区日报是如何监控系统的健康情况的

网站域名的 DNS 管理,我用 CloudFlare。使用 CloudFlare 还有其他的好处,比如它帮我挡住了不少恶意请求,帮我缓存了各种静态文件。

客服

每天都有读者来信。当然,大部分的问题都能在 FAQ 里得到解答。但也有很多来信给了我很多鼓励,知道你们从湾区日报推荐的文章里学到了东西得到了成长,我真的很高兴。

微博与微信上的读者来信,大部分都能得到关键词匹配的自动回复,算是缓解了我手动回复的压力。而花时间去写 FAQ 页面则省去了回复大部分邮件的时间。

代码管理与新功能的开发

湾区日报有3个 git repo(网站后台,iOS app,以及运维相关的脚本),都放在 Bitbucket 上,不对外公开。使用 Bitbucket 而不用 GitHub 的原因是为了省钱;如果要在 GitHub 上使用 private repo,得交钱;而 Bitbucket 我个人用的话,可以有无限数量的 private repo。

我比较倾向于 commit 小段代码,出问题了也可以比较小粒度地 revert。一般一个 commit 包含的代码量不多于 100 行。很显而易见的代码修改我直接在 master branch 上操作,然后直接 push master;比较 tricky 的代码修改我会建立一个新的 branch,然后给自己发 pull request,自己 review 一遍自己写的代码。

我经常上线没有写完的代码,然后 wrap 在 feature switch 里面。我这种小破 project 大部分的方案都是土办法,不用太学术派不用太杀鸡用牛刀,意思一下就行了。所以一个 feature switch 其实就是 Postgres 里的一个表格里的一行。湾区日报99.999%的workload是 read-only 的,所以网站上很多页面其实都是缓存在内存然后走CDN的,数据库访问不会太 crazy。

顺便提一下,有一些年轻的读者(学生或者刚工作不久的年轻人)发邮件过来逼我开源湾区日报的代码,让我有点哭笑不得。联想到一有什么自然灾害,名人们就要被逼着捐款。详见 FAQ 第18条

开发环境

我用家里的 iMac 写代码。Mac OS X 下运行虚拟机 Vagrant + VirtualBox。虚拟机里跑的是 Ubuntu,与 production 里用的操作系统一样。然后通过 Vagrant 的 synced folders 在 Mac OS X 与虚拟机之间共享代码的文件夹。在 Mac OS X 上用 PyCharm 写代码,利用 PyCharm 里的 Vagrant 的支持,在虚拟机里跑服务器。

数据备份

有一个每天自动执行一次的 job 把所有数据 dump 出来,压缩一下,按日期命名,最后上传到某个地方。上传到哪里呢?任何提供API的云存储服务都行(Dropbox、Box之类的)。

对于 PostgreSQL 里的数据,我用 Django 的 dumpdata 命令把所有数据 dump 成一个 json file,然后 gzip 一下。

对于 Redis 里的数据,直接 gzip 一下 disk 上的 dump.rdb

详情见这篇博文:湾区日报是如何备份数据库的?

总结

如果把这篇文章给2014年8月6日的我看,我肯定不会做湾区日报这个 side project 了,太花时间了 -- 竟然要做网站,要做发布系统,要学 Swift 然后写 iOS app,还要每周发布 app 新版本,还要管理好几个发布渠道,还要做客服回邮件,还要每天花1到3个钟头读文章写简评。

幸亏写这篇文章的时候,大部分困难的工作已经完成了。这就是互联网时代的产品迭代,是一个循序渐进的过程,是个人与产品共同成长的过程。你不能期望一夜成功 -- 其实,你也可以一夜成功,只是这一夜发生在第1000天甚至第3600天。

运营湾区日报是没什么经济上的回报的,尽管有一些广告收入与app内购的收入,但与投入的时间(再乘以一个哪怕是实习生的时薪)相比,相当微不足道。之所以我还能继续做下去,是看中知识的积累与个人的成长。这些运营经验以及从每天5篇文章里学到的东西,是完全可以运用到我其他的项目上的。就算最后真的什么都没做成,也是一段美好的回忆。临死的时候,回顾一生,至少我还能说,我做过一个叫湾区日报的博客,每天有那么几万个读者(我也是读者之一),我们每天都在进步。这就够了。

from:

http://www.wanqu.co/blog?s=top

-end-

好烂啊有点差凑合看看还不错很精彩 (No Ratings Yet)
Loading...
380 views
good coders code, great reuse

good coders code, great reuse

good coders code, great reuse.
good coders code, great reuse

Einstein argued that there must be simplified explanations of nature, because God is not capricious or arbitrary. No such faith comforts the software engineer.

Fred Brooks, Jr.

跳至工具栏