程序员必须知道的API接口常识写在上面。到现在我还清楚的记得电商教程是怎么定义接口的:不管是增删改查,还是带参数查询,都是POST请求,比如下面这样:修改用户收货地址POST/xxx-mall/cart/update_address现在好像都是POST请求,为了方便传递参数。那时我还没有API接口需要设计的意识。学习过类似教程的朋友应该明白了。老师敲了一行代码,学生跟着敲。如果没人提这件事,进入团队正式工作后很容易出丑……(笔者亲身经历过,捂脸)本文PPT课上不使用官方口音打算介绍一下API接口的概念,我想用聊天的方式把现有的一顶顶和API相关的小技巧分享给大家。文章将分为五个小部分:认识API接口API限流API版本管理API权限和安全API团队间互通注意事项:这是一篇含蓄罗列了很多知识点的文章,大家可以按需深入搜索进一步学习。当年之所以热衷于看这样的文章,是因为学习一个知识点只需要时间。对于学生来说,时间不是问题。问题是不知道学哪个方向T_T。这篇文章希望通过一系列的讲座,梳理一下目前所学的API知识体系,希望在梳理的同时对大家有所帮助。1、第一时间了解API接口。记得刚学web开发的时候,后端框架相关的教程基本都是教学生写渲染模板(不分语言),也就是说后端返回整个网页的数据,而浏览器只负责渲染。一般这类模板会在后台对应一个路由。比如前端要登录一个页面查看用户信息,url中输入的访问地址会是这样:https://ajun24.com/user当时我还以为是这样的路由地址是API概念的全部……值得一提的是,大部分后端教程都会简单的教前端,而前端的补充教程中有一个必学的知识点——结束,称为:AJAX。老师很可能会演示如何使用AJAX技术,写一个小demo,告诉大家可以通过这种方式在页面上发送异步请求。这个技术请求的后台接口一般不会跳转或者返回一个html页面,大概率会返回一段json数据。我一直对这样的接口和返回页面数据的接口很着迷。直到实习结束后才明白什么叫前后端分离开发。。。不过为了教学方便,大概率会以渲染的形式来讲解完整的项目模板。毕竟只在一个系统中编写代码演示要方便得多。那年我就是这样完成我的第一个项目的。虽然我对如何构建一个软件系统有一个整体的了解,但是我对API设计的理解却很薄弱。其实我在学习AJAX的知识点的时候就在想:有没有可能用类似AJAX的方式获取所有的数据呢?这样会感觉更方便。后来实习的时候,前端同学跟我说:开发前需要先定义好API。当然,他也告诉我:你不能用POST请求来删除一个东西。图片(捂脸)后来导师提醒我:你需要了解如何设计REST风格的API。自从那次出丑之后,我明白了一件事,要敢于把自己的缺点暴露给那些愿意指出你的人。就像我们上大学的时候,最好找一份实习。每一次拒绝,每一次offer,都会告诉我们这个社会需要什么样的人才,什么样的技能可以帮助我们找到工作。.在正式面试的情况下,或许我们应该更清楚地向面试官介绍什么是表现层的状态转换,但在这篇文章中,我想把REST风格的API称为更容易让人理解的API。你会发现一个符合REST风格的API很容易让别人知道调用这个API可以做什么,例如:GET/users#查询用户信息PATCH/users/{user_id}#根据以下信息更新一个用户的信息id,只是部分客户端提交的数据是按照约定写的。编写API就像说IT领域的行话。大家只要看到你的API,就知道你能提供什么样的服务。有的同学可能会疑惑为什么要遵守规则呢?如果我们负责的系统只对接同事的系统,那么当我们约定API的时候,只需要打个招呼,或者简单的在聊天工具上说明一下,甚至可能连文档都没有。但是在很多情况下,我们的系统会被很多其他系统调用。想象一下我们调用云厂商API的场景:别人的工程师很可能不是我们的微信好友。大多数时候,没有人站在我们这边。手把手告诉我们如何调用API。这时候如果要调用对方提供的API,就得阅读对方提供的API文档。如果对方的API没有按照规范来定义,那么API文档绝对是难读如天书。读天书的痛苦,保证每个人经历过一次就难以忘怀。一个好的API文档一般就像一个工具手册,没有太多的学习成本,否则别人下次可能就不会使用我们的服务了。Picture所以先系统的学习API定义约定,然后编写API文档,再根据设计进行开发是一个比较好的研发过程。接下来的问题是,了解了API规范后,如何写出好的API文档呢?众所周知,编写文档对于程序员来说是一件非常痛苦的事情。一想到学习编写专业API文档的成本,真是令人望而却步。这时候我们就可以借助一些自动化工具来辅助我们完成一份优秀的API文档。比如我们可以使用swagger,它可以通过我们的代码自动生成API文档。最近看到很多基于API的研发测试集成产品和平台。我觉得一站式、流水线式的研发管理是未来的趋势!2、关于API限流API写完后会被调用,但是由于电脑&网络系统的限制,我们的API接口不能无限调用。可以在网上选择更专业的API文档。比如你看一下云厂商提供的API,基本都会看到一个接口调用频率限制。例如,单个用户的调用频率为每秒30次。所以我们在设计API的时候,限流是我们不得不考虑的事情(不是内部玩笑话,一般是指面向用户的系统)。在设计限流之前,我们首先要知道我们系统的瓶颈。假设我们的API纯粹调用了我们自己的技术组件,比如数据库,消息队列等中间件。这时候我们可以通过压力测试知道一个接口的最大承载能力;假设我们的系统是一个中间系统,需要依赖其他系统的接口来完成业务,那么此时基于木桶原则,其他业务系统访问我们接口的频率就会受到限制。了解了自己项目的访问瓶颈之后,就需要考虑自己系统的架构了。假设我们的系统是单机部署:此时我们只需要一个简单的令牌桶算法就可以完成限流。下面是一个卡桶算法实现的最小命令Demo:简单解释:实现一个固定容量的桶,按照一定的频率向桶中放入令牌,直到桶满为止。如果桶中没有令牌,按照原先的概念不方便实现等待将令牌放入令牌桶的操作,所以在取令牌的时候进行放入令牌的步骤。通过当前提币时间减去上次提币时间差,我们就可以知道这段时间加了多少代币。classTokenBucket(object):#rate是令牌桶产生令牌的速率,capacity是令牌桶产生令牌的速率def__init__(self,rate,capacity):self._rate=rateself._capacity=容量自。_current_amount=0self._last_consume_time=int(time.time())#token_amount是执行一次操作需要的token数量defconsume(self,token_amount):#rate乘以时间差得到token的增量increment=(int(time.time())-self._last_consume_time)*self._rate时间差乘以速率得到token增量self._current_amount=min(increment+self._current_amount,self._capacity)#不允许iftoken数量不够Operationiftoken_amount>self._current_amount:returnFalse#更新上次操作时间self._last_consume_time=int(time.time())#结算当前token数量self._current_amount-=token_amountreturnTrue但是在实际工作中,我们部署单体架构的机会并不多。现在的大公司都建立了自己的云生态,业务部门上云后可以快速扩张和收缩。所以我们的系统很可能是集群部署的,用户请求通过代理层。对每个后端节点进行负载均衡:此时上面15行代码显然不符合我们的分布式系统架构,我们不得不考虑更复杂的限流算法(这里不是指令卡桶算法不合适,但是令牌桶算法的实现需要改进),当然这个实现很可能会放在代理层,并且它没有在我们的业务层中实现。大家可以上网看看主流云厂商提供的云服务。很多都会提供API网关,对应我们上面说的代理层。如果一个公司有统一的API网关服务,或者类似的代理服务,业务部门在API限流上可以省去很多精力。我有时候想,当越来越多的中小企业基于巨头云厂商来搭建业务的时候,大家考虑的技术问题会越来越少,越来越关注业务。这是好事还是坏事?羊毛布?3、关于API版本管理介绍完API和限流的基础知识,接下来说说业务相关的API版本管理。在真正接触业务之前,我认为只有软件需要进行版本控制。为什么API也需要版本控制?其实原理是一样的。软件会根据需要不断迭代版本,API也会迭代版本。但是本着开闭的原则,为了不影响之前的业务,我们最好不要改动原有的API。所以我们在设计API的时候,可以指定版本号,比如上面的例子:GET/users#查询用户信息可以统一定义为:GET/api/v1/users#查询用户信息假设有第二个这个接口的版本,我们可以通过版本号来区分:GET/api/v2/users#查询用户详情如果我是两年前,可能对API版本管理不感兴趣,但是大家代入自己就可以理解了以下场景是的:例如,我们的产品允许我们创建一个新的查询用户API,假设我们没有定义版本号,因为/users路由已经在使用中,我们必须定义一个新的:GET/get_user_info#查询用户信息新接口含义与旧接口类似。如果我们一直在负责这个系统,那还好说(心里有不同的版本)但是如果这个系统换成另一个继任者,当他面对大量意义相似的接口时4.关于API权限和security接下来,让我们考虑API权限和安全问题。当初我还是初学者的时候,完全没有API接口权限的概念。老师为了快速教会我们开发系统,设计了很多接口,完全裸露。如果一点点相关知识都不懂,很容易给人一种工作不周全的感觉。在实际生产中,没有权限是无法查看接口的。如果我们的系统暴露在公网,没有进行权限检查,系统很可能很快就会挂掉;更严格。关于权限验证,个人暂时分为三个维度,可能对应三种业务类型:第一种是直接给IP设置白名单,比较适合内部系统,客户端有限且固定;二是设置权限验证流程,比如使用Token认证,多用于ToB业务。在云供应商处注册帐户后,您基本上会得到一对密钥。后续的API调用一般需要根据key进行鉴权;三是通过用户登录判断权限,多用于ToC业务。比如我们登录京东,就需要一个账号登录淘宝。如果您不登录,则无法访问购物车和其他页面。值得一提的是,权限设计是知识的另一个维度。除了第一个维度之外,后两者其实可以独立形成一个系统。比如公司的用户管理系统、集中权限认证系统等。权限验证关系到公司财产安全,不容忽视。很多时候,我们甚至需要在API设计层面考虑安全问题。再举商城的例子,比如登录后获取用户购物车的订单,API很可能会这样设计:GET/users/287435/orders,但这未必是明智的选择直接暴露用户ID,可能被不法分子利用,我们可以用另一种方法,比如下面的方法来代替:GET/users/me/orders总而言之,除了参考规范,API的设计还需要根据自身业务情况做进一步的安全考虑。5.关于API团队间通信是一个扩展性的话题。我相信每个人都觉得我们处在一个数据时代。我们的个人信息,包括各种行为偏好,都存储在各个互联网公司的数据仓库中。企业可能比我们更了解我们,互联网上有很多与数据资产相关的话题。既然数据被比作资产,资产流动性是一个经久不衰的话题,各种数据的开放性也备受关注。数据的对外开放,必然涉及到API接口。当然,作为一个小码农,我的眼界极其有限,很难从更高的层面去谈企业数据问题。但是在工作中,其他业务团队提出调用自己负责的项目的API接口时,也需要多方面的考虑。本文列出了个人在技术上会考虑的点。可以用三句话来概括:你能看懂我的API吗?不要炸毁我的API!API只能在获得许可的情况下使用!由于API的概念太大,能接触到的也只是一些皮毛,但时不时总结整理一下还是很有帮助的。
