{"action":"closed","issue":{"url":"https://api.github.com/repos/plantain-00/blogs/issues/20","repository_url":"https://api.github.com/repos/plantain-00/blogs","labels_url":"https://api.github.com/repos/plantain-00/blogs/issues/20/labels{/name}","comments_url":"https://api.github.com/repos/plantain-00/blogs/issues/20/comments","events_url":"https://api.github.com/repos/plantain-00/blogs/issues/20/events","html_url":"https://github.com/plantain-00/blogs/issues/20","id":163399827,"number":20,"title":"websocket和http的权衡","user":{"login":"plantain-00","id":7639395,"avatar_url":"https://avatars.githubusercontent.com/u/7639395?v=3","gravatar_id":"","url":"https://api.github.com/users/plantain-00","html_url":"https://github.com/plantain-00","followers_url":"https://api.github.com/users/plantain-00/followers","following_url":"https://api.github.com/users/plantain-00/following{/other_user}","gists_url":"https://api.github.com/users/plantain-00/gists{/gist_id}","starred_url":"https://api.github.com/users/plantain-00/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/plantain-00/subscriptions","organizations_url":"https://api.github.com/users/plantain-00/orgs","repos_url":"https://api.github.com/users/plantain-00/repos","events_url":"https://api.github.com/users/plantain-00/events{/privacy}","received_events_url":"https://api.github.com/users/plantain-00/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2016-07-01T13:50:31Z","updated_at":"2016-08-02T13:30:28Z","closed_at":"2016-08-02T13:30:28Z","body":"websocket的特色是主动推送以及广播效果，效果比http轮询要好。\r\n\r\n传输格式上，http目前只支持文本，还要携带header和cookie，而websocket可以支持传输二进制数据，可以利用protobuf等压缩size，所以传输的量websocket明显小于http。\r\n\r\n传输大量内容时，例如文件上传，如果使用websocket，会阻塞其它数据的传输，这种情况使用http要更好一些。使用http获取数据时，可以利用浏览器的缓存机制，避免重复下载。\r\n\r\nwebsocket的浏览器支持程度是，>=IE10，不过可以使用socket.io等库，来支持低版本的浏览器。\r\n\r\n一个小特点是，websocket是不受同源策略限制的。\r\n\r\n模型上http是请求－响应模型，而websocket是基于事件的的模型，发出消息后，不一定会有对应的响应，也可能有多个响应。\r\n实际使用时，http类似于常规的接口同步调用，服务端无状态，客户端有状态，收到响应时有请求时的context，知道是哪个请求的结果，而websocket不是这样，服务端有状态，有连接时就产生的context，客户端没有局部状态，发送消息时的context可以保存在消息中，也可以保存在全局的hash结构中，在各个事件中，从消息体中，或者全局的hash结构中，恢复出消息发送时的context，执行相应的操作。\r\n这样消息的发出和接收不再一一对应，也就完全解藕出来。\r\n对于具体的命令，可以默认它成功，如果出现错误时，推送这个错误通知，并还原消耗的资源。\r\n对于查询，可以做成连接时主动返回的形式，在变更时，主动通知变更后的结果，使开发模型更简单。\r\n另外某些情况下，可以把客户端的定时转移到服务端，定时查询并组合数据后，统一推送，从而使系统负载更低。\r\n\r\n设计http接口时，需要从资源的增删改查角度设计，服务端驱动。\r\n设计websocket接口时，需要从客户端需要的事件角度设计，客户端驱动。\r\n\r\n最后给出一个例子，某个用户用自己的积分，换取某个物品：\r\n如果使用http，客户端在请求时，扣除积分，并携带token，成功后加入仓库，失败后恢复积分，并提示错误原因。\r\n如果使用websocket，客户端在发送消息时，扣除积分，（不需要携带token，服务端也不需要验证，因为服务端是有状态的，连接时已经验证过了），成功后在仓库更新事件收到消息，把物品加入仓库，失败后在积分更新事件收到消息，更新积分，在消息提示事件收到消息，提示错误消息。\r\n\r\n结论，http和websocket有各自的用武之地，完全不同的编程模型，结合着使用，可以发挥完美的效果。\r\n\r\n另外，通过websocket连接，可以使用传统的json-rpc，宏观上类似于方法调用，但是实现时，如果不借助第三方库，客户端需要生成不重复的id，并在收到消息时，匹配消息的id和已发出的消息的id，还要管理已发出消息的请求的生命周期，会更复杂一些。"}}
{"actor":{"display_login":"plantain-00"}}