究竟什么是REST服务器?一个老程序员的唠叨

说实话,每当我看到“REST服务器是什么”这种问题,脑袋里总会浮现出十几年前刚入行时,被一堆术语砸得晕头转向的样子,那时候不像现在,网上随便一搜就是铺天盖地的教程,我们那会儿,得自己啃英文文档,得翻墙去技术论坛里捡别人吃剩下的干货。
现在你们问“REST服务器”,多少有点初恋般的困惑,知道它重要,知道大家都在用,但真要让你说清楚它到底是个什么玩意儿,又觉得词穷,来,别急,我们不搞那些教科书式的定义,我试着用我理解的“人话”,把这个东西给你掰扯明白。
得纠正一个常见的误解:这个世界上并不存在一个叫“REST服务器”的硬件。
你买不到一台贴着“REST服务器”标签的机器,就像你买不到一台“身份证号码服务器”一样。“REST”是一个架构风格,或者说得更俗一点,它是一套设计规矩、一个江湖约定,一台机器,因为它遵守了REST这套规矩来对外提供服务,我们就叫它“RESTful的服务器”,或者简称REST服务器,重点不在“服务器”,在“REST”。
那REST这套规矩,到底是什么呢?

如果让我用一个词来概括它的核心精神,那就是——无状态。
别被“无状态”这三个字吓到,听起来很冷冰冰,我们换个说法,叫“记不住你是谁”,这就像一个金鱼只有7秒记忆的餐馆老板。
你想啊,传统的服务器,就像一个记性太好的管家,你跟他说:“给我倒杯水。”他去了,回来时还记得你,然后你又说:“加块冰。”他跑去厨房,回来还认得你,然后你再问:“上个月的账单是多少?”他挠挠头,得去翻他那个巨大的、记录了你所有言行举止的笔记本。
这个“笔记本”,就是服务器端的“会话状态(Session)”,它记住你什么时候来过、点了什么菜、穿什么颜色的衣服,这种模式有个巨大的问题:当客人多了,一个管家的笔记本记不住所有人,就得换更大的笔记本,或者雇更多管家,这些管家还得互相通气,共享那个笔记本,不然A管家记下的客人,B管家不认识,又得从头问一遍,这管理起来,成本高,风险大,容易乱。
REST服务器的规矩刚好相反,它就是个金鱼记忆的老板。

你跟REST服务器说:“给我倒杯水。”它给你倒完,就把你忘了,你再说:“加块冰。”不好意思,它不记得你是谁了,你得重新说:“我是坐在3号桌,穿红衣服,刚才让你倒水的那个人,现在给我加块冰。” 你看,每一次请求,你都必须把自己所有的“状态信息”随身携带,服务器收到请求,读取你带来的信息,处理完,把结果还给你,叮”的一声,清零,你这个人就在它的记忆里消失了。
这就叫“无状态”。每一次HTTP请求,都包含了理解这个请求所需要的全部信息,服务器不依赖于任何在此之前请求所留下的上下文。
这样做有什么天大的好处呢?
第一,就是爽,超级爽。 还是那个餐馆的例子,因为老板记不住任何人,所以老板可以随时换人,今天1号服务员接待了你,他突然肚子疼下班了,2号服务员随便看了你递过来的纸条(也就是你发的请求),他完全知道你要干嘛,因为纸条上写得很清楚,这叫什么?这叫水平扩展,系统要应付双十一的大流量,很简单,多雇几个服务员(多加几台服务器)就行了,他们之间不需要复杂地同步那个该死的笔记本,那如果在一个有状态的老系统里,这就很麻烦,你得多花钱,去搞“会话复制”、“共享缓存”之类的复杂技术。
第二,清晰,超级清晰。 在REST的世界观里,服务器上的所有东西都是“资源(Resource)”,什么是资源?你的用户信息是一个资源,你发的一条微博是一个资源,这篇博客文章也是一个资源,每个资源都有一个唯一的标识符,那就是我们常说的URL。
https://api.example.com/users/12345 这个URL,就是代表“用户ID为12345的那个用户”这个资源。
https://api.example.com/orders/67890 这个URL,就是代表“订单ID为67890的那个订单”这个资源。
对一个资源,我们能做什么事呢?基本上就是“增删改查”这四件事,对应到HTTP协议里的四个方法:
GET:查看一个资源,比如GET /users/12345 就是获取这个用户的信息,这是安全的,不会改变任何东西。
POST:创建一个新资源,比如POST /users,带上一堆JSON数据,让服务器帮我创建一个新用户。
PUT (或PATCH):更新一个资源,比如PUT /users/12345,带上修改后的数据,把整个用户信息替换掉,PATCH则是部分更新。
DELETE:删除一个资源,比如DELETE /users/12345,就是把这个用户删掉。
你看,这么一映射,是不是特别清楚?任何操作,都可以被分解为:对什么资源(URL),做什么动作(HTTP方法),这比那些老系统里,搞一大堆奇怪的URL像addUser.do?action=create&type=normal 要优雅得多。
这也是REST的精髓之一:使用统一的接口,我不需要猜你这个URL是干嘛的,你一看GET 加URL,就知道是读;DELETE 加URL,就知道是删。
但说到这儿,我得给你泼盆冷水,理想很丰满,现实很骨感。
你在网上看到的,包括很多公司的所谓“RESTful API”,其实大部分都只是“看起来像REST”,或者叫“RESTish”,为什么?因为真正的REST还有一个更高级的要求,叫HATEOAS(Hypermedia As The Engine Of Application State),翻译过来就是“超媒体即应用状态引擎”。
这个词太吓人了,我换个说法,叫“返回的答案里就告诉你下一步怎么走”。
什么意思呢?假设你请求GET /users/12345,一个纯正的REST服务器返回给你的,除了这个用户的基本信息,还应该包含一堆链接,这些链接告诉你的客户端,下一步你可以做什么。
返回的JSON里除了{"name": "张三", "id": 12345},还可能包含:
{
"name": "张三",
"id": 12345,
"links": [
{
"rel": "self",
"href": "https://api.example.com/users/12345"
},
{
"rel": "friends",
"href": "https://api.example.com/users/12345/friends"
},
{
"rel": "orders",
"href": "https://api.example.com/users/12345/orders"
}
]
}看到没?服务器告诉你,你不仅可以看这个用户的信息,你还可以通过这个链接去访问他的朋友列表和订单列表,你的客户端不需要事先写死那些URL,而是像逛超市一样,跟着服务器给的指示牌走就行了,这样,服务器端的URL结构改变了,只要它返回的“指示牌”也跟着变,你的客户端就完全不需要修改代码,因为它永远是从上一个请求的返回里,去寻找下一个请求的路径。
这才是REST设计的初衷,一个真正动态的、可自描述的系统。但在现实世界里,99%的人嫌麻烦,不会这么做,大家更习惯把URL写死在文档里,然后让客户端程序员去硬编码,绝大多数号称RESTful的API,其实都只做到了资源化(URL)和统一接口(GET/POST/PUT/DELETE),而放弃了HATEOAS,这当然也是一种务实的妥协,毕竟我们追求的是解决问题,而不是追求完美的理论教条。
那为什么REST这玩意儿在2000年被Roy Fielding提出后,会迅速流行起来,并取代了SOAP这种更重量级、更复杂的协议呢?
答案就两个词:简单 和灵活。
在SOAP时代,你要调用一个远程服务,得搞一个庞大的XML信封,写一堆复杂的WSDL(Web Services Description Language)描述文件,客户端和服务端的代码生成都要经过严格的工具链,那感觉就像,你只是想跟邻居打个招呼,却必须先写一封正式的国书,盖上国玺,走一遍外交部流程。
而REST,它直接建立在HTTP这个已经非常成熟和普遍的基础协议之上,HTTP协议的GET、POST、PUT、DELETE,加上URL,加上常见的JSON或XML作为数据格式,基本上你的前端工程师(浏览器端)、后端工程师、甚至APP工程师,都能快速理解和使用,它把复杂的分布式系统问题,简化为了我们每天在浏览器里浏览网页的行为模式——看网页(GET)、填表单提交(POST)、修改页面(PUT/POST)、删除页面(DELETE)。
这种“向下兼容”的智慧,是它成功的关键,它没有发明新的、更复杂的协议,而是把现有的、经过千锤百炼的HTTP协议用到了极致。
现在的你,如果要设计一个API,是选择REST还是GraphQL还是gRPC?这取决于你的场景,但无论如何,理解REST的核心思想——无状态、资源化、统一接口,依然是理解现代互联网架构的基石。
就像学开车,不一定非要开手动挡,但理解了手动挡的离合器和换挡逻辑,你开自动挡时会理解得更深,也知道那些“自动驾驶”辅助功能是在帮你做什么。
回到最初的问题,REST服务器是什么?它不是一种硬件,也不是一个具体的产品,它是一套设计哲学,它告诉构建和维护服务器的人们:别什么都往服务器上堆,让服务器轻松点,它只做一件事——根据你发来的请求,对资源进行操作,并把结果还给你,别记着我,每次重新认识。
这很酷,不是吗?让复杂的世界变得简单一点,哪怕只是那么一小会儿。
文章摘自:https://idc.huochengrm.cn/js/27506.html
评论