` 内部的 `
` 元素内部的 `` 元素。
+
+```
+$('div.accepted-answer pre code').text()
+> "print("Hello World!")"
+```
+
+`text` 函数提取并连接原本将由上一个查询返回的元素列表中的所有文本。这也从代码中去除了用来使语法高亮的元素。
+
+### 介绍 Cheerio
+
+我们的下一步涉及使用我们创建好的查询结合 [Cheerio][29](一个服务器端实现的 jQuery)来实现扒页面的功能。
+
+#### 安装 Cheerio
+
+打开你的命令行工具,切换到你的软件包的根目录并执行:
+
+```
+npm install --save cheerio@0.20.0
+apm install
+```
+
+#### 实现扒页面的功能
+
+在 `lib/sourcefetch.js` 为 `cheerio` 添加一条引用语句:
+
+```
+import { CompositeDisposable } from 'atom'
+import request from 'request'
+import cheerio from 'cheerio'
+```
+
+现在创建一个新函数 `scrape`,它用来提取 StackOverflow HTML 里面的代码片段:
+
+```
+fetch() {
+ ...
+},
+
+scrape(html) {
+ $ = cheerio.load(html)
+ return $('div.accepted-answer pre code').text()
+},
+
+download(url) {
+ ...
+}
+```
+
+最后,让我们更改 `fetch` 函数以传递下载好的 HTML 给 `scrape` 而不是将其插入到编辑器:
+
+```
+fetch() {
+ let editor
+ let self = this
+
+ if (editor = atom.workspace.getActiveTextEditor()) {
+ let selection = editor.getSelectedText()
+ this.download(selection).then((html) => {
+ let answer = self.scrape(html)
+ if (answer === '') {
+ atom.notifications.addWarning('No answer found :(')
+ } else {
+ editor.insertText(answer)
+ }
+ }).catch((error) => {
+ console.log(error)
+ atom.notifications.addWarning(error.reason)
+ })
+ }
+},
+```
+
+我们扒取页面的功能仅仅用两行代码就实现了,因为 cheerio 已经替我们做好了所有的工作!我们通过调用 `load` 方法加载 HTML 字符串来创建一个 `$` 函数,然后用这个函数来执行 jQuery 语句并返回结果。你可以在官方 [开发者文档][30] 查看完整的 `Cheerio API`。
+
+### 测试更新后的软件包
+
+重新加载 Atom 并在一个选中的 StackOverflow URL 上运行 `soucefetch:fetch` 以查看到目前为止的进度。
+
+如果我们在一个有采纳答案的页面上运行这条命令,代码片段将会被插入到编辑器中:
+
+
+
+如果我们在一个没有采纳答案的页面上运行这条命令,将会弹出一个警告通知:
+
+
+
+我们最新的 `fetch` 函数给我们提供了一个 StackOverflow 页面的代码片段而不再是整个 HTML 内容。要注意我们更新的 `fetch` 函数会检查有没有答案并显示通知以提醒用户。
+
+在 [sourcefetch 教程仓库][11] 查看这一步所有的代码更改。
+
+### 实现用来查找相关的 StackOverflow URL 的谷歌搜索功能
+
+现在我们已经将 StackOverflow 的 URL 转化为代码片段了,让我们来实现最后一个函数——`search`,它应该要返回一个相关的 URL 并附加一些像“hello world”或者“快速排序”这样的描述。我们会通过一个非官方的 `google` npm 模块来使用谷歌搜索功能,这样可以让我们以编程的方式来搜索。
+
+#### 安装这个 Google npm 模块
+
+通过在软件包的根目录打开命令行工具并执行命令来安装 `google` 模块:
+
+```
+npm install --save google@2.0.0
+apm install
+```
+
+#### 引入并配置模块
+
+在 `lib/sourcefetch.js` 的顶部为 `google` 模块添加一条引用语句:
+
+```
+import google from "google"
+```
+
+我们将配置一下 `google` 以限制搜索期间返回的结果数。将下面这行代码添加到引用语句下面以限制搜索返回最热门的那个结果。
+
+```
+google.resultsPerPage = 1
+```
+
+#### 实现 search 函数
+
+接下来让我们来实现我们的 `search` 函数:
+
+```
+fetch() {
+ ...
+},
+
+search(query, language) {
+ return new Promise((resolve, reject) => {
+ let searchString = `${query} in ${language} site:stackoverflow.com`
+
+ google(searchString, (err, res) => {
+ if (err) {
+ reject({
+ reason: 'A search error has occured :('
+ })
+ } else if (res.links.length === 0) {
+ reject({
+ reason: 'No results found :('
+ })
+ } else {
+ resolve(res.links[0].href)
+ }
+ })
+ })
+},
+
+scrape() {
+ ...
+}
+```
+
+以上代码通过谷歌来搜索一个和指定的关键词以及编程语言相关的 StackOverflow 页面,并返回一个最热门的 URL。让我们看看这是怎样来实现的:
+
+```
+let searchString = `${query} in ${language} site:stackoverflow.com`
+```
+
+我们使用用户输入的查询和当前所选的语言来构造搜索字符串。比方说,当用户在写 Python 的时候输入“hello world”,查询语句就会变成 `hello world in python site:stackoverflow.com`。字符串的最后一部分是谷歌搜索提供的一个过滤器,它让我们可以将搜索结果的来源限制为 StackOverflow。
+
+```
+google(searchString, (err, res) => {
+ if (err) {
+ reject({
+ reason: 'A search error has occured :('
+ })
+ } else if (res.links.length === 0) {
+ reject({
+ reason: 'No results found :('
+ })
+ } else {
+ resolve(res.links[0].href)
+ }
+})
+```
+
+我们将 `google` 方法放在一个 `Promise` 里面,这样我们可以异步地返回我们的 URL。我们会传递由 `google` 返回的所有错误并且会在没有可用的搜索结果的时候返回一个错误。否则我们将通过 `resolve` 来解析最热门结果的 URL。
+
+### 更新 fetch 来使用 search
+
+我们的最后一步是更新 `fetch` 函数来使用 `search` 函数:
+
+```
+fetch() {
+ let editor
+ let self = this
+
+ if (editor = atom.workspace.getActiveTextEditor()) {
+ let query = editor.getSelectedText()
+ let language = editor.getGrammar().name
+
+ self.search(query, language).then((url) => {
+ atom.notifications.addSuccess('Found google results!')
+ return self.download(url)
+ }).then((html) => {
+ let answer = self.scrape(html)
+ if (answer === '') {
+ atom.notifications.addWarning('No answer found :(')
+ } else {
+ atom.notifications.addSuccess('Found snippet!')
+ editor.insertText(answer)
+ }
+ }).catch((error) => {
+ atom.notifications.addWarning(error.reason)
+ })
+ }
+}
+```
+
+让我们看看发生了什么变化:
+
+- 我们选中的文本现在变成了用户输入的 `query`
+- 我们使用 [TextEditor API][21] 来获取当前编辑器选项卡使用的 `language`
+- 我们调用 `search` 方法来获取一个 URL,然后通过在得到的 Promise 上调用 `then` 方法来访问这个 URL
+
+我们不在 `download` 返回的 Promise 上调用 `then` 方法,而是在前面 `search` 方法本身链式调用的另一个 `then` 方法返回的 Promise 上面接着调用 `then` 方法。这样可以帮助我们避免[回调地狱][31]
+
+在 [sourcefetch 教程仓库][12] 查看这一步所有的代码更改。
+
+### 测试最终的插件
+
+大功告成了!重新加载 Atom,对一个“问题描述”运行软件包的命令来看看我们最终的插件是否工作,不要忘了在编辑器右下角选择一种语言。
+
+
+
+### 下一步
+
+现在你知道怎么去 “hack” Atom 的基本原理了,通过 [分叉 sourcefetch 这个仓库并添加你的特性][13] 来随心所欲地实践你所学到的知识。
+
+--------------------------------------------------------------------------------
+
+via: https://github.com/blog/2231-building-your-first-atom-plugin
+
+作者:[NickTikhonov][a]
+译者:[OneNewLife](https://github.com/OneNewLife)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://github.com/NickTikhonov
+[1]: https://education.github.com/experts
+[2]: https://github.com/NickTikhonov/sourcerer
+[3]: https://github.com/NickTikhonov/sourcefetch-guide
+[4]: https://github.com/NickTikhonov/sourcefetch-tutorial/commit/89e174ab6ec6e270938338b34905f75bb74dbede
+[5]: https://atom.io/docs/api/latest/TextEditor
+[6]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String
+[7]: https://github.com/NickTikhonov/sourcefetch-tutorial/commit/aa3ec5585b0aa049393351a30be14590df09c29a
+[8]: https://www.wikipedia.com/en/Document_Object_Model
+[9]: https://github.com/NickTikhonov/sourcefetch-tutorial/commit/85992043e57c802ca71ff6e8a4f9c477fbfd13db
+[10]: https://github.com/NickTikhonov/sourcefetch-tutorial/commit/896d160dca711f4a53ff5b182018b39cf78d2774
+[11]: https://github.com/NickTikhonov/sourcefetch-tutorial/commit/039a1e1e976d029f7d6b061b4c0dac3eb4a3b5d2
+[12]: https://github.com/NickTikhonov/sourcefetch-tutorial/commit/aa9d0b5fc4811a70292869730e0f60ddf0bcf2aa
+[13]: https://github.com/NickTikhonov/sourcefetch-tutorial
+[14]: https://developers.google.com/web/fundamentals/getting-started/primers/promises
+[15]: https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol
+[16]: https://atom.io/
+[17]: https://en.wikipedia.org/wiki/%3F:
+[18]: https://atom.io/docs/api/v1.9.4/Panel
+[19]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
+[20]: https://en.wikipedia.org/wiki/Event-driven_programming
+[21]: https://atom.io/docs/api/v1.11.1/TextEditor
+[22]: https://www.npmjs.com/
+[23]: http://recurial.com/programming/understanding-callback-functions-in-javascript/
+[24]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
+[25]: https://atom.io/docs/api/v1.11.1/NotificationManager
+[26]: https://www.google.com/chrome/
+[27]: http://stackoverflow.com/questions/1077347/hello-world-in-python
+[28]: http://stackoverflow.com/questions/3463426/in-c-how-should-i-read-a-text-file-and-print-all-strings
+[29]: https://www.npmjs.com/package/cheerio
+[30]: https://github.com/cheeriojs/cheerio
+[31]: http://callbackhell.com/
diff --git a/published/201610/20160823 The infrastructure behind Twitter - efficiency and optimization.md b/published/201610/20160823 The infrastructure behind Twitter - efficiency and optimization.md
new file mode 100644
index 0000000000..f47d262379
--- /dev/null
+++ b/published/201610/20160823 The infrastructure behind Twitter - efficiency and optimization.md
@@ -0,0 +1,122 @@
+揭秘 Twitter 背后的基础设施:效率与优化篇
+===========
+
+过去我们曾经发布过一些关于 [Finagle](https://twitter.github.io/finagle/) 、[Manhattan](https://blog.twitter.com/2014/manhattan-our-real-time-multi-tenant-distributed-database-for-twitter-scale) 这些项目的文章,还写过一些针对大型事件活动的[架构优化](https://blog.twitter.com/2013/new-tweets-per-second-record-and-how)的文章,例如天空之城、超级碗、2014 世界杯、全球新年夜庆祝活动等。在这篇基础设施系列文章中,我主要聚焦于 Twitter 的一些关键设施和组件。我也会写一些我们在系统的扩展性、可靠性、效率方面的做过的改进,例如我们基础设施的历史,遇到过的挑战,学到的教训,做过的升级,以及我们现在前进的方向等等。
+
+> 天空之城:2013 年 8 月 2 日,宫崎骏的《天空之城(Castle in the Sky)》在 NTV 迎来其第 14 次电视重播,剧情发展到高潮之时,Twitter 的 TPS(Tweets Per Second)也被推上了新的高度——143,199 TPS,是平均值的 25 倍,这个记录保持至今。-- LCTT 译注
+
+### 数据中心的效率优化
+
+#### 历史
+
+当前 Twitter 硬件和数据中心的规模已经超过大多数公司。但达到这样的规模不是一蹴而就的,系统是随着软硬件的升级优化一步步成熟起来的,过程中我们也曾经犯过很多错误。
+
+有个一时期我们的系统故障不断。软件问题、硬件问题,甚至底层设备问题不断爆发,常常导致系统运营中断。出现故障的地方存在于各个方面,必须综合考虑才能确定其风险和受到影响的服务。随着 Twitter 在客户、服务、媒体上的影响力不断扩大,构建一个高效、可靠的系统来提供服务成为我们的战略诉求。
+
+> Twitter系统故障的界面被称为失败鲸(Fail Whale),如下图 -- LCTT 译注
+> 
+
+#### 挑战
+
+一开始,我们的软件是直接安装在服务器,这意味着软件可靠性依赖硬件,电源、网络以及其他的环境因素都是威胁。这种情况下,如果要增加容错能力,就需要统筹考虑这些互不关联的物理设备因素及在上面运行的服务。
+
+最早采购数据中心方案的时候,我们都还是菜鸟,对于站点选择、运营和设计都非常不专业。我们先直接托管主机,业务增长后我们改用租赁机房。早期遇到的问题主要是因为设备故障、数据中心设计问题、维护问题以及人为操作失误。我们也在持续迭代我们的硬件设计,从而增强硬件和数据中心的容错性。
+
+服务中断的原因有很多,其中硬件故障常发生在服务器、机架交换机、核心交换机这地方。举一个我们曾经犯过的错误,硬件团队最初在设计服务器的时候,认为双路电源对减少供电问题的意义不大 -- 他们真的就移除了一块电源。然而数据中心一般给机架提供两路供电来提高冗余性,防止电网故障传导到服务器,而这需要两块电源。最终我们不得不在机架上增加了一个 ATS 单元(AC transfer switch 交流切换开关)来接入第二路供电。
+
+提高系统的可靠性靠的就是这样的改进,给网络、供电甚至机房增加冗余,从而将影响控制到最小范围。
+
+#### 我们学到的教训以及技术的升级、迁移和选型
+
+我们学到的第一个教训就是要先建模,将可能出故障的地方(例如建筑的供电和冷却系统、硬件、光纤网络等)和运行在上面的服务之间的依赖关系弄清楚,这样才能更好地分析,从而优化设计提升容错能力。
+
+我们增加了更多的数据中心提升地理容灾能力,减少自然灾害的影响。而且这种站点隔离也降低了软件的风险,减少了例如软件部署升级和系统故障的风险。这种多活的数据中心架构提供了代码灰度发布(staged code deployment)的能力,减少代码首次上线时候的影响。
+
+我们设计新硬件使之能够在更高温度下正常运行,数据中心的能源效率因此有所提升。
+
+#### 下一步工作
+
+随着公司的战略发展和运营增长,我们在不影响我们的最终用户的前提下,持续不断改进我们的数据中心。下一步工作主要是在当前能耗和硬件的基础上,通过维护和优化来提升效率。
+
+### 硬件的效率优化
+
+#### 历史和挑战
+
+我们的硬件工程师团队刚成立的时候只能测试市面上现有硬件,而现在我们能自己定制硬件以节省成本并提升效率。
+
+Twitter 是一个很大的公司,它对硬件的要求对任何团队来说都是一个不小的挑战。为了满足整个公司的需求,我们的首要工作是能检测并保证购买的硬件的品质。团队重点关注的是性能和可靠性这两部分。对于硬件我们会做系统性的测试来保证其性能可预测,保证尽量不引入新的问题。
+
+随着我们一些关键组件的负荷越来越大(如 Mesos、Hadoop、Manhattan、MySQL 等),市面上的产品已经无法满足我们的需求。同时供应商提供的一些高级服务器功能,例如 Raid 管理或者电源热切换等,可靠性提升很小,反而会拖累系统性能而且价格高昂,例如一些 Raid 控制器价格高达系统总报价的三分之一,还拖累了 SSD 的性能。
+
+那时,我们也是 MySQL 数据库的一个大型用户。SAS(Serial Attached SCSI,串行连接 SCSI )设备的供应和性能都有很大的问题。我们大量使用 1U 规格的服务器,它的磁盘和回写缓存一起也只能支撑每秒 2000 次的顺序 IO。为了获得更好的效果,我们只得不断增加 CPU 核心数并加强磁盘能力。我们那时候找不到更节省成本的方案。
+
+后来随着我们对硬件需求越来越大,我们可以成立了一个硬件团队,从而自己来设计更便宜更高效的硬件。
+
+#### 关键技术变更与选择
+
+我们不断的优化硬件相关的技术,下面是我们采用的新技术和自研平台的时间轴。
+
+- 2012 - 采用 SSD 作为我们 MySQL 和 Key-Value 数据库的主要存储。
+- 2013 - 我们开发了第一个定制版 Hadoop 工作站,它现在是我们主要的大容量存储方案。
+- 2013 - 我们定制的解决方案应用在 Mesos、TFE( Twitter Front-End )以及缓存设备上。
+- 2014 - 我们定制的 SSD Key-Value 服务器完成开发。
+- 2015 - 我们定制的数据库解决方案完成开发。
+- 2016 - 我们开发了一个 GPU 系统来做模糊推理和训练机器学习。
+
+#### 学到的教训
+
+硬件团队的工作本质是通过做取舍来优化 TCO(总体拥有成本),最终达到达到降低 CAPEX(资本支出)和 OPEX(运营支出)的目的。概括来说,服务器降成本就是:
+
+1. 删除无用的功能和组件
+2. 提升利用率
+
+Twitter 的设备总体来说有这四大类:存储设备、计算设备、数据库和 GPU 。 Twitter 对每一类都定义了详细的需求,让硬件工程师更针对性地设计产品,从而优化掉那些用不到或者极少用的冗余部分。例如,我们的存储设备就专门为 Hadoop 优化过,设备的购买和运营成本相比于 OEM 产品降低了 20% 。同时,这样做减法还提高了设备的性能和可靠性。同样的,对于计算设备,硬件工程师们也通过移除无用的特性获得了效率提升。
+
+一个服务器可以移除的组件总是有限的,我们很快就把能移除的都扔掉了。于是我们想出了其他办法,例如在存储设备里,我们认为降低成本最好的办法是用一个节点替换多个节点,并通过 Aurora/Mesos 来管理任务负载。这就是我们现在正在做的东西。
+
+对于这个我们自己新设计的服务器,首先要通过一系列的标准测试,然后会再做一系列负载测试,我们的目标是一台新设备至少能替换两台旧设备。最大的性能提升来自增加 CPU 的线程数,我们的测试结果表示新 CPU 的 单线程能力提高了 20~50% 。同时由于整个服务器的线程数增加,我们看到单线程能效提升了 25%。
+
+这个新设备首次部署的时候,监控发现新设备只能替换 1.5 台旧设备,这比我们的目标低了很多。对性能数据检查后发现,我们之前对负载特性的一些假定是有问题的,而这正是我们在做性能测试需要发现的问题。
+
+对此我们硬件团队开发了一个模型,用来预测在不同的硬件配置下当前 Aurora 任务的填充效率。这个模型正确的预测了新旧硬件的性能比例。模型还指出了我们一开始没有考虑到的存储需求,并因此建议我们增加 CPU 核心数。另外,它还预测,如果我们修改内存的配置,那系统的性能还会有较大提高。
+
+硬件配置的改变都需要花时间去操作,所以我们的硬件工程师们就首先找出几个关键痛点。例如我们和 SRE(Site Reliability Engineer,网站可靠性工程师)团队一起调整任务顺序来降低存储需求,这种修改很简单也很有效,新设备可以代替 1.85 个旧设备了。
+
+为了更好的优化效率,我们对新硬件的配置做了修改,只是扩大了内存和磁盘容量就将 CPU 利用率提高了20% ,而这只增加了非常小的成本。同时我们的硬件工程师也和合作生产厂商一起为那些服务器的最初出货调整了物料清单。后续的观察发现我们的自己的新设备实际上可以代替 2.4 台旧设备,这个超出了预定的目标。
+
+### 从裸设备迁移到 mesos 集群
+
+直到 2012 年为止,软件团队在 Twitter 开通一个新服务还需要自己操心硬件:配置硬件的规格需求,研究机架尺寸,开发部署脚本以及处理硬件故障。同时,系统中没有所谓的“服务发现”机制,当一个服务需要调用一个另一个服务时候,需要读取一个 YAML 配置文件,这个配置文件中有目标服务对应的主机 IP 和端口信息(预留的端口信息是由一个公共 wiki 页面维护的)。随着硬件的替换和更新,YAML 配置文件里的内容也会不断的编辑更新。在缓存层做修改意味着我们可以按小时或按天做很多次部署,每次添加少量主机并按阶段部署。我们经常遇到在部署过程中 cache 不一致导致的问题,因为有的主机在使用旧的配置有的主机在用新的。有时候一台主机的异常(例如在部署过程中它临时宕机了)会导致整个站点都无法正常工作。
+
+在 2012/2013 年的时候,Twitter 开始尝试两个新事物:服务发现(来自 ZooKeeper 集群和 [Finagle](https://twitter.github.io/finagle/) 核心模块中的一个库)和 [Mesos](http://mesos.apache.org/)(包括基于 Mesos 的一个自研的计划任务框架 Aurora ,它现在也是 Apache 基金会的一个项目)。
+
+服务发现功能意味着不需要再维护一个静态 YAML 主机列表了。服务或者在启动后主动注册,或者自动被 mesos 接入到一个“服务集”(就是一个 ZooKeeper 中的 znode 列表,包含角色、环境和服务名信息)中。任何想要访问这个服务的组件都只需要监控这个路径就可以实时获取到一个正在工作的服务列表。
+
+现在我们通过 Mesos/Aurora ,而不是使用脚本(我们曾经是 [Capistrano](https://github.com/capistrano/capistrano) 的重度用户)来获取一个主机列表、分发代码并规划重启任务。现在软件团队如果想部署一个新服务,只需要将软件包上传到一个叫 Packer 的工具上(它是一个基于 HDFS 的服务),再在 Aurora 配置上描述文件(需要多少 CPU ,多少内存,多少个实例,启动的命令行代码),然后 Aurora 就会自动完成整个部署过程。 Aurora 先找到可用的主机,从 Packer 下载代码,注册到“服务发现”,最后启动这个服务。如果整个过程中遇到失败(硬件故障、网络中断等等), Mesos/Aurora 会自动重选一个新主机并将服务部署上去。
+
+#### Twitter 的私有 PaaS 云平台
+
+Mesos/Aurora 和服务发现这两个功能给我们带了革命性的变化。虽然在接下来几年里,我们碰到了无数 bug ,伤透了无数脑筋,学到了分布式系统里的无数教训,但是这套架还是非常赞的。以前大家一直忙于处理硬件搭配和管理,而现在,大家只需要考虑如何优化业务以及需要多少系统能力就可以了。同时,我们也从根本上解决了 Twitter 之前经历过的 CPU 利用率低的问题,以前服务直接安装在服务器上,这种方式无法充分利用服务器资源,任务协调能力也很差。现在 Mesos 允许我们把多个服务打包成一个服务包,增加一个新服务只需要修改配额,再改一行配置就可以了。
+
+在两年时间里,多数“无状态”服务迁移到了 Mesos 平台。一些大型且重要的服务(包括我们的用户服务和广告服务系统)是最先迁移上去的。因为它们的体量巨大,所以它们从这些服务里获得的好处也最多,这也降低了它们的服务压力。
+
+我们一直在不断追求效率提升和架构优化的最佳实践。我们会定期去测试公有云的产品,和我们自己产品的 TCO 以及性能做对比。我们也拥抱公有云的服务,事实上我们现在正在使用公有云产品。最后,这个系列的下一篇将会主要聚焦于我们基础设施的体量方面。
+
+特别感谢 [Jennifer Fraser][1]、[David Barr][2]、[Geoff Papilion][3]、 [Matt Singer][4]、[Lam Dong][5] 对这篇文章的贡献。
+
+--------------------------------------------------------------------------------
+
+via: https://blog.twitter.com/2016/the-infrastructure-behind-twitter-efficiency-and-optimization
+
+作者:[mazdakh][a]
+译者:[eriwoon](https://github.com/eriwoon)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://twitter.com/intent/user?screen_name=mazdakh
+[1]: https://twitter.com/jenniferfraser
+[2]: https://twitter.com/davebarr
+[3]: https://twitter.com/gpapilion
+[4]: https://twitter.com/mattbytes
+[5]: https://twitter.com/lamdong
\ No newline at end of file
diff --git a/published/201610/20160912 15 Top Open Source Artificial Intelligence Tools.md b/published/201610/20160912 15 Top Open Source Artificial Intelligence Tools.md
new file mode 100644
index 0000000000..e986d3950f
--- /dev/null
+++ b/published/201610/20160912 15 Top Open Source Artificial Intelligence Tools.md
@@ -0,0 +1,140 @@
+15 个开源的顶级人工智能工具
+=========
+
+人工智能(artificial intelligence, AI)是科技研究中最热门的方向之一。像 IBM、谷歌、微软、Facebook 和亚马逊等公司都在研发上投入大量的资金、或者收购那些在机器学习、神经网络、自然语言和图像处理等领域取得了进展的初创公司。考虑到人们对此感兴趣的程度,我们将不会惊讶于斯坦福的专家在[人工智能报告][1]中得出的结论:“越来越强大的人工智能应用,可能会对我们的社会和经济产生深远的积极影响,这将出现在从现在到 2030 年的时间段里。”
+
+在最近的一篇[文章][2]中,我们概述了 45 个十分有趣或有前途的人工智能项目。在本文中,我们将聚焦于开源的人工智能工具,详细的了解下最著名的 15 个开源人工智能项目。
+
+
+
+*开源人工智能*
+
+以下这些开源人工智能应用都处于人工智能研究的最前沿。
+
+### 1. Caffe
+
+
+
+它是由[贾扬清][3]在加州大学伯克利分校的读博时创造的,[Caffe][4] 是一个基于表达体系结构和可扩展代码的深度学习框架。使它声名鹊起的是它的速度,这让它受到研究人员和企业用户的欢迎。根据其网站所言,它可以在一天之内只用一个 NVIDIA K40 GPU 处理 6000 万多个图像。它是由伯克利视野和学习中心(BVLC)管理的,并且由 NVIDIA 和亚马逊等公司资助来支持它的发展。
+
+### 2. CNTK
+
+
+
+它是计算网络工具包(Computational Network Toolkit)的缩写,[CNTK][5] 是一个微软的开源人工智能工具。不论是在单个 CPU、单个 GPU、多个 GPU 或是拥有多个 GPU 的多台机器上它都有优异的表现。微软主要用它做语音识别的研究,但是它在机器翻译、图像识别、图像字幕、文本处理、语言理解和语言建模方面都有着良好的应用。
+
+### 3. Deeplearning4j
+
+
+
+[Deeplearning4j][6] 是一个 java 虚拟机(JVM)的开源深度学习库。它运行在分布式环境并且集成在 Hadoop 和 Apache Spark 中。这使它可以配置深度神经网络,并且它与 Java、Scala 和 其他 JVM 语言兼容。
+
+这个项目是由一个叫做 Skymind 的商业公司管理的,它为这个项目提供支持、培训和一个企业的发行版。
+
+### 4. DMTK
+
+
+
+[DMTK][7] 是分布式机器学习工具(Distributed Machine Learning Toolkit)的缩写,和 CNTK 一样,是微软的开源人工智能工具。作为设计用于大数据的应用程序,它的目标是更快的训练人工智能系统。它包括三个主要组件:DMTK 框架、LightLDA 主题模型算法和分布式(多义)字嵌入算法。为了证明它的速度,微软声称在一个八集群的机器上,它能够“用 100 万个主题和 1000 万个单词的词汇表(总共 10 万亿参数)训练一个主题模型,在一个文档中收集 1000 亿个符号,”。这一成绩是别的工具无法比拟的。
+
+### 5. H20
+
+
+
+相比起科研,[H2O][8] 更注重将 AI 服务于企业用户,因此 H2O 有着大量的公司客户,比如第一资本金融公司、思科、Nielsen Catalina、PayPal 和泛美都是它的用户。它声称任何人都可以利用机器学习和预测分析的力量来解决业务难题。它可以用于预测建模、风险和欺诈分析、保险分析、广告技术、医疗保健和客户情报。
+
+它有两种开源版本:标准版 H2O 和 Sparking Water 版,它被集成在 Apache Spark 中。也有付费的企业用户支持。
+
+### 6. Mahout
+
+
+
+它是 Apache 基金会项目,[Mahout][9] 是一个开源机器学习框架。根据它的网站所言,它有着三个主要的特性:一个构建可扩展算法的编程环境、像 Spark 和 H2O 一样的预制算法工具和一个叫 Samsara 的矢量数学实验环境。使用 Mahout 的公司有 Adobe、埃森哲咨询公司、Foursquare、英特尔、领英、Twitter、雅虎和其他许多公司。其网站列了出第三方的专业支持。
+
+### 7. MLlib
+
+
+
+由于其速度,Apache Spark 成为一个最流行的大数据处理工具。[MLlib][10] 是 Spark 的可扩展机器学习库。它集成了 Hadoop 并可以与 NumPy 和 R 进行交互操作。它包括了许多机器学习算法如分类、回归、决策树、推荐、集群、主题建模、功能转换、模型评价、ML 管道架构、ML 持久、生存分析、频繁项集和序列模式挖掘、分布式线性代数和统计。
+
+### 8. NuPIC
+
+
+
+由 [Numenta][11] 公司管理的 [NuPIC][12] 是一个基于分层暂时记忆(Hierarchical Temporal Memory, HTM)理论的开源人工智能项目。从本质上讲,HTM 试图创建一个计算机系统来模仿人类大脑皮层。他们的目标是创造一个 “在许多认知任务上接近或者超越人类认知能力” 的机器。
+
+除了开源许可,Numenta 还提供 NuPic 的商业许可协议,并且它还提供技术专利的许可证。
+
+### 9. OpenNN
+
+
+
+作为一个为开发者和科研人员设计的具有高级理解力的人工智能,[OpenNN][13] 是一个实现神经网络算法的 c++ 编程库。它的关键特性包括深度的架构和快速的性能。其网站上可以查到丰富的文档,包括一个解释了神经网络的基本知识的入门教程。OpenNN 的付费支持由一家从事预测分析的西班牙公司 [Artelnics][14] 提供。
+
+### 10. OpenCyc
+
+
+
+由 Cycorp 公司开发的 [OpenCyc][15] 提供了对 Cyc 知识库的访问和常识推理引擎。它拥有超过 239,000 个条目,大约 2,093,000 个三元组和大约 69,000 owl:这是一种类似于链接到外部语义库的命名空间。它在富领域模型、语义数据集成、文本理解、特殊领域的专家系统和游戏 AI 中有着良好的应用。该公司还提供另外两个版本的 Cyc:一个免费的用于科研但是不开源,和一个提供给企业的但是需要付费。
+
+### 11. Oryx 2
+
+
+
+构建在 Apache Spark 和 Kafka 之上的 [Oryx 2][16] 是一个专门针对大规模机器学习的应用程序开发框架。它采用一个独特的三层 λ 架构。开发者可以使用 Orys 2 创建新的应用程序,另外它还拥有一些预先构建的应用程序可以用于常见的大数据任务比如协同过滤、分类、回归和聚类。大数据工具供应商 Cloudera 创造了最初的 Oryx 1 项目并且一直积极参与持续发展。
+
+### 12. PredictionIO
+
+
+
+今年的二月,Salesforce 收购了 [PredictionIO][17],接着在七月,它将该平台和商标贡献给 Apache 基金会,Apache 基金会将其列为孵育计划。所以当 Salesforce 利用 PredictionIO 技术来提升它的机器学习能力时,成效将会同步出现在开源版本中。它可以帮助用户创建带有机器学习功能的预测引擎,这可用于部署能够实时动态查询的 Web 服务。
+
+### 13. SystemML
+
+
+
+最初由 IBM 开发, [SystemML][18] 现在是一个 Apache 大数据项目。它提供了一个高度可伸缩的平台,可以实现高等数学运算,并且它的算法用 R 或一种类似 python 的语法写成。企业已经在使用它来跟踪汽车维修客户服务、规划机场交通和连接社会媒体数据与银行客户。它可以在 Spark 或 Hadoop 上运行。
+
+### 14. TensorFlow
+
+
+
+[TensorFlow][19] 是一个谷歌的开源人工智能工具。它提供了一个使用数据流图进行数值计算的库。它可以运行在多种不同的有着单或多 CPU 和 GPU 的系统,甚至可以在移动设备上运行。它拥有深厚的灵活性、真正的可移植性、自动微分功能,并且支持 Python 和 c++。它的网站拥有十分详细的教程列表来帮助开发者和研究人员沉浸于使用或扩展他的功能。
+
+### 15. Torch
+
+
+
+[Torch][20] 将自己描述为:“一个优先使用 GPU 的拥有机器学习算法广泛支持的科学计算框架”,它的特点是灵活性和速度。此外,它可以很容易的通过软件包用于机器学习、计算机视觉、信号处理、并行处理、图像、视频、音频和网络等方面。它依赖一个叫做 LuaJIT 的脚本语言,而 LuaJIT 是基于 Lua 的。
+
+--------------------------------------------------------------------------------
+
+via: http://www.datamation.com/open-source/slideshows/15-top-open-source-artificial-intelligence-tools.html
+
+作者:[Cynthia Harvey][a]
+译者:[Chao-zhi](https://github.com/Chao-zhi)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: http://www.datamation.com/author/Cynthia-Harvey-6460.html
+[1]: https://ai100.stanford.edu/sites/default/files/ai_100_report_0906fnlc_single.pdf
+[2]: http://www.datamation.com/applications/artificial-intelligence-software-45-ai-projects-to-watch-1.html
+[3]: http://daggerfs.com/
+[4]: http://caffe.berkeleyvision.org/
+[5]: https://www.cntk.ai/
+[6]: http://deeplearning4j.org/
+[7]: http://www.dmtk.io/
+[8]: http://www.h2o.ai/
+[9]: http://mahout.apache.org/
+[10]: https://spark.apache.org/mllib/
+[11]: http://numenta.com/
+[12]: http://numenta.org/
+[13]: http://www.opennn.net/
+[14]: https://www.artelnics.com/
+[15]: http://www.cyc.com/platform/opencyc/
+[16]: http://oryx.io/
+[17]: https://prediction.io/
+[18]: http://systemml.apache.org/
+[19]: https://www.tensorflow.org/
+[20]: http://torch.ch/
\ No newline at end of file
diff --git a/published/201610/20160912 8 best practices for building containerized applications.md b/published/201610/20160912 8 best practices for building containerized applications.md
new file mode 100644
index 0000000000..7ed7784ee9
--- /dev/null
+++ b/published/201610/20160912 8 best practices for building containerized applications.md
@@ -0,0 +1,74 @@
+8 个构建容器应用的最佳实践
+====
+
+
+
+容器是未来在共有云和私有云进行应用开发的主要趋势,但是容器到底是什么,为什么它们成为了一种广受欢迎的部署机制,而且你需要怎样来修改你的应用来为容器化的环境优化它?
+
+### 什么是容器?
+
+容器技术的历史始于 2000 年的 SELinux 和 2005 年的 Solaris zones。今天,容器是由包括 SELinux、Linux 命名空间和控制组(cgroup)等几项内核特性构成,提供了用户进程、网络空间和文件系统空间的隔离。
+
+### 为什么它们如此流行?
+
+最近容器技术大规模的应用在很大程度上是由于旨在使容器更加易于使用的标准的发展,例如 Docker 镜像格式和分布模型,这个标准使用不可变镜像(immutable image),这正是容器运行时环境的起点,不可变镜像可以保证开发团队发布的镜像就是经过测试的,和部署到生产环境中的镜像是同样的镜像。
+
+容器所提供的轻量级隔离为一个应用组件提供了一个更好的抽象。在容器中运行的组件将不会干扰其它可能直接运行在虚拟机上的应用。它们可以避免对系统资源的争夺,而且除非它们共享一个持久卷,否则不会阻止对同一个文件的写请求。容器使得日志和指标采集的实践得以标准化,而且它们可以在物理机和虚拟机上支持更大的用户密度,所有的这些优点将导致更低的部署成本。
+
+### 我们应该如何构建一个基于容器的应用呢?
+
+将应用改为运行在容器中并不是什么很高的要求。主要的 Linux 发行版都有提供了基础镜像,任何可以在虚拟机上运行的程序都可以在上面运行。但是容器化应用的趋势是遵循如下最佳实践:
+
+#### 1. 实例是一次性的
+
+你的应用的任何实例都不需要小心地保持运行。如果你的一个运行了许多容器的系统崩溃了,你还能够转移到其它可用的系统去创建新的容器。
+
+#### 2. 重试而不是崩溃
+
+当你的应用的一个服务依赖于另一个服务的时候,在另一个服务不可用的时候它应该不会崩溃。例如,你的 API 服务正在启动而且监测到数据库不能连接。你应该设计它使得其不断重试连接,而不是运行失败和拒绝启动。当数据库连接断开的时候 API 可以返回 503 状态码,告诉客户端服务现在不可用。应用应该已经遵守了这个实践,但是如果你正在一个一次性实例的容器环境中工作,那么对这个实践的需要会更加明显。
+
+#### 3. 持久性数据是特殊的
+
+容器是基于共享镜像启动,它使用了写时复制(COW)文件系统。如果容器的进程选择写入文件,那么这些写的内容只有在直到容器存在时才存在。当容器被删除的时候,写时复制文件系统中的那一层会被删除。提供给容器一个挂载的文件系统目录,使之在容器存活之外也能持久保存,这需要另外的配置,而且会额外消耗物理存储。明确的抽象定义了什么存储是持久的,催生出了实例是一次性的观点。拥有一个抽象层也使得容器编制引擎可以处理挂载和卸载持久卷的复杂请求,以便这些持久卷可以用于容器。
+
+#### 4. 使用 stdout 而不是日志文件
+
+现在你或许会思考,如果持久的数据是特殊的,那么我用日志文件来做什么事情?容器运行时环境和编制引擎项目所采用的方法是进程应该[写入 stdout/stderr][1],而且具有归档和维护[容器日志][2]的基础设施。
+
+#### 5. 敏感信息(以及其它配置信息)也是特殊的
+
+你绝不应该将敏感信息例如密码、密钥和证书硬编码到你的镜像中。通常在你的应用与开发服务、测试服务,或者生产服务相交互时,这些敏感信息通常都是不同的。大多数开发者并没有访问生产环境的敏感信息的权限,所以如果敏感信息被打包到镜像中,那么必须创建一个新的镜像层来覆盖这个开发服务的敏感信息。基于这一点来看,你再也不能使用与你们开发团队所创建的和质量测试所测试的相同的镜像了,而且也失去了不可修改的镜像的好处。相反的,这些值应该被存储在环境变量中文件中,它们会在容器启动时导入。
+
+#### 6. 不要假设服务的协同定位
+
+在一个编排好的容器环境中,你会希望让编排器将你的容器发送到任何最适合的节点。最适合意味着很多事情:它应该基于那个节点现在拥有最多的空间、容器所需的服务质量、容器是否需要持久卷,等等。这可能意味这你的前端、API 和数据库容器最终都会放在不同的节点。尽管给每个节点强制分配一个 API 容器是可以做到的(参考 Kubernetes 的 [DaemonSets][3]),但这种方式应该留给执行监控节点自身这类任务的容器。
+
+#### 7. 冗余/高可用计划
+
+即使你没有那么多负载需要高可用性的配置,你也不应该以单路方式编写服务,否则会阻止它运行多份拷贝。这将会允许你运用滚动式部署,使得将负载从一个节点移动到另外一个节点非常容易,或者将服务从一个版本更新到下一个版本而不需要下线。
+
+#### 8. 实现就绪检查和灵活性检查
+
+应用在响应请求之前会有一定的启动时间是一件很正常的事情,例如,一个 API 服务器需要填充内存数据缓存。容器编排引擎需要一种方法来检测你的容器是否准备好服务用户请求。为一个新的容器提供就绪检查可以允许我们进行滚动式部署,使得旧容器可以继续运行直到不再需要它,这可以防止服务宕机。类似的,一个存活检查也是一种容器编排引擎持续检查容器是否在健康可用状态的方法。决定容器健康或者说“存活”应该由容器应用的创建者说了算。一个不再存活的容器将会被结束,而且一个新的容器会被创建来替代它。
+
+### 想查找更多资料?
+
+我将会出席十月份的格雷丝霍普计算机女性峰会(Grace Hopper Celebration of Women in Computing),你可以在这里来看一下关于我的访谈:[应用的容器化:是什么,为什么,和如何实现][4]。今年不去 GHC 吗?那你可以在 [OpenShift][5] 和 [Kubernetes][6] 的项目站点来了解关于容器、编排和应用的相关内容。
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/life/16/9/8-best-practices-building-containerized-applications
+
+作者:[Jessica Forrester][a]
+译者:[LinuxBars](https://github.com/LinuxBars)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/jwforres
+[1]: https://docs.docker.com/engine/reference/commandline/logs/
+[2]: http://kubernetes.io/docs/getting-started-guides/logging/
+[3]: http://kubernetes.io/docs/admin/daemons/
+[4]: https://www.eiseverywhere.com/ehome/index.php?eventid=153076&tabid=351462&cid=1350690&sessionid=11443135&sessionchoice=1&
+[5]: https://www.openshift.org/
+[6]: http://kubernetes.io/
diff --git a/published/201610/20160912 Content Security Policy, Your Future Best Friend.md b/published/201610/20160912 Content Security Policy, Your Future Best Friend.md
new file mode 100644
index 0000000000..90cd08e208
--- /dev/null
+++ b/published/201610/20160912 Content Security Policy, Your Future Best Friend.md
@@ -0,0 +1,231 @@
+内容安全策略(CSP),防御 XSS 攻击的好助手
+=====
+
+很久之前,我的个人网站被攻击了。我不知道它是如何发生的,但它确实发生了。幸运的是,攻击带来的破坏是很小的:一小段 JavaScript 被注入到了某些页面的底部。我更新了 FTP 和其它的口令,清理了一些文件,事情就这样结束了。
+
+有一点使我很恼火:在当时,还没有一种简便的方案能够使我知道那里有问题,更重要的是能够保护网站的访客不被这段恼人的代码所扰。
+
+现在有一种方案出现了,这种技术在上述两方面都十分的成功。它就是内容安全策略(content security policy,CSP)。
+
+### 什么是 CSP?
+
+其核心思想十分简单:网站通过发送一个 CSP 头部,来告诉浏览器什么是被授权执行的与什么是需要被禁止的。
+
+这里有一个 PHP 的例子:
+
+```
+");
+?>
+```
+
+#### 一些指令
+
+你可以定义一些全局规则或者定义一些涉及某一类资源的规则:
+
+```
+default-src 'self' ;
+ # self = 同端口,同域名,同协议 => 允许
+```
+
+基础参数是 `default-src`:如果没有为某一类资源设置指令规则,那么浏览器就会使用这个默认参数值。
+
+```
+script-src 'self' www.google-analytics.com ;
+ # 来自这些域名的 JS 文件 => 允许
+```
+
+在这个例子中,我们已经授权了 www.google-analytics.com 这个域名来源的 JavaScript 文件使用到我们的网站上。我们也添加了 `'self'` 这个关键词;如果我们通过 `script-src` 来重新设置其它的规则指令,它将会覆盖 `default-src` 规则。
+
+如果没有指明协议(scheme)或端口,它就会强制选择与当前页面相同的协议或端口。这样做防止了混合内容(LCTT 译注:混合内容指 HTTPS 页面中也有非 HTTPS 资源,可参见: https://developer.mozilla.org/zh-CN/docs/Security/MixedContent )。如果页面是 https://example.com,那么你将无法加载 http://www.google-analytics.com/file.js 因为它已经被禁止了(协议不匹配)。然而,有一个例外就是协议的提升是被允许的。如果 http://example.com 尝试加载 https://www.google-analytics.com/file.js,接着协议或端口允许被更改以便协议的提升。
+
+```
+style-src 'self' data: ;
+ # Data-Uri 嵌入 CSS => 允许
+```
+
+在这个例子中,关键词 `data:` 授权了在 CSS 文件中 data 内嵌内容。
+
+在 CSP 1 规范下,你也可以设置如下规则:
+
+- `img-src` 有效的图片来源
+- `connect-src` 应用于 XMLHttpRequest(AJAX),WebSocket 或 EventSource
+- `font-src` 有效的字体来源
+- `object-src` 有效的插件来源(例如,`