`
mypages
  • 浏览: 87828 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

网上关于rest连接状态实现的讨论

阅读更多

一个实用主义者的思考

April 10th, 2008 :: jackyz

这几天在考虑“虚构ajax 聊天室”的 uri 设计,想用 rest 风格来试试,时髦一下嘛。但对 rest 有很多地方其实都是一知半解,于是去问老朋友—— rest in action 上的 dlee 同学——拽着问了一大堆初级问题(见这里 ,以及这里 ),回头又啃了一些文章,也算是对 rest 进行了一番独立思考吧。想到整个过程对于其它人或许也有用,于是 blah 之。

需要说明的背景是:我是一个实用主义者。也就是说:搞开发不求纯粹但求实用。乃是在“多快好省”实现需求的前提下,顺便向“有风格”的方向靠,能靠上最好,靠不上拉倒。重点不在结果,而是在过程——也就是说,设计决策中,如果我选择了 free mobile phone ringtones | cricket free phone ringtones | 1600 nokia ringtones | madonna ringtones | free ringtones converter | cheap virgin mobile ringtones | free ringtones 3gforfree | mobile phone ringtones virgin | sprint pcs ringtones | free nokia mp3 ringtones | download free ringtones nokia | download free ringtones to cellular phone | free lg ringtones verizon wireless | get ringtones | free composer ringtones | gold mp3 ringtones | motorola ringtones | alltel free music ringtones | cingular free ringtones wireless | free boost mobile ringtones | rest ,那么借鉴的是什么,如果我选择了不遵循它,那么理由又是什么。另外一个需要说明的是,尽管这几天啃了不少 rest 的文章,但“每个人的心中都有一个 xxx”(请自行将 xxx 替换为你喜欢的任何词语),加之对 rest 可能仍未吃透,所以大家凑合着看,或许某天夜里悟透了,爬起来把这里的思考全都推倒重来亦无不可能(免责声明了啊)。如果发现有错误,那太好了,欢迎之 至,请随时指出。

下面就是“虚构 ajax 聊天室”的 rest 设计之旅。

 

虚构 ajax 聊天室?

搞了这么多年 web 开发,“聊天室”一直是我最 favorite 的应用,闲起来就会翻将出来,在脑子里面虚构一遍,从最初的“隐藏 iframe ”到“server push”,乃至“the google way”(有兴趣可以看这里 )……, 可谓常见常新。这么丰富多彩的实现方式,见证了历代程序员“克服 http 无连接缺陷”的智慧,让人每次想来都能从中获得不少乐趣。但自 ajax 大行其道以来,众多拿“写一个 ajax 聊天室”作为例子的书出得满大街都是,而最近 google application engine 的推出也未免俗,又拿了个 ajax 聊天室当作教材。搞得我也开始有点审美疲劳。但,一则“ rest 和 comet 是否存在冲突 ”的讨论又重新引起了我对于这个“上古题材”的兴趣。可不是么,传说中 comet 正是聊天这类应用的大救星,如果它和 rest 冲突,那么“有 rest+comet 加持的 ajax 超炫聊天室”岂不是要梦想落空?悬念啊,我喜欢。

需求很简单,就不啰嗦了。

最初的 rest 幻想

rest 是 Representational State Transfer 的缩写(表述性状态转移?),意味着 State 的 Transfer 是 Representational 的,也就是说,状态的转移是表述性的(至少是可见的)。大致来说,如果把一个请求看作是一个表述性的句子(也就是语言中“主谓宾定状补”的元素),那么 rest 的主张就是让大家用 http 协议标准之内的东西来表达这些东西。具体来说,主语是 http auth,谓语是 http method ,宾语是 uri (俺语法差,错了请指出),定状补这些一般往 uri 或者 content-type 中塞。

rest 要求 http request 本身就是一个完整的“句子”,它已经包含为其提供服务所需的全部信息(完备性),这么做的好处是,收到这个 request 的任何一个 web server 都能在无需额外支持的情况下独立对此 request 提供服务。比如说,原 web server down 掉了,下一个 request 由中间层转给了备份的 web server ,此时备份 web server 要能完成服务,而不需要任何之前“状态”的支持——这很让人想起所谓的“无共享架构 ”(这个词对于 erlang guy 来说再亲切没有了)。从这个意义上理解,rest 反对 session 和 cookie(对于这个我有点怀疑)确实很好理解。

理想情况下,这么设计:

列表用户:

http_auth: {auth_token}
content-type: text/javascript
LISTUSER /chat/{room}/

接收消息:

http_auth: {auth_token}
content-type: text/javascript
RECIVE /chat/{room}/

发送消息:

http_auth: {auth_token}
content-type: text/javascript
SEND /chat/{room}/

to={the_receiver}&face={the_face}&text={what_i_said}

要点在于:
1.因为 comet (在保持的长连接上不断向客户端发送 script 的方式)操作的语义不可见,所以改成 xhr 不断刷新的实现方式(先不考虑负载),以符合 rest (这也可以是某种 comet ,参照这篇 )。
2.自定义 LISTUSER, RECEIVE 和 SEND http 动词,分别对应列表用户,发送和接收动作。
3.聊天室的 uri 定义为 /chat/{room} 这个资源名,各个操作都在这个资源上进行,这个 uri 看起来也很简洁清晰。
4.使用 content-type 表达结果为 json 数据

现实问题

rest 描述的未来相当美好,但是(总是有个讨厌的但是),在实用主义者的角度,会发现几个问题。

1. 主语放在哪?
我们都知道 http 标准的 basic authentication 是个摆设。它其实就是 username 和 password 经过 base64 之后放在 header 里面。如果不配合 https 随时随地的在每一个 request 中传递这些玩意,恐怕是很雷人的一件事。而我们又知道 https 也是一个头疼的东西,只有那几个“拿钱发证”机构的根证书是内置在浏览器中的,自己搞的证书能用,但也能把人烦死。而且,对于聊天室这样的应用来说,如何 说服游客让它们来参观时也能接受一个莫名的 basic authentication 窗口,同样也是很让人挠头的问题。你知道,我是一个实用主义者,这个问题让我很想念 cookie (把主语放在 uri 之中亦无不可,但一般主语涉及验证,可以想象,放入了主语的 uri 会是一个难看的 uri,俺从审美上 pass 掉这个方案了)。

2. 谓语不够用?
rest 实际上只有两个谓语:幂等(迷瞪)的GET 和 不幂等(不迷瞪)的POST (同样不迷瞪的 PUT 和 DELETE 太有充数的嫌疑了)。如果有人不同意我上面的话,那我可以更正。但,即便是算上了 PUT 和 DELETE ,总共也只有 4 个动词,如果一个语言只有 4 个动词就好意思说自己是用来“表述语义”的,我会觉得很寒。好在 rest 也了解这是一个问题。所以它有这么两种解决方案:A.增加动词,象 webdav 一样,但这么做显然有个问题,自定义的 http 动词其设备的通过性是个问题,再有就是大家都来增加新的 http 动词,那 http 的动词域该会膨胀成什么样子?B.把原来的动词转化为“新的资源+以及对其的CRUD操作”(这样的话就可以 4 个动词打天下了),也就是那个知名的三角形。作为一个实用主义者,我想说的是——别把 A 当真了,其实也就给了你一个 B 方法而已。

3. uri 爆炸。
毫无疑问,应用了上述的 B 方法之后,除了原来的那些东西,还增加了大量的“动词 uri”。大部分语言的动词都是很发达的,这么做的结果也就是会导致 uri 也会很发达。原先以为 uri 可以得到简化(一个资源就是一个物理上的 uri 而不是一个逻辑上的 uri )的想法肯定是要落空了。

妥协的设计

实用主义者新的设计如下:

列表用户:

cookie: {auth_token}
content-type: text/javascript
GET /chat/{room}/_listuser

接收消息:

cookie: {auth_token}
content-type: text/javascript
POST /chat/{room}/_receive

发送消息:

cookie: {auth_token}
content-type: text/javascript
POST /chat/{room}/_send

to={the_receiver}&face={the_face}&text={what_i_said}

相比上一个理想化的设计,妥协的要点在于:
1.不用 http basic authentication 而用 cookie 来取代 http_auth 的位置。将 cookie 当作 http_auth 头来用,不是 session 没有引入服务端的状态,应该不算背离 rest 吧(哪位知道,澄清一下?不胜感谢)。
2.不用自定义 http 动词的方式,而是改用“新资源+U操作”的方式。
3.因为增加动词,引入了三个虚拟 uri 其中:
/chat/{room}/_listuser+GET 来表达“列表用户”(幂等)操作
/chat/{room}/_receive +POST 来表达“接收”(不幂等)操作
/chat/{room}/_send +POST 来表达“发送”(不幂等)操作
此时,聊天室的 uri :/chat/{room} 已经变成了“逻辑上的资源”,物理的 uri 无法继续看起来简洁清晰了(不符合审美啊,强忍了)。

回过头来再想想?

两个动词?

GET 和 POST 实际上只表达了“幂等操作”和“非幂等操作”的含义。所谓的 http method 表达谓语基本上是误读(如果应用只有 CRUD 那就另当别论)。实际上,如果你的应用不止是 CRUD 的话,谓语基本上会是放在 uri 之中当作一个虚拟资源来用的(而且,如果这个操作是幂等的那就用 GET,否则就用 POST)。

关于 cookie 再说几句。

为了避免影响“伸缩性”,rest 反对 session 这很好理解。因为作为新引入的而且通常又都绑定在 web 服务器上的这一个层次,因为其频繁访问的特性,在多个web服务器需要进行故障切换的角度,显然已经变成了“web服务器上的共享内存”,而共享内存又是 伸缩性的大敌。所以 rest 旗帜鲜明的反对使用 session 这种说法言之成理。但如果因为这样就连带着将 cookie 也一并作为反对的目标,就似乎有些不妥(某种角度上看 cookie 和 http_auth 一样,也是每个 request 都带着的,而且它也不绑定任何物理的 web 服务器)。另外一个反证是 rails 2.0 因为反对 session 而将 session 转而采用 cookie 的方式来实现(不确定,谁来解释下?)——如果 rest 是反对 cookie 的,那么这种做法岂不是很让人费解?

把 cookie 用来存放 session ?

我认为这是不妥的做法,cookie 和 session 在概念上完全不同。cookie 位于 http header 之中,相当于客户端的一个小标识。每一个请求都会带着。这意味着:1 cookie 的大小是有限制的,可以想象,如果每一个访问图片和css的请求都带着 10k 的 cookie ,那对带宽是多大的浪费。2 cookie 是客户端可见的,因为它发往客户端,在客户端保存,又在发起每一个请求时从客户端发回服务器,可以将它理解为服务器让客户端拿着的一个 ticket 。而标准的 session 显然并非如此。说起 session 时我们的常识都是:它不通过网络传播。这意味着:1 它是服务器本地的资源,不通过网络传输,客户端不可见,2 大小无限,想放什么放什么(当然,从性能角度考虑,最好不要放太多东西)。显然这两者的概念太不相同。如果用 cookie 来存放 session ,当然是具备了在不同服务器之间的迁移性,但,其一是破坏了 session 的可见性,其二是增加了大量的网络带宽。与其这样还不如干脆取消 session 这种机制,或者换一个别的名字。

服务器端的共享状态?

rest 的其中一个目的就是尽量避免服务端的共享状态,这个设计思路下 request 发往 web 群集中的任何一个都能正常工作。然而,从另外一个层面来分析,很多情况下,服务器端的状态又是不可避免的。比如,为多个 web 群集所共享的数据库就是一个有状态的东西。我们很难想象在数据库 down 掉了之后,前端的 web 如何能够继续提供服务。又或者在上述的聊天室例子中,想必要有一个“聊天服务器”来为这些 web 提供服务。否则,在一个 web 服务器上发送过的消息,切到另外一个 web 服务器上时又要再重发一遍,岂不是让人抓狂?rest 的参考方案并不重要,应该也没有不可逾越的教条,我们大可以根据实际情况自行调整。这种思想的要点或许是在于“让 request 所表达的语义尽可能的清晰(在http框架内,而不是构造新的协议)和完整(包含完成请求的所有必须信息),避免在设计之中包含依赖于 web 服务器上的某种额外的共享状态机制,比如 session,而人为的给 web 服务器的迁移带来障碍。

就这样吧

   1.
      pi1ot
      April 11th, 2008 at 07:28 | #1
      Reply | Quote

      有其他新用户进入房间时你如何得到通知去更新userlist?
   2.
      jackyz
      April 11th, 2008 at 07:40 | #2
      Reply | Quote

      @pi1ot
      通过 /chat/{room}/_receive +POST 接收到一条“用户进入消息”,相应的,也可以有“用户退出消息”。
   3.
      pi1ot
      April 11th, 2008 at 12:19 | #3
      Reply | Quote

      这个消息是server post 到 client的?貌似我没看懂rest
   4.
      jackyz
      April 12th, 2008 at 08:26 | #4
      Reply | Quote

      @pi1ot
      关于“comet的n多种可能”请移步“the google way”……。
   5.
      pi1ot
      April 14th, 2008 at 13:01 | #5
      Reply | Quote

      一竿子支回去年我们讨论过的话题了…
      打岔一下,perogramming erlang咋样了,去年圣诞礼物没指望上,今年圣诞有戏吗
   6.
      jackyz
      April 15th, 2008 at 17:36 | #6
      Reply | Quote

      呵呵,我们已经交稿,后面要看出版社的了。应该不用等到圣诞节吧。
   7.
      kk
      April 17th, 2008 at 12:32 | #7
      Reply | Quote

      如果用 cookie 来存放 session ,当然是具备了在不同服务器之间的迁移性,但,其一是破坏了 session 的可见性,其二是增加了大量的网络带宽。

      第一点的坏处没有那么大,只是美感不太高
      第二点同上,而且不是大量,cookie可以只是保存用户id,名字的md5字符串…
      而迁移性,服务器的伸缩性是一个性命攸关的问题
      当第一台服务器撑不住要分散到2,3台服务器上时… SNA的好处就体现了
   8.
      jackyz
      April 21st, 2008 at 16:31 | #8
      Reply | Quote

      @kk,要点在于 cookie 和 session 在“概念上”完全不可能是同一个东西。在 asp/php/jsp 程序员的概念里 session 是一个“本地的存储设施”,而且“大小无限”(想放什么都行)。这两点都是 cookie 所不能提供的。

      比如,其中一个应用场景是将“一组页面流程中的数据先暂存在 session 中再一起提交”。另外一个常见的应用场合是将“ authorize 相关的数据放在 session 中”。还有将“ session 作为当前回话用户的某种数据缓存机制”。这些应用场景,用 cookie 来做,也许能实现,但显然有问题,这就是“概念混淆”带来的问题。

      “破坏可见性”的坏处是“形成了安全隐患”,而“增加网络带宽”的坏处是“影响用户体验和提高运营成本”,说起来,也是可大可小的。

      SNA 是不错的,这里不反对 SNA ,反对的是“用 cookie 来存放 session ”这种实现方式。甚至于说,为了 SNA 完全可以牺牲掉 session (早年的 php 没有 session 还不是一样写程序?),而不是象这样搞出一套“混淆视听的 session”。
   9.
      TracyLiu
      May 13th, 2008 at 11:58 | #9
      Reply | Quote

      首先申明,我对rest和web的了解还出于入门阶段。说的不对的,请指教。
      对于chat,在资源/chat/{room}/下,是不是还包括 人 和 消息?所以相应的有/chat/{room}/user 和 /chat/{room}/message。这样,对于room中的listuser和message是否可以通过CRUD就可以解决呢?

 


RESTful Services with Erlang and Yaws

April 1st, 2008 :: jackyz

说来也巧,刚刚推荐过 InfoQ 的 The Power of Javascript 隔天就看到 InfoQ 又发了 Steve Vinoski 的一篇 RESTful Services with Erlang and Yaws ,地址在[这里 ],说不得,只好再次推荐。

和 Javascript/Ajax 一样,RESTful 也是风头正劲的 buzz words 。一言以蔽之,其实质就是回归 http 协议的本质,尽量在其框架之内解决问题。首先就是要 uri 化应用本身的资源,确保一个资源只有一个 uri ,以达致简洁。其次就是在 http 协议的 GET/POST/PUT/DELETE 动词(请求方法)上做文章(与之相对应的就是用户埋在 form 中的 act/op/delete/edit/modify/change/update/… 等千奇百怪的自定义参数),将其映射为 CRUD 的常规操作,再就是对 http 协议的 content-type 进行严格的清晰化,针对不同客户端的请求,返回不同“格式”的数据,除此之外,对于 status code 和 header 之类也做一番“依照规范”的改进。相比 post 带上一大坨自定义参数的“老旧风格”,不规范之余,也会让参数越来越冗长以及自定义的格式越来越糟糕, RESTful 风格则显然更多的发掘了 http 协议本身已经内置的潜力,可谓正本清源。

但我还有一个小小的疑问。RESTful 之中只定义了4个“动词”,如若我的应用更为另类,需要更多的“动词”,又该如何?自定义新的 HTTP Method 引入更多的自定义 Method 是否会破坏 RESTful 想要“规约简化”的本意?希望有人能够解答此疑惑。

misc

<script src="http://erlang-china.org/wp-content/themes/inove-10/js/comment.js" type="text/javascript"></script>

<!---->


  1. April 3rd, 2008 at 07:06 |
    Reply | Quote

    还有啥特别的操作?
    所有对资源的操作不都可以抽象成 查看,创建,编辑,删除之一吗
    有什么例外?举个例子
    #

    jackyz
    April 7th, 2008 at 08:55 | #2
    Reply | Quote



    CRUD 对于数据库应用当然是不错的抽象,但,现实应用中似乎并非只有数据库这一种应用。

    比如:聊天室、竞价拍卖、股票交易……,这些隐含“有连接”概念(stateful)的应用。从实现层面,站在数据库的角度来看(如果是用数据库来实现的话)确实也可以说它有对实现数据库记录的 CRUD 动作(但假若我不是用数据库来实现的呢?),显然这种抽象并非此类业务比较自然的抽象模型。以聊天为例,比如,可将其业务动词抽象为比较原始的:连接、发送、接收,若更复杂一些,还可以创造出 N 多种“业务动词”出来,这些和 CRUD 又该如何映射?

    我的问题是:RESTful 规范只规定了4种动词(分别用4种 HTTP 方法来映射),这4个动词是“严格规定” or “仅仅作为示例”?

    “严格规定”意味着只能有这4个,因为 HTTP 1.1 的标准方法只支持8个方法,标准内的其他方法已有相对确定的含义,显然,前面已经说过,这在很多情况下都是不够用的。

    “仅仅作为示例”则意味着,可以使用 HTTP 1.2 或更高版本比如 WebDav 规范之中定义过的方法,或者,用户也可以根据自己的业务需求自行定制新的 HTTP 方法,显然,这有导致 HTTP 方法大爆炸的危险,问题是,这些定制方法对于网络设备或者代理软件之类的也意味着难于处理的境地。
    #

    jackyz
    April 7th, 2008 at 09:04 | #3
    Reply | Quote

    还有一种可能,那就是”RESTful”不适用”隐含有连接”的模型?
    #


    April 7th, 2008 at 09:54 | #4
    Reply | Quote

    比如:聊天室、竞价拍卖、股票交易……,

    这些已经脱离了’资源’这个范畴了,算soa方面了,需要人肉写交互代码吧
    #
    jackyz
    April 7th, 2008 at 10:55 | #5
    Reply | Quote

    @kk
    我感觉这类应用不应该是rest不适用的范畴,似乎有若干此类应用也开放了restful的接口。

    刚才拉住dlee一阵猛问,很有收获,记载在下面。

    “资源是一个抽象的概念,并非严格的必须是一个URL,如果操作不够,那就再构造几个新的URL来表达操作,把对于method的渴望映射到URL中。在webdav中的这种自定义method的方式,并不符合rest的原则。”

    “rest的核心是操作语义的可见性,其目的是为了让应用有良好的可伸缩性。”

    “http的无状态,也是从伸缩性角度的考虑。”

    那么“从伸缩性的角度考虑,在rest指导下架构的应用,是否就必须是无状态的呢”或“在rest的框架内,如何处理有状态的应用?”又或者“有状态的应用如何映射为无状态的呢?”

    继续思考……。
    #

    jackyz
    April 7th, 2008 at 13:09 | #6
    Reply | Quote

    update1

    “在webdav中的这种自定义method的方式,并不符合rest的原则。”——此言并不确切,fielding认可webdav的方法,restful也不限定method的数目。但,问题在于webdav自己定义的http方法可能会造成现有http支持设施的处理困难,因而出现实际应用中的问题。

    也就是说,我上面的问题已经被回答了,方法不够用,那就:
    A.增加方法,象 webdav 一样,但有底层设施不支持的问题(不好用)。
    B.放到“社会主义初级阶段”的url里面去。但url显然会膨胀(不好看)。
    这两种方法都是rest所接受的。

    update2

    状态有两种:连接的状态,资源的状态,二者并无直接的关联。rest考虑的是资源的状态,而极力避免连接的状态(这会在伸缩性上造成麻烦),也就是 “每次请求都是独立的(目前将其理解为,包含所有的必须信息)”,这意味着可以在任何另外一台web服务器上来处理这个请求,request本身包含处理这个请求的所需信息。而对于连接的状态,rest则旗帜鲜明的表示反对。一般而言将cookie或session都认为是不符合原则的。长连接的 comet也在其列。

    那么,现在的新问题是“有状态的连接”比如comet的chat应用,又要如何用rest的原则来指导其构建呢?

    继续thinking…


zhaoja... @hotmail.com: hi
李锟(dlee): hi
zhaoja... @hotmail.com: 好久没见,可好?
李锟(dlee): 还好
李锟(dlee): 你现在在哪里啊?
zhaoja... @hotmail.com: 呵呵,我还是老样子啊。有个关于restful的问题想不明白,就想起你来了。
李锟(dlee): 呵呵,可以来我们的讨论组讨论
zhaoja... @hotmail.com: 应该没那么复杂,就是一个简单的问题,你看这里:
zhaoja... @hotmail.com: http://erlang-china.org/misc/restful_erlang_yaws.html
zhaoja... @hotmail.com: 看我后面的comment就行了。
zhaoja... @hotmail.com: 主要是对restful的理念还不是很清晰。
zhaoja... @hotmail.com: 我看到webdav自己扩展了很多http的方法,这是restful所鼓励的么?
李锟(dlee): 这个问题很有代表性,是大多数人对REST心存疑虑的原因
zhaoja... @hotmail.com: 恩,我想,可能是我在哪里没有理解透彻
李锟(dlee): 答案是,如果需要更多的操作,定义一个新的资源
李锟(dlee): 这里主要的问题是,大多数人不理解资源是抽象的
zhaoja... @hotmail.com: 哦?可是。。。问题在于,这样的话,URL的数量岂不是会成倍的增加?
李锟(dlee): 大多数人把资源看作是一些很具体的东西,例如服务器端的一个文件、数据库中的一条记录。
李锟(dlee): 没有关系啊,URL数量成倍增加有什么问题?
zhaoja... @hotmail.com: 恩。看来就是在这里理解有问题了。我之前认为RESTful将资源定义为URI是为了规约URI,通过
引入methods来解决自定义act参数的问题。
李锟(dlee): URI+4种HTTP方法本来就是设计用来做这个事情的
zhaoja... @hotmail.com: 好像见过你提到comet和restful是有冲突的?具体怎么讲?
李锟(dlee): 当然可以引入自定义的method,WebDAV就是这样干的,不过这种做法不推荐。
李锟(dlee): 对,是有冲突的
zhaoja... @hotmail.com: 是的哦,自定义的method在设备的通过性上违背了restful的原则,所以,我也很存疑。
李锟(dlee): comet的典型实现,包括Dojo的那个什么协议都是这样做的
李锟(dlee): 客户端通过动态生成的script标签请求服务器的一个用不结束的代码流
李锟(dlee): 这个代码流中有js脚本,通过这些脚本来传递数据
李锟(dlee): 这样做违反了REST
zhaoja... @hotmail.com: 违背了哪一条?
李锟(dlee): 没有人说你绝对不应该违反REST,REST也不是五台山上的清规戒律。只是告诉你如果你违反了REST,你会付出代价。
zhaoja... @hotmail.com: 是不是rest暗示并非针对有连接的应用?
李锟(dlee): 如果你觉得这样的代价可以承受,那就无所谓了
李锟(dlee): 违反REST是因为违反了操作语义的可见性
李锟(dlee): 操作的语义不应该由消息体来传达
李锟(dlee): 而应该完全放在头信息字段中
李锟(dlee): 这样中间组件才能够以最有效的方式实现缓存和安全审计。
李锟(dlee): 违反了操作语义的可见性,就打破了REST的统一接口,会对应用的可伸缩性造成严重影响。
李锟(dlee): 这种方式,客户端很难实现有效的缓存。
zhaoja... @hotmail.com: 但是对于像comet这种在无连接的http上实现有连接的应用模式,因为browser不保持连接,
似乎是很难在rest框架内做到语义的可见性。
李锟(dlee): 所以Comet是有代价的,如果服务器端没有相应的支持,并发一大就会耗费掉服务器端的所有资源。
李锟(dlee): Jetty解决这个问题是通过Java NIO的无阻塞连接实现的
李锟(dlee): Tomcat也有类似的支持
zhaoja... @hotmail.com: 对于这个问题,试想,如果换成老的xhr定时刷新,是否会更加符合rest原则呢?
李锟(dlee): 那样更符合REST原则,但是实时性就差很多了。
李锟(dlee): 无连接就是为了得到最大的可伸缩性
李锟(dlee): 服务器端无状态也是为了得到最大的可伸缩性
zhaoja... @hotmail.com: 我有一个疑问,比如 GET /chat/room/update 这个就是不断刷新的动作,这个语
义,我感觉可见性还是没有表达出来呢。因为,这里隐含了 who ,这个 who 可能是通过 cookie 或什么别的来传递的。这个 who 某种
意义上就是一个状态。
zhaoja... @hotmail.com: 从 rest 的原则来设计,这样的有状态的东西,要如何转换为无状态的呢?
李锟(dlee): Comet通过GET请求还有可能改变服务器端资源的状态,这样做是不对的。GET不应该改变资源的状态。
李锟(dlee): cookie对于REST应用来说应该完全弃用。
zhaoja... @hotmail.com: 是否这样更加符合REST?

POST /chat/room/update

?who=1234
李锟(dlee): 或者这样说,cookie不应该作为客户端与服务器端传递资源状态的手段,因为它不适合做这件事情
李锟(dlee): cookie只应该用来在客户端保存客户端自己的状态,服务器端应该完全不处理cookie
李锟(dlee): cookie应该被当作客户端离线存储的一种手段
李锟(dlee): POST /chat/room/1234
李锟(dlee): 这样就可以了
李锟(dlee): who这个信息应该出现在URL中
zhaoja... @hotmail.com: 如果这样的话,似乎有个伪造url的风险
李锟(dlee): 不放在URL中就不会被伪造了吗?
李锟(dlee): 伪造有什么危害?
zhaoja... @hotmail.com: 对聊天室来说,伪造就有冒充其他人说话的问题。
李锟(dlee): 那是通过HTTP身份认证来解决的
李锟(dlee): HTTP 1.1内建的机制
李锟(dlee): 还支持引入第三方的认证算法
zhaoja... @hotmail.com: http身份认证对于游客是一个问题啊
李锟(dlee): 很简单,游客不需要认证就可以发言,但是要以dlee的名义发言,必须通过身份认证
zhaoja... @hotmail.com: 恩,是我没有说清楚。这里的身份,是某一个客户端,不是某一个用户的意思。在一个chat的会话中,关
键是要“将信息送给确定的人”,可能两个人都是游客,但,发送给A的就不能发送给B。
李锟(dlee): 某个客户端的身份认证也一样可以用HTTP身份认证机制来实现
zhaoja... @hotmail.com: 这里其实就是一个token,目前的http设施之中,cookie似乎是这个token的最好存放地
点。
zhaoja... @hotmail.com: 我所认为的http身份认证是发起一个http验证请求,此时用户的浏览器会探出一个输入用户名和密码
的框,我们说的是不是同一个东西?
zhaoja... @hotmail.com: 作者:kk

比如:聊天室、竞价拍卖、股票交易……,

这些已经脱离了’资源’这个范畴了,算soa方面了,需要人肉写交互代码吧

你觉得这个回应怎么样?我觉得这类应用,rest应该也能适用才是吧。
zhaoja... @hotmail.com: 呵呵,浪费了你很多时间。我先去吃饭了,回头再聊。
李锟(dlee): 刚才去吃饭了
李锟(dlee): 就是这个HTTP身份认证,不过也可以自己来实现
李锟(dlee): HTTP身份认证是针对一个realm的,就是服务器端一组资源
zhaoja... @hotmail.com: 这个身份认证还能让它不弹出一个对话么?
李锟(dlee): cookie是针对一个domain的,对应服务器端的所有资源,范围比realm大
李锟(dlee): 《Ajax模式与最佳实践》中有介绍,我回去再帮你看看
李锟(dlee): 资源是抽象的,跟社会主义初级阶段一样,什么都可以塞进去。
李锟(dlee): 它就像如来的手掌一样
李锟(dlee): 开个玩笑,呵呵
zhaoja... @hotmail.com: 哈哈。。。
zhaoja... @hotmail.com: 看来用rest需要在url上狠做文章
李锟(dlee): RESTful Web Services里面讲的挺清楚的,建议参考一下
李锟(dlee): URL用来携带地址信息,就是who的信息,HTTP method用来携带操作语义。
zhaoja... @hotmail.com: 恩,好的,我回去参考下。还是回那个问题本身,rest很强调无状态,那么一个在本质上就是有状态的应
用在rest框架内,是否能够得到妥善的解决呢?这个问题是否有人回答过了?
李锟(dlee): 无状态指的是会话的状态,不是资源的状态。
李锟(dlee): 我以前写过Fielding论文导读,澄清过这个问题。
李锟(dlee): 会话的状态应该完全在客户端
李锟(dlee): 每个请求应该携带完成该请求必须的所有会话状态
zhaoja... @hotmail.com: 照这么说,session之类的服务端状态机制也是为rest所反对的吧。
李锟(dlee): 对的,其实真正的REST应用完全不用session
李锟(dlee): Rails 2.0做了一个折中的设计,就是session数据默认保存在客户端的cookie中
李锟(dlee): 这样服务器可以不必保存session数据,提高了服务器的可伸缩性
zhaoja... @hotmail.com: 恩,但是在具体应用之中,状态这个东西在服务端是确实存在的。比如,购物车,如果完全放在客户端,似乎
也能工作。但至少,服务端还是需要保存用户在结帐之前已经买了什么东西。这种状态,在rest中是怎么映射的呢?
zhaoja... @hotmail.com: 是否也将其弄成某种资源来处理?
李锟(dlee): 开始的时候说到的WebDAV的做法,是完全符合REST的做法,因为REST的统一接口并没有限制每个接口只能有几个方
法。Fielding本人也明确肯定WebDAV的做法没有问题。
zhaoja... @hotmail.com: 哦?不是说webdav自己加入的n多自定义的http方法,违反了rest的原则么?
李锟(dlee): ...

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics