构建你的长寿命的API第1部分:规范驱动的API开发

构建你的长寿命的API第1部分:规范驱动的API开发

         这篇文章是由MuleSoft的Mike Stowe在nginx.conf 2016公布的演示文稿改编的。第一部分重点是规范驱动的API开发。

第二部分讨论的最佳实践。你能够查看完整的呈现的记录的YouTube。详细信息例如以下: 

0:00 介绍 

1:52 API正在改变世界 

2:32 API正在连接一切 

3:36 API应该是持久的 

4:01 构建一个持久的API的5个步骤 

4:38 从长计议 

6:03 你的API是契约 

6:39 细致想清楚 

7:36 谁将使用你的API? 

8:40 什么是你的API的目的? 

9:41 列出你的用户可能须要做什么 

10:53 你正在建立什么类型的API? 

11:43 SOAP vs RPC vs REST 

12:34 你理解REST约束吗? 

13:42 大多数API不是RESTful 

14:55 为长期构建 

15:20 版本号控制是必要的邪恶 

17:51 什么时候须要版本号 

18:35 什么时候不须要版本号 

19:54 版本号控制不会导致糟糕的设计 

21:12 使用规范驱动开发 

22:00 混合方法 

23:11 敏捷设计周期 

24:36 今天的一些API规范 

25:05 RAML长处 

27:25 RAML是什么样子的? 

28:33 规范是 Blueprint 

0:00介绍 
      迈克•斯托:今天我们将谈论构建你的长寿命的API。在过去的十年里,我已经有构建和使用API的机会,同一时候发现了几个不同的事情。 
         首先是构建API实际上非常easy。这真的不是那么难写的代码,或者使用框架比方Grape、Rails API、Jersey、Apigility,或者其它的框架。

我意识到的第二件事是。人们并不擅长制作持久的API。让我问大家一个问题:在这里有多少人使用了一个API已经被破坏?所以我们都有相同的痛点。 
         这次谈话的重点是,我们怎样才干使一个API变得持久,为什么要变得持久,怎样处理API的版本号问题,以及我们怎样可以确保我们构建什么样API值得我们的用户会喜欢。所以从长远来看。它使得我们不会花费很多其它的钱用于开发或者支持。 
         我们不打算潜入了大量的代码。相反。我们将专注于原则。最佳实践,以及我们怎样建立一个更有效的方法。

 
1:52 API正在改变世界


        我想公平地说:API正在改变世界。假设你以前使用过智能手机,或者即使你以前开过车。你可能已经使用了API。今天有超过15000公共API 在ProgrammableWeb站点上,它们连接各种各样的设备,但这仅仅是冰山一角。


        假设你想想看,有几十万甚至上百万的API, 连接着mobile apps,以及用于商业用途连接部门机构。 
2:32 API正在连接一切


         今天,API连接了非常多不同的东西。

显然,他们正在连接我们的移动应用程序,以及连接我们的企业架构,同一时候也连接我的手机与手表,如Apple Watch和Android手表、眼镜、汽车、冰箱、恒温器、家用机器人等等。


        想一下,全部的东西正在被 API连接着,这是多么重要。 
        想象一下,在你的家里有家庭安全系统,但最糟糕的事情可能发生:有人闯入你的房子。但警报開始关闭,然后说“须要更新”(它无法通知警察,由于API已过期)。这不是一件好事情。

 
        假设我们了解微服务,我们想要做的最后一件事是部署700微服务。都依赖于一个API,可是这个API被破坏了——我们要回去更新700微服务,它们可能须要又一次进行组成。 
3:36 API应该是持久的


         为了让API更好的工作,为了让物联网更好工作。为了使微服务更好工作,它们须要的API是持久的。


        不仅如此,版本号变动或更改你的API的代价是十分昂贵的。这不仅仅是你去说:“我们要重建我们的API或重构我们的代码”,也关系到全部用户或者公司的各部门,由于他们依赖这个API。

 
4:01构建一个持久的API的5个步骤 
        值得庆幸的是使用五个简单的步骤。就能够构建持久的API。


        第一步是拥有一个长期的思维模式。这听起来像是常识,但非常多人会说:“我们要建立这个API,我们要得到它在那里,我们得到的反馈。然后我们将版本号控制它“,可是实际上从来没有这么工作过。

第二步了解你正在建设什么。

它似乎也是常识,但大多数API是非持久地开发。没有真正了解什么是实际上他们须要构建。第三步利用规范驱动的开发,我们将后面谈到。第四步纳入最佳实践。然后反复步骤1到4。

 
4:38从长计议


        你的API是契约。我们忘记了,不像一个敏捷的Web应用程序——我们能够说,“我们将启动它。然后我们能够进行更改“——你不能更改你的API。否则会影响你的用户,造成他们的系统挂掉。版本号控制也不是解决方式。 
        我最喜欢的长期思考的理由是。你可能真的存在非常糟糕的长期设计。

你可能会觉得你擅长设计,但让我问你:你以前看过你的代码一年后。说:“这是最惊人的事情。我不会改变不论什么东西?我们真的善于在短期内解决问题,但不是长期的。为了使API设计看起来更加安全,你能够支付一点点很多其它如今或很多其它更晚。所以你须要考虑事情。 
        思维模式就是一切。

你不会希望一个团队走向一场篮球比赛,“我们要输了。我们会输。”由于非常可能,他们不会赢。同理,API设计也是这样。

 
6:03你的API是契约


         你的API是契约。我们常常忘记。当我们做出改变(破坏旧功能)时,我们正在夺去消费者赚钱的能力。

当我们改变我们的API,我们的客户或我们公司的其它部门必须说:“等等,我不得不停止我做的一切。回去和解决的事情,由于你打破了”。

这意味着他们不会加入新功能,他们不会赚很多其它的钱,他们肯定不会支付你很多其它的钱,由于他们正在努力解决的东西。而不是获得新的客户。 
6:39细致想清楚


        在构建API之前,你必须考虑你的API的每一个方面。这些方面可能看起来像基本问题和常识,但他们错过了非常多。 
         你的API是为了谁?你正在建立什么类型的API?你将怎样维护你的API?非常多公司都说:“看,我们将要构建一个API,推出它。这就是它。”我回答你。这不是它。你必须维护它。它们将是安全补丁。 
        你怎样记录你的API?你要有一个完整的文档团队吗?你要使用Swagger控制台吗?你使用RAML吗?你将怎样让用户与你的API进行互动?你将怎样处理诸如身份验证、配置、限制、安全风险、DDoS攻击、开发者无意中使用无限循环等小事?你要怎样管理支持? 
        这些不必是真正艰难的讨论,但你必须有。你的支持方法可能是有一个专门的API支持团队,或者有project师将提供支持。或有一个社区论坛。或者[你甚至能够说]“我们真的不是投资在API。所以祝你好运; 假设他们须要支持,他们能够弄清楚”。 
7:36谁将使用你的API?


        你的终于用户是谁?它会是如今的客户吗?它会是商业伙伴吗?第三方服务或开发人员?这是非常重要的回答,由于在你能够构建之前,你必须了解他们是谁,他们须要什么。他们须要訪问哪些操作?这意味着从第一天開始涉及你的用户。 
        当我開始作为一个网络开发人员,我是一个菜鸟。我有这个摄影client。她告诉我,“我在寻找一个漂亮的摄影站点。我想要这样的类型的图像,这样的类型的字体。”她给了我的规格。我出去了,我建立了最漂亮的摄影站点,在我看来。我把它送给她,她看着它。说:“这是什么?你使用深色。我做婚纱摄影,我想要淡色。你使用这个图像,我想要那个图像。你使用这样的字体,我想要那个字体。我把我的心倒入这个站点,但结果是她讨厌它。由于我没有让她參与设计过程。

我没有问她。她想要什么样子的。 API设计也是这个道理。 
8:40你的API的目的是什么?


        在MuleSoft时候,我们处理非常多企业客户,他们说,“嘿。我们想要一个API。”我们回答,“嗯,这是伟大的。但你的API是什么?”他们说,“我们将与世界分享我们的服务和数据。“所以我们问他们,”好吧,但他们想要什么数据?他们将要訪问什么服务?他们将怎样与你现有的服务或其它API进行交互?他们怎样与来自第三方的其它API或服务进行交互。他们可能须要与你的服务一起使用?他们须要什么行动来处理? 
         一个我们碰到的陷阱是说。“我们要建立的REST API。我们要做的CRUD,我们要做的HTTP方法。”我们開始思考POST,PUT,PATCH,DELETE立即。

退一步说。“他们(我们的客户)须要可以加入用户。编辑用户。可能检索password。发送消息”。

 
         这下一点是为房间里的project师。由于让我们老实说,我们是可怕的:仅仅做必要的。不要喜欢你的API。 
9:41列出你的用户须要做什么


        这是一个很easy的方法来组织一个API。我们仅仅是说。“我们要实用户,然后你就行创建一个用户。编辑用户等等。

我们将有一个消息系统; 这里是我们的消息。和我们须要的行动。

我们将有产品,所以我们须要可以审查一个产品。加入一个产品到购物车。我们要有一个购物车,所以我们须要建立一个结帐。 
        当我们经历这个过程。一些事情開始发生。你注意到的第一件事是,我们已经定义了我们的资源,甚至没有尝试。我们有一切为用户的东西,这是用户的资源。

全部这些东西的消息[是]的信息资源。 
你会注意到的还有一件事是,我们有反复。我们有信息的用户。并发送一条消息。那么,它可能没有不论什么意义实际上有一个专门的资源下,用户发送一条消息,这似乎多余。 
          我们所做的是有机会来看看这个问题,“哪里不属于?”我们能够说。“ 发送消息和邮件用户在所属的消息 ”。并且还开发这些两者之间的关系纽带。所以。不要回头说,“让我们创建一个超媒体地图并将全部这些事情联系在一起”事实之后。我们已经创建了一个超媒体地图。我们已经知道,当我们拉起一个用户时。我们须要向他们发送消息的能力,这将是一个链接。

 
10:53你正在建立什么类型的API?


        你正在建立什么类型的API?你要构建一个REST API,一个部分REST API,SOAP,RPC?让我问你:什么是正确的类型的API构建?答案是:它取决于它的依赖。 
        非常多人会说“REST!

”假设你是一个大型企业,而且全部的客户都是传统客户,他们没有准备好REST API。但他们须要SOAP,由于他们有SOAP库,它可能使感觉使用SOAP。

这就是为什么Salesforce最长时间维护SOAP API和REST API。由于这是他们的客户要求。

 
        为什么要以该格式构建API?你理解你选择的格式的优缺点吗?对你的开发时间意味着什么?对用户的可用性意味着什么?长寿是什么意思?它将怎样影响你长期? 
11:43 SOAP vs RPC vs REST


         对于SOAP。我们能够说,“哦,SOAP,这是过时了。这是这个庞大的SOAP封装须要SOAP库。它仅仅是XML。“可是SOAP有WSDL,当中有些人喜欢,它能够是状态或无状态,这是一种不错的。

 
         RPC,在还有一方面,是真的,真的好用。它返回统一格式- JSON-RPC或XML-RPC -但真的没有上线管道得到它。我把这个网址,我得到这个回来,并做了GET或者POST,这就是它。 
         最后还有REST。它具有全部这些巨大的利益,但有一些注意事项用它。这对于开发者来说也有点难度,特别是当你開始整合超媒体等东西时。由于对链接进行硬编码总是比实际动态使用更easy。 
12:34你了解REST约束吗?


        如果你要构建REST API。由于你的目标是实现长久,灵活和敏捷。你真的明确什么是REST吗?你是否明确client和server必须可以单独演进,你对移动设备所做的更改不应该影响server,或者client不应该影响server? 
        你明确REST是无状态的吗?你不在server端存储状态。当然,client能够存储状态。可是你不保留他们正在做的调用的记录。

所以假设我在这里连续两个电话,你不记得第一个电话。你不在乎第一个电话。

你自己接受每一个电话。 
        它是可缓存的。这意味着你不仅在你的最后提供缓存,但你告诉你的用户,“这里是怎样缓存此页面”或“这里是你能够做什么缓存此页面,这里的时间限制”或 ”这将被缓存在全部层”。 
13:42大多数API不是RESTful

 
        创建REST理论的Roy Fielding注意到有一天没有人使用超媒体。

他继续问:“有手冊坏了吗?文档是否错误?我做错了什么,使它不清楚。假设它没有超媒体。它不是REST? 
这是否意味着你必须构建一个完整的。全然RESTful API?绝对不。

你必须构建满足你需求的API,可是你须要了解为什么。 
        有一个公司正在构建一个API的样例,他们说。“我们要构建REST。

”他们開始使用它,然后随着时间的推进,非常快他们说,“嗯,我们将让他们给我们发送HTML,然后我们将发送他们的JSON。”然后是,“我们要做POST,但他们将通过查询字符串发送数据。

他们開始调整事情,由于他们觉得。“这将使事情更easy和更好的为我们的用户”。没有理解他们正在须要什么的构建API。

他们实际上创建了很多其它的问题。须要很多其它的迭代,并花了非常多钱试图构建这个API。 
         再次,了解为什么要构建一种类型的API而不是还有一种。假设你不这么做,你将付出很多其它的道路,终于有一个API是一种混合了全部的东西,是不会工作。 
14:55为长期构建 
        这也意味着构建你的API超越今天。这是我们遇到的挑战。今天我们说。“这是API,这些是我们须要的,这是我们的平台”。

这是伟大的。但你的平台二年后将是什么样呢?三年?五年?


       我们真的,真的非常好的短期设计。但正如Roy Fielding所说,我们对长期设计感到恐惧。 
15:20版本号化是一个必要的邪恶


         这使我们进行版本号控制。版本号化是一个必要的邪恶。在短期内。非常easy说“我们要版本号。它会是伟大的”。同一时候,版本号也有缺点。


        首先,版本号控制会产生向后兼容性,这意味着当你升级API时。依赖于你的API的应用程序将会断开。当它们遭到破坏,你会听到投诉。 
         第二是有多个服务须要维护和多个系统须要支持。你能够说,“不,不,不 —— 这不是它的工作原理。我们将弃用这个API。我们不会再支持它了。我们要公布一个新的API”。 
嗯,这听起来非常大的理论。直到有一个安全风险,你必须修补这个安全漏洞。

或者你得到那个一百万美元的客户说:“你知道吗?实际上。我们坚持使用旧的API,我们不能升级,我们须要这个功能“或者公司的还有一个部门说”我们须要它”。

 
         在MuleSoft之前,我有机会作为Constant Contact的开发人员传道人,我的整个工作是让人们从版本号1升级到版本号2。在这一年我在那里,我得到了,我想四人升级他们的API。

他们觉得。“这一个工作。

为什么我们应该回去花钱来解决没有被破坏的东西? 
         还有一个问题是版本号控制在开发者之间造成混乱。

 
         在Constant Contact,有一天我打电话,那个行上的绅士说:“我有一个问题:API不工作。”我问他:“你使用什么版本号的API?”他说,你的。

 
         好吧,没问题。有时人们会困惑他们使用的是哪个版本号。所以我挖的更深,“它是怎样工作的?”他回答说:“嗯。我送POST,我得到的数据了。”我说:“好吧。你得到的XML或JSON?”他回答:“是的“。事实证明,他接管了还有一个刚刚说“这没有成功”的开发者。他呼吁找出为什么它不工作,但他没有做家庭作业,他不知道我们使用什么版本号的API。

它花了大约20分钟仅仅是要弄清楚他是什么版本号。

原来他是在版本号2,但他须要的功能是版本号1。这真的把他气坏啦。由于他们刚刚从版本号1升级到版本号2。 
        因此。开发者的採用差点儿是不可能的; 你终于会造成混乱,不得不支持新的和旧的API。 
17:51什么时候你须要版本号


       当你具有向后不兼容的平台更改时,你须要对API进行版本号化。

在这样的情况下。更改API以反映你如今正在做的新事物可能是有意义的。

或者,假设你曾经是一家汽车店,如今你是一家面包店。更改你的API是有意义的。 
         第二个实例是当你的API不再可扩展时。换句话说。你搞砸了。

你觉得你有完美的API,但你不断变化和扩展,不断变化和改进,然后你被卡住,如今你有麻烦。

 
        最后,假设你的规格是过时的。或许[你的客户]如今想要JSON,但你仍然使用SOAP与XML,所以你须要更新你的API。

 
18:35什么时候不须要版本号


        你不应该由于你加入新的端点或在响应中加入了其它数据而对API进行版本号化。有关于严格模式的论点。除非你正在做一些须要严格模式的事情。否则我会避免说“这是数据响应的严格模式”。 
        你不应该版本号,由于你改变了技术(你从Java到Ruby)。

或者假设你更改了应用程序服务。你应该可以更改代码。你应该可以更改你的服务。你应该可以更改依赖关系。而不会影响API的接口。 
        这是我们看到的还有一个挑战。顺便说一句。公司说“你能够基于你的数据库生成一个API。

我们将依据你的数据库名称创建API“。假设你创建一个独特的接口,那么实际上是能够的 -——假设你回去,你開始改变全部这些,并将它从数据库中解耦。

问题是。一旦你说“好吧,我们使用这个数据库。我们将移动到CRM“。

全部这些名称都是严格对齐到数据库。

相同的事情,假设你说“看,我们要有一个CRM,我们将通过我们的系统代表一个CRM。

”假设你使用特定的API或特定的系统和你的API的顶部紧密耦合,第二个你改变它们,破坏接口,这是打破了向后兼容性。 
19:54版本号控制不会导致糟糕的设计 

        版本号控制不能原谅可怜的设计。

这很,很重要的须要指出:版本号控制不是一个解决方式。它实际上可能在路上产生很多其它的问题。



        设计不佳的API将花费你远远,远远长于短期内可能给你带来的优点。

 
        我不自豪的一个故事是我有机会增加MuleSoft作为承包商工作,我们建立了这个API。我们花了六个月的时间编写代码,我们构建了这个完美的API。

它遵循全部最佳做法和最新标准; 代码是完美的。

然后经过六个月的工作,我们公布了这个API,三个星期后。我们意识到没有人使用它。

这是由于它不是最佳实践 ——我们有一个伟大的基于REST的API。这仅仅是由于它不能满足他们的须要。 
        我们花了接下来的三个月试图拯救这个API,试图解决它。可是我们最终最终把它扔掉了。

这是9到10个月的工作全然被抛弃,由于我们的API不能满足我们的客户的需求。全部由于我们没有花两个星期在開始问我们的用户。我们没有涉及我们的用户,了解他们的需求。

 
21:12使用规范驱动的开发


        我们可以避免的方法是使用一种叫做规范驱动开发。

 
         规范驱动开发的工作方式是我们首先要做的是在我们编写不论什么代码之前定义我们的API。我们还将引入设计模式和代码重用。我们对全部的应用程序这样做,所以为什么我们不使用我们的API设计? 
我们将模拟我们的API,并在我们编写单行代码之前获取用户的反馈。我们进行必要的更改。然后我们開始编码到规范,而不是偏离。我们的规范成为真理的源泉。 
         我们终于得到的是一个两阶段的敏捷过程。我们有一个敏捷设计过程来开发契约。然后是一个敏捷开发过程。你能够使用測试驱动开发来实际开发代码。

这样做的原因是,这样的方式没有进入代码或设计,我们没有測试。我们不确定。 
22:00混合方法


        所以首先我们要设计我们的API,模拟它。获得用户反馈。进行不论什么更改。測试它,确保它是完美的,然后我们将进入开发。 
        假设你遇到一个问题在开发中。你[实现]这是一个好主意在理论上。但它不工作会发生什么?你仅仅需回到设计过程。在你的測试中解决它。确保它的工作,測试它与用户,然后向前。你如今正在做的是创建一个API,不仅你的用户会喜欢,这将满足他们的需求。你要測试现实世界的用例,并且没有设计缺陷。

 
假设你不这样做。会发生什么?有一个社交媒体巨头的API,他们有一个资源。假设你想按年龄搜索。你必须把年龄在JSON中的一种方式。假设你想按位置搜索,这是一个全然不同的方式。

假设你想按年龄和位置搜索。它是第三种方式。

这不是由于某些依赖关系。

这是由于他们有不同的开发人员工作,他们没有意识到,他们有这个设置。

 
23:11敏捷设计周期


        敏捷设计周期是什么样的?设计API。在你模拟它后获取用户反馈。验证:“这是否满足我们的需求?它满足我们用户的需求吗?它是一个好的设计吗?“假设不是。继续工作,直到你的设计完好,然后当你准备好。进入编码阶段。 
         这里的目标是让我们的开发者无所畏惧地发展。我们不想让我们的开发者看看API。而且说“我们正在构建这个资源。并有你的问题。你是怎样设置这些数据的?你使用骆驼盒还是蛇盒?你使用一个PUT或一个PATCH来处理?数据是否包括在数据对象中?我们怎样区分这一点?“你不想遇到这些问题。

你不想要这些不一致,由于这些将导致你的API中断。

 
         这些问题花费代价是很昂贵的。我们说:“嘿,我们要构建这个API。我们要做的MVC,去更改代码。“和[发现]这是行不通的。好消息是今天,有几个新的规格,将使这很,很easy。还有一个很好的事情是这些同样的规格处理了你有很多其它的选择。所以。你不仅仅是在设计你的API,然后扔那了,就像我们做的瀑布 [发展]。 
         如今你有一个规范,能够用来生成你的文档。能够用来生成你的測试驱动开发測试。你有一个规范,能够用来创建SDK和client生成器。交互式场景,全部这些不同的东西。

 
24:36今天的一些API规范


        首先是RAML这是基于REST的API建模语言。

 
        第二个是IO Docs是由Mashery®。

这是我在I / O文档上的免责声明:我不会建议使用它,仅仅是由于TIBCO Mashery已经移向Swagger。所以他们真的不是维护I / O文档了。

 
        第三个是Swagger或OpenAPI Initiative,这是还有一个伟大的和很受欢迎的规格在那里。

 
        第四个 是API Blueprint。当涉及到的文档这是梦幻般的。同一时候它有一些伟大的工具。 
25:05 RAML长处


        我是RAML的粉丝的几个理由。使用RAML,你能够在几行文本中定义API。你能够看到你的API的样子。与API设计相比較。

你能够高速为你的API设计原型,供开发者试用。这意味着,通过点击button。你能够将此API发送到世界各地,并让你的开发者实时地尝试。 
        当你发现设计缺陷时,你能够高速做出调整和更改。

你能够轻松地记录你的API。你能够让开发者在线试用你的API。 
        RAML还有一大特点是一种叫做API Notebook。

而不是让你的开发商说[给你的客户]。“嘿,这里是我们的API。你觉得什么?“你能够发送给你的客户一个API Notebook,而且不须要编写不论什么小代码之外的代码,他们实际上能够測试你的API使用真实的用例。看看它是否满足他们的需求。 
        你能够让开发者在线试用你的API。

你能够让开发者通过API Notebook与其它API交互。然后,假设你想要SDK,client生成器,代码封装器、库、甚至你的构建API的框架。你能够通过开源社区生成这些。假设你正在为大众消费的SDK,可是。我真的会倾向于使用专业的公司像瘦APIMatic.io或REST United,由于不管你使用RAML或Swagger,非常多开源的client生成器是一种粗略。


        最重要的是,这是我更喜欢RAML超过Swagger的真正原因——你能够使用数据模型和设计模式。这意味着我们说“这些API看起来是我们想要的”。 
         你能够重用代码; 你能够拉入库,这意味着假设你有一个用户对象跨多个API共享,你能够以命名空间的方式拉。

你能够创建叠加层,因此你能够有一个规范,然后能够覆盖你的开发环境,你的QA环境。预发和生产[环境]等。 
         在这个样例中。我们希望有一个资源类型collection。对于我们的集合,我们将一次获得多个项目。

我们get有一个样例说明。

而不是一次重新地写了这一切。我们不得不说exampleCollection。在为我们拉取Rest。

 
27:25 RAML是什么样子?


        RAML是什么样子的?这是我为什么我喜欢RAML,顺便说一句。

RAML很具体,很复杂[不!

]。 
假设我想创建一个资源,我想打电话给一个资源播放列表,我将怎样定义在RAML文件中?/playlists,就像我在API上。假设我想加入一个GET到方式播放列表,我怎么想补充一点?get。假设我想有一个200反应,是什么状态代码我用它来把一个200回应?200。 
         所以,你能够看到它非常easy開始使用。RAML的优点在于,假设你是一个开发者。一个科技作家。或者CEO,无关紧要。你甚至能够让你的CEO改动你的API文档; 这取决于你。我不会去过多的深入RAML。但你想深入了解到很多其它请看raml.org。因此,总的来说。在构建API时,你将须要使用规范,不管是RAML还是Swagger。 
28:33规范是Blueprint


        但记住它不是一个“完毕”。

 
        一旦開始设计API,每次进行更改时。都要运行这些測试。这样做的原因是,你能够设计完美的基础,但假设你開始不对地构建在它的顶部。你缩短你的寿命。 
         这篇文章是由MuleSoft的Mike Stowe在nginx.conf 2016公布的演示文稿改编的。

第一部分重点是规范驱动的API开发。第二部分讨论的最佳实践(请看兴许章节)。你能够查看完整的呈现的记录的YouTube

posted @ 2017-08-15 21:27  claireyuancy  阅读(235)  评论(0编辑  收藏  举报