转:来自HeroKu的HTTP API 设计指南(中文版)

八月 31st, 2014 评论关闭
简介

本指南中文翻译者为 @Easy ,他是国内首家互联网人才拍卖网站 JobDeer.com 的创始人。转载请保留本信息。

本指南描述了一系列 HTTP+JSON API 的设计实践, 来自并展开于 Heroku Platform API 的工作。本指南指导着Heroku内部API的开发,我们希望也能对Heroku以外的API设计者有所帮助。

目录

基础

  • 总是使用TLS
  • 在Accepts头中带上版本号
  • 通过Etags支持缓存
  • 用Request-Ids追踪请求
  • 用Ranges来分页

请求

  • 返回适当的状态码
  • 总是返回完整的资源
  • 在请求body中接收JSON序列
  • 使用一致的路径格式
  • 小写所有路径和属性
  • 支持非ID的参数作为快捷方式
  • 少用路径嵌套

响应

  • 总是提供资源(UU)ID
  • 提供标准的时间戳
  • 使用ISO8601格式的UTC时间
  • 嵌入外键数据
  • 总是生成结构化的错误信息
  • 显示频率限制的状态
  • 在所有的响应中压缩JSON数据

文档及其他

  • 提供机器可读的JSON格式
  • 提供人类可读的文档
  • 提供可执行的示例
  • 描述稳定性
基础 总是使用TLS

总是使用TLS(就是https)来访问API,没有必要指出什么时候需要用,什么时候不需要用,只管任何时候都用它就好。

对所有非TLS的请求返回403 Forbidden,不要用重定向,这会允许一些不良的客户端行为,而又没有任何好处。依赖重定向的客户端会使流量翻倍,而让TLS毫无意义 —— 敏感数据已经在第一次请求时发送出来了。

在Accepts头中带上版本号

从一开始就为API分配版本。使用Accepts头来发送版本信息,可以使用自定义的内容类型,如:

Accept: application/vnd.heroku+json; version=3

不要提供默认版本,而由客户端显式指定它使用哪一个特定的版本。

通过Etags支持缓存

在所有的请求中带上 ETag 头 , 用于识别特定版本的返回资源。用户可以在随后的请求中通过提供If-None-Match头的值来检查内容是否过期。

用Request-Ids追踪请求

在每个API相应中提供Request-Id头,带上一个唯一的UUID值。如果服务器和客户端都记录了这些值,在跟踪和调试请求时会派上大用场。

用Ranges来分页

对所有可能产生大量数据的  阅读全文...

百度员工离职总结:如何做个好员工

七月 21st, 2014 评论关闭

2014 年 7 月 4 日,我从百度离职了。

这是第一次,我不是因为和老板闹翻而离职;

这是第一次,我带着晋升的喜悦而离职;

这是第一次,我带着满满的收获而离职。

我曾经认为,我永远不会成为一个好员工,因为我太独、太挑剔、不喜欢听话的好孩子、而且讨厌一切想要改变我的人。但是三年过去,我改变了不少,我必须承认,所谓“进步”的过程,就是被认可的过程,也是被“驯化”的过程。

所谓“驯化”,就是了解规则、遵守规则、利用规则的过程。我并非被某些人“驯化”,而是被社会与职场的规律驯化。我曾经鄙视这个过程,但今天看来,作为一个资质平庸的人,如果你想在这个社会里做成点儿什么,“被驯化”是不可避免的。

我也曾自诩“卓尔不群”,又受了老罗“彪悍的人生不需要解释”的“蛊惑”。但在现实中,这个路子不一定行得通。你不得不向很多人解释、用他们(而不是自己)喜欢的方式解释,因为只有得到他们的认可和支持,你才能继续工作下去。如果你是一个资质平庸的人,你不得不这样做,美剧《犯罪心理》中有一句话:“凡按自己的方式追求理想者,无不树敌。”

树敌多了,你就死了。

现在,我不敢说自己是个“好员工”,我只是觉得我是个比曾经的自己更好的员工。在离职的时候,我打算把自己这几年的职场心得总结一下,算是给自己的一个礼物。

我是一个资质平庸的人,以下这些心得只适用于愚钝且资质平庸的我,对于才华横溢的天才们并不适用。

一、你有“同理心”吗?

什么叫“同理心”?

说复杂点儿,同理心就是站在当事人的角度和位置上,客观地理解当事人的内心感受,且把这种理解传达给当事人的一种沟通交流方式。

说简单点儿,同理心就是“己所不欲,勿施于人”。将心比心,也就是设身处地去感受、去体谅他人。

说白了,同理心就是“情商”。

具体点说:

同理心就是,领导交办一项工作,你要读懂他的目的、看清他的用意。我经常遇到这样的情况:给团队成员安排工作时,一再询问“我说明白了吗”“有没有问题”,再三确认后,提交上来的东西仍然答非所问。所以我在接受任务时,总会向领导确认:你想要的是什么?你的目的是什么?了解这个以后,就可以站在他的角度,有效的帮他解决问题。

同理心就是,在激励员工时,点准他们的“兴奋点”,不揭“伤疤”。每个人都  阅读全文...

转:为SSD编程:总结每个程序员都应该了解的固态硬盘知识

六月 4th, 2014 评论关闭

在这部分,我以独立的简单段落的形式总结了其它部分的内容。每个段落概括了其他部分一节或几节的内容,这样可以让读者在每个主题下能够得到更多细节。

基础 1. 存储单元类型

固态硬盘(SSD)是基于闪存的数据存储设备。每个比特都存储在存储单元中,而存储单元分为三类:每个单元1比特(单层单元,SLC),每个单元2比特(多层单元,MLC),每个单元3比特(三层单元,TLC)。

>> 详见第1.1节

2. 寿命限制

每个单元都有P/E(写/擦)循环的最大限制,在此之后存储单元被认为是损坏的。这表示NAND闪存已经损耗殆尽,并有一个寿命限制。

>> 详见第1.1节

3. 基准测试很难

测试者是人,因此并不是所有的基准测试都毫无破绽。在读生产商或者第三方的基准测试结果的时候请小心,并在相信这些数据之前使用多个来源的数据。在有可能的时候,使用你的系统特定的工作负载在你打算使用的SSD型号上,运行自己的内部基准测试。最后,着眼于与你的系统最相关的性能指标。

>> 详见第2.2节和第2.3节

 

页和块 4. NAND闪存页和块

闪存单元组织成为阵列,称为块,而块组织成为面。块中能够进行读写操作的最小单元是页。页不能独立擦除,只能整块擦除。NAND闪存页大的大小并不一致,大多数硬盘的页大小是2KB、4KB、8 KB 或16 KB。大多数SSD每个块有128或256个页。这即表示一个块的大小可能在256 KB 到4 MB之间。例如Samsung SSD 840 EVO的块大小是2048 KB,每块包括256页每页8KB。

>> 详见第3.2节

5. 读是页对齐的

一次读取少于一页是不可能的。当然可以通过操作系统只请求一个直接,但SSD中会取回整个页,强制读取比所需多的多的数据。

>> 详见第3.2节

6. 写是页对齐的

写入到SSD的时候,写入将补齐到页大小。所以即便写入操作只影响一字节,都会重写整个页。写入比所需更多的数据被称为写入放大。写入一个页也被称为“(编置to program)”一个页。

>> 详见第3.2节

7.页不能覆写

NAND闪存页只能在其为“空”的状态下进行写入。当数据改变,页的内容被复制到内部寄存器中,数据更新,然后新版本的数据将存储字啊一个”空“页中,这个操作被称为”读-改-写“。数据并非原地更新,因为”空”页并非原先存储数据的页。一旦数据被保存到硬盘上,原来的页将被标记为“废弃”,并一直保持这样  阅读全文...

转:真正统治世界的十大算法

五月 10th, 2014 评论关闭

不久前的某一天,我在浏览Reddit发现了一篇有趣的文章《统治世界的十大算法》,作者George Dvorsky在那篇文章中试图解释算法之于当今世界的重要性,以及哪些算法对人类文明最为重要。

此时此刻,如果你已经学过算法的话,那么在你阅读那篇文章时,你脑海中所浮现的第一件事也许是“作者是否明白算法是什么?”或是“Facebook的新闻提要是一种算法?”,因为如果Facebook的新闻提要也算是一种算法的话,那么最终你可以把几乎所有的东西都归类为算法。因此,在本文中我会试着去解释什么是算法,以及哪十个(也许更多)算法是真正统治世界的。

什么是算法?

直白地说,算法就是任何明确定义的计算过程,它接收一些值或集合作为输入,并产生一些值或集合作为输出。这样,算法就是将输入转换为输出的一系列计算过程。来源:Thomas H. Cormen, Chales E. Leiserson (2009), 《算法导论第三版》。**

简而言之,我们可以说算法就是用来解决一个特定任务的一系列步骤(是的,不止计算机在使用算法,人类也同样如此)。目前,一个有效的算法应该含有三个重要特性:

1. 它必须是有限的:如果你设计的算法永无休止地尝试解决问题,那么它是无用的。
2. 它必须具备明确定义的指令:算法的每一步都必须准确定义,在任何场景下指令都应当没有歧义。
3. 它必须是有效的:一个算法被设计用以解决某个问题,那么它就应当能解决这个问题,并且仅仅使用纸和笔就能证明该算法是收敛的。

还有一个要点需要指出,算法不仅仅在计算机科学中使用,同时也存在于数学领域中。事实上,首个被记载的数学算法要追溯到公元前1600年,古巴比伦人开发了已知最早的算法,用作因式分解和计算平方根。这里,我们回答了前面所提到的那篇文章中的第一个问题,它认为算法是计算机范畴的实体,但如果你知晓算法这个词的真正内涵的话,真正统治世界的十大算法也能在数学书籍中找到(加法、减法、乘积等等)。

不过在这篇文章中,让我们将算法的定义限定在计算机算法上,所以剩下的问题是:哪十个算法统治了世界?在此我整理了一个小型列表,排名不分先后。

1. 归并排序,快速排序和堆排序

阅读全文...

转:不要成为工具的奴隶

四月 23rd, 2014 评论关闭

开发人员很容易迷恋上工具,因为工具通常比较实用,而且具备明确定义的行为,比起学习最佳实践或方法,学习工具更为简单。然而,工具仅仅为解决问题提供协助,他们并不能自行解决问题。

一位理解问题实质的开发人员能够使用工具提高生产率和质量,而拙劣的程序员从来不投入时间或精力去理解如何更好的编程和如何避免缺陷,他们会花时间学习如何使用工具,但这种学习方式脱离了对工具目标以及如何高效使用的正确理解。

在某种程度上说,这其中有一部分是工具供应商的错,他们嗅到了为一些普遍问题提供支持是一条财路,比如说:

*缺陷追踪器,帮助你进行缺陷追踪管理
*版本控制系统,管理源代码更改
*敏捷开发支持工具(Version One, JIRA)
*调试器,帮助你寻找缺陷

市面上有很多工具,但在这里我仅仅浏览一下下面的列表,同时指出在哪些地方开发人员和组织正在经受挑战。记住,以下所有的统计数据都来源于40多年间的超过15000个项目。

缺陷跟踪器

 

一些公司还没有用过缺陷跟踪软件,不管你信不信,我反正是信了,我遇到过这样几个奇葩公司,你一定觉得难以置信吧。没有缺陷跟踪软件的结果是相当杯具的,我们有证据证实。

不充分的缺陷跟踪方法:生产率 -15%,质量 -21%
就此我们达成了高度共识,那就是我们需要进行缺陷跟踪,并且我们都清楚,离开了这类工具,管理大量缺陷是不可能的。

自动化缺陷跟踪工具:生产率 +18%,质量 26%*

 

先说一个问题,开发人员总是爱争执哪个缺陷跟踪系统最好,这里的根本问题在于,几乎每个缺陷跟踪系统设置不好都会导致糟糕的结果。实际上,如果每个缺陷跟踪系统都能进行合理配置的话,结果都会大有裨益。这里最常见的误区是:
*在缺陷生命周期状态中引入了不相关属性,即创建诸如”延期“, ”无法解决“或 ”已设计的功能“这样的状态。
*无法指出问题是否已被修复。
*无法理解谁负责解决缺陷。

工具的供应商非常乐意继续提供这些缺陷跟踪器的新版本,然而要高效地使用缺陷跟踪器,更多的是取决于如何使用好这个工具,而非选择哪一种工具。

很多公司都在设法解决的一个最基本的问题是:如何定义缺陷?缺陷通常是指代码没有遵照规范工作,但是假设我们没有规范或规范很烂,那又会如何?你可以看一  阅读全文...

转:HAR(HTTP Archive)规范

三月 14th, 2014 评论关闭
HAR(HTTP Archive)规范

HAR(HTTP Archive),是一个用来储存HTTP请求/响应信息的通用文件格式,基于JSON。这个格式的出现可以使HTTP监测工具以一种通用的格式导出所收集的数据,这些数据可以被其他支持HAR的HTTP分析工具(包括Firebug,httpwatch,Fiddler等)所使用,来分析网站的性能瓶颈。目前HAR规范最新版本为HAR 1.2。HAR文件必须是UTF-8编码,有无BOM无所谓。

HAR数据结构:

一个HAR文件就是一个JSON对象,如下:

{ "log": { "version" : "1.2", "creator" : {}, "browser" : {}, "pages": [], "entries": [], "comment": "" } }
  • version [string] – 版本,默认为1.1。
  • creator [object] – 创建HAR文件的程序名称和版本信息。
  • browser [object, 可选] – 浏览器的名称和版本信息。
  • pages [array, 可选] – 页面列表,如果应用不支持按照page分组,可以省去此字段。
  • entries [array] – 所有HTTP请求的列表。
  • comment [string, 可选](new in 1.2) – 注释。

注:每个页面对应一个 对象,每个HTTP请求对应一个对象。如果HTTP的监测分析工具不能把请求按照page分组,那么为空。

<creator> & <browser>

这两个对象的结构是一样的

"creator": { "name": "Firebug", "version": "1.6", "comment": "", } "browser": { "name": "Firefox", "version": "3.6", "comment": "" }
  • name [string] – HAR生成工具或者浏览器的名称。
  • version [string] – HAR生成工具或者浏览器的版本。
  • comment [string, 可选](new in 1.2) – 注释。
<pages>

这个对象保存了页面列表,格式如下:

"pages": [ { "startedDateTime": "2009-04-16T12:07:25.123+01:00", "id": "page_0", "title": "Test Page", "pageTimings": {...}, "comment": "" } ]
  • startedDateTime [string] – 页面开始加载的时间(格式ISO 8601 – YYYY-MM-DDThh:mm:ss.sTZD, 例如2009-07-24T19:20:30.45+01:00)。
  • id [string] – page的唯一标示,entry会用到这个id来和page关联在一起  阅读全文...

转:Linux内核管理风范

二月 27th, 2014 评论关闭
1. 中译.Linux内核管理风范 1.1. 导言

Linus Torvalds 在2004年把一篇讲”Linux内核的管理风格”的文章放在了内核源码文档里。这篇文章有意对应他以前写的关于编码 风格的文章(比如烧书仪式),也有技术人员熟悉的Dilbert卡通的影子。 Henrik Ingo 写”Open Life: The Philosophy of Open Source“一书的时候,拿这篇文章作了后记。

这篇文章其实是总结了Linus十几年里领导开源运动的经验。更重要的是,它讲述了一种与传统不同的做事理念,一种后互联网时代的、尊重技术和自由的理念。

Linus的写作诙谐生动,完全不同于ESR的《大教堂和市集》。所以我作了比较自由的翻译。以下是译文。

1.2. Linux内核的管理风格

(Linux kernel management style, by Linus Torvalds. Retrieved from http://openlife.cc/node/43, Jan-28-2008)

这个简单文档描述Linux内核偏爱的(或编造的,取决于你问谁)管理模式。它在一定程度上是编码风格文档的影子,主要写来避免一遍又一遍回答同一类问题*。

  • 管理风格是很个人化的,比起简单的编码风格条例更难量化,所以这个文档跟现实可能沾边也可能不沾边。它开始于游戏,但是不见得就不作数。你只有自个儿决定。
  • 顺便说一下,我们说到”内核管理者”的时候,完全是说技术带头人,不是公司里那些作传统管理工作的人。如果你是在订单上签名的人或者对你们组的预算知道一丁半点,你几乎一定不是个”内核管理者”。这些建议对你可能适用也可能不适用。
  • 首先,我建议你买一本《高度成功人士的七个习惯》,不-要读它,烧了。表一下决心。
    • (*) 这个文档不见得”回答”多少问题,更大程度上是展示我们的无知,让提问者死了这条心。

不管怎样,开讲了:

1.2.1. 第一章:决定

每个人都觉得管理者是作决定的,作决定是很重要的。决定越大、越艰难,管理者就越伟大。这一点很深刻、很明显,但不见得正确。

  • 事情的要义是避免-作决定的必要性。特别是,当有人告诉你”是甲还是乙,我们需要你来作决定”,你作管理的麻烦就来了。你手下的人一般比你更懂具体问题,所以要是他们找你作一个技术性的决定,你死定了。要替他们作决定,你显然水平不够。

(推论:如果你手下的人不比你更懂具体  阅读全文...

微博平台的RPC服务化实践

一月 27th, 2014 评论关闭

微博平台的RPC服务化实践

 

2014年第一分钟,新浪微博的发布量以808298条再次刷新记录,第一秒微博发布量相较去年提升55%。(数据来源:新浪科技 http://tech.sina.com.cn/i/2014-01-01/02409059293.shtml )这是微博平台 RPC 框架 “Motan” 上线后第一次抗峰值,整体表现平稳,基本达到最初的“应用方无感知”的目标。

 

在RPC服务化这个事情上,微博平台不是第一个吃螃蟹的:早的有亚马逊和eBay等国外先驱,近的有Twitter的finagle,淘宝的dubbo等等,网上各种公开的资料铺天盖地。另一方面,单纯的RPC调用功能实现,从技术上看其实并不复杂:client 发起调用,框架拦截调用信息,序列化,传输,server端收到调用信息,反序列化,根据调用信息发起实际调用获取结果,再原路返回。实现这些功能可能也就三五天的事情,但在一个复杂的业务环境下,稳定可靠的应用它,才是最大的挑战。

 

微博平台的 RPC 服务化拆分历程始于2013年7月。在此之前,我们花了很长的时间讨论服务化的目标,主要是项目的范围:哪些问题不属于服务化项目需要解决的问题。 实际的框架代码开发花了三个工程师(王喆@wangzhe_asdf9 陈波@fishermen 麦俊生@麦俊生)大约一个月时间,然后花了将近两个月的时间推动在第一个业务上线:调整工程师的开发模式,调整测试流程,修改上线系统,添加监控和报警,小流量测试,灰度发布,最后才是全量上线。然后又花了一个月,在微博平台主要业务中全部上线。

 

微博RPC的一些基本的数据指标:

  • Motan 框架:2w+ 行 Java 代码,1w 行 test 代码,UT行覆盖率超过 70%(当前 Motan 实现中,与微博平台内部多个系统都有功能绑定,还不具备开源条件,但开源是我们从一开始就设立好的目标之一)
  • 支持 2 种调用方式:inJVM 和 TCP远程调用。inJVM 方式类似 loopback 网卡:数据经过了协议栈流程处理,但没有流经真正的网络设备。inJVM方式主要用来支持开发调试和测试,以及在RPC服务上线初期作为Fail-Back降级使用
  • 典型业务场景下单实例 tps 极限 20k,微博平台一般采用单机双实例,即单机极限 40k
  • 典型业务场景下平均响应时间 <3 ms,框架层额外消耗 < 0.01 ms
  • 最大的单个核心业务日调用量超过 800亿次

 <  阅读全文...

微博关系服务与Redis的故事

一月 25th, 2014 评论关闭

微博关系服务与Redis的故事

 

新浪微博的工程师们曾经在多个公开场合都讲到过,微博平台当前在使用并维护着可能是世界上最大的Redis集群,其中最大的一个业务,单个业务使用了超过 10T 的内存,这个业务就是微博关系服务。

 

2009年微博刚刚上线的时候,微博关系服务使用的是最传统的 memcache+mysql 的方案。Mysql 按 uid hash 进行了分库分表,表结构非常简单:

tid fromuid touid addTime 自增id 关系主体 关系客体 加关注时间

 

业务方存在两种查询:

  • 查询用户的关注列表:select touid from table where fromuid=?order by addTime
  • 查询用户的粉丝列表:select fromuid from table where touid=?order by addTime

两种查询的业务需求与分库分表的架构设计存在矛盾,最终导致了冗余存储:以 fromuid 为hash key存一份,以 touid 为hash key再存一份。memcache key 为 fromuid.suffix ,使用不同的 suffix 来区分是关注列表还是粉丝列表,cache value 则为 PHP Serialize 后的 Array。后来为了优化性能,将 value 换成了自己拼装的 byte 数组。

 

2011年微博进行平台化改造过程中,业务提出了新的需求:在核心接口中增加了“判断两个用户的关系”的步骤,并增加了“双向关注”的概念。因此两个用户的关系存在四种状态:关注,粉丝,双向关注和无任何关系。为了高效的实现这个需求,平台引入了 Redis 来存储关系。平台使用 Redis 的 hash 来存储关系:key 依然是 uid.suffix,关注列表,粉丝列表及双向关注列表各自有一个不同的 suffix,value 是一个hash,field 是 touid,value 是 addTime。order by addTime 的功能则由 Service 内部 sort 实现。部分大V的粉丝列表可能很长,与产品人员的沟通协商后,将存储限定为“最新的5000个粉丝列表”。

 

需求实现:

  • 查询用户关注列表:hgetAll uid.following ,then sort
  • 查询用户粉丝列表:hgetAll uid.follower,then sort
  • 查询用户双向关注列表:hgetAll uid.bifollow,then sort
  • 判断两个用户关系:hget uidA.following uidB && hget uidB.following uidA

后来又增加了几个更复杂的需求:“我与他的共同关注列表”、“我关注的人  阅读全文...

密码保护:再见2013

十二月 27th, 2013 评论关闭

这是一篇受密码保护的文章。您需要提供访问密码:

密码:

阅读全文...

无觅相关文章插件,快速提升流量