Long Polling and HTTP Keep-Alive: 长轮询与连接复用

客户端想"一有新消息就知道",但只能由客户端主动发请求(比如它在内网里,服务端连不进来),常用的办法是长轮询。这篇记录长轮询怎么工作,以及它底下的 HTTP 连接复用(keep-alive)是怎么回事。起因是给 homelab 配 GitHub Actions 自托管 runner 时,想弄清楚 runner 在内网里是怎么及时拿到任务的。 短轮询和长轮询 短轮询:客户端每隔固定时间问一次"有没有新消息",服务端立刻回答,有就给,没有就回空。 间隔设短了,大部分请求都是空跑,浪费流量和服务端资源 间隔设长了,消息要等到下一次轮询才能拿到,延迟最多一个间隔 长轮询:客户端发出请求后,服务端先不回答,把请求挂住: 挂住期间来了消息,立刻在这个请求上返回 一直没有消息,等到约定的时间(比如 50 秒)返回一个空响应 客户端收到响应(不管有没有消息)后马上发下一个请求 client server |---- GET /messages (wait up to 50s) ---->| | | no message yet, hold the request | | ... 12s later a message arrives |<--------- 200 [message] ----------------| |---- GET /messages (wait up to 50s) ---->| sent again immediately | | nothing for 50s |<--------- 200 [] (empty) ---------------| |---- GET /messages (wait up to 50s) ---->| 所以长轮询几乎任何时候都有一个请求挂在服务端,消息一到就能送出去,延迟接近实时;没有消息时每 50 秒才一个请求,空跑也很少。消息在两次请求之间到达也不会丢:服务端先把它放进队列,下一个请求一到就取走。 ...

Created 20206-10-20 · Updated 20206-10-20 · 2 min · 310 words · -

HTTP basic

HTTP basic get/post 1.HTTP请求格式: 在HTTP请求中,第一行必须是一个请求行 (request line) ,用来说明请求类型、要访问的资源以及使用的HTTP版本。紧接着是一个首部 (header) 小节,用来说明服务器要使用的附加信息。在首部之后是一个空行,再此之后可以添加任意的其他数据[称之为主体 (body) ]。 重定向 Redirect 重定向是指当浏览器请求一个URL时,服务器返回一个重定向指令,告诉浏览器地址已经变了,麻烦使用新的URL再重新发送新请求。 例如,我们已经编写了一个能处理/hello的HelloServlet,如果收到的路径为/hi,希望能重定向到/hello 如果浏览器发送GET /hi请求,RedirectServlet将处理此请求。由于RedirectServlet在内部又发送了重定向响应,因此,浏览器会收到如下响应: HTTP/1.1 302 Found Location: /hello 当浏览器收到302响应后,它会立刻根据Location的指示发送一个新的GET /hello请求,这个过程就是重定向: ┌───────┐ GET /hi ┌───────────────┐ │Browser│ ────────────> │RedirectServlet│ │ │ <──────────── │ │ └───────┘ 302 └───────────────┘ ┌───────┐ GET /hello ┌───────────────┐ │Browser│ ────────────> │ HelloServlet │ │ │ <──────────── │ │ └───────┘ 200 <html> └───────────────┘ 观察Chrome浏览器的网络请求,可以看到两次HTTP请求: 并且浏览器的地址栏路径自动更新为/hello。 重定向有两种: 一种是302响应,称为临时重定向,一种是301响应,称为永久重定向。两者的区别是,如果服务器发送301永久重定向响应,浏览器会缓存/hi到/hello这个重定向的关联,下次请求/hi的时候,浏览器就直接发送/hello请求了。 重定向有什么作用?重定向的目的是当Web应用升级后,如果请求路径发生了变化,可以将原来的路径重定向到新路径,从而避免浏览器请求原路径找不到资源。 HttpServletResponse提供了快捷的redirect()方法实现302重定向。 http2 https://halfrost.com/http2-http-frames/ https://www.liaoxuefeng.com/wiki/1252599548343744/1328761739935778 https://alanli7991.github.io/2016/10/26/HTTP%E8%AF%B7%E6%B1%82GETPOST%E4%B8%8E%E5%8F%82%E6%95%B0%E5%B0%8F%E7%BB%93/ ...

Created 23236-10-23 · Updated 9096-10-09 · 1 min · 166 words · -

从 HTTP GET 和 POST 的区别说起

从 HTTP GET 和 POST 的区别说起 HTTP 定义了与服务器交互的不同方法,最基本的方法是 GET 和 POST. 面试时得到的回答大多是: POST 是安全的,因为被提交的数据看不到,或者被加密的,其它的还有 GET 的时候中文出现乱码 (在地址栏里) ,数据最大长度限制等等。 说 POST 比 GET 安全肯定是错的,POST 跟 GET 都是明文传输,用httpfox等插件,或者像WireShark 等类似工具就能观察到。 POST 和 GET 的差别其实是很大的。语义上,GET 是获取指定URL上的资源,是读操作,重要的一点是不论对某个资源 GET 多少次,它的状态是不会改变的, 在这个意义上,我们说 GET 是安全的 (不是被密码学或者数据保护意义上的安全) 。因为 GET 是安全的,所以 GET 返回的内容可以被浏览器, Cache 服务器缓存起来 (其中还有很多细节,但不影响这里的讨论) 。 而 POST 的语意是对指定资源"追加/添加"数据,所以是不安全的,每次提交的 POST,参与的代码都会认为这个操作会修改操作对象资源的状态, 于是,浏览器在你按下 F5 的时候会跳出确认框,缓存服务器不会缓存 POST 请求返回内容。 很遗憾到目前为止没有应聘者能够提到这一点。我猜测这背后的原因大概有两个,一是也许大多数人往往 (我也一样) 满足于只要完成任务就好,不管用哪个, 表单提交了,数据处理了,内容显示或者重新定向到另外一个页面,就算完成了一个任务,从任务表里划掉,结束。 而且对大部分项目(OA, CRM, MIS)的大部分情况下,用哪个似乎都可以。 同时,在被商业机构在媒体和书籍上宣传兜售的 WS-* 概念和使用集成开发环境提供的"方便"的代码生成工具后,“了解"到所有 Web 服务调用都是通过 POST, 更潜意识里确定了 POST 和 GET 是一样的,而且 GET 能做的,POST 都能做,POST 简直就是 GET++ 嘛。 自然,能用 POST 就用 POST,不必在乎两者的差别了。 ...

Created 3036-06-03 · Updated 9096-10-09 · 4 min · 790 words · -

IP, TCP 和 HTTP

IP,TCP 和 HTTP 172.16.128.0/24 经常看到这类IP地址"/24"表示什么意思? 子网掩码, 代表多少个1 子网掩码是4个8位2进制数组成的, 换化成10进制是就是现在这样的, 如255.255.255.0, 换成2进制的话就是11111111 11111111 11111111 00000000, 前面有24个1, 也就是ip/24, 192.168.1.1/24 就表示ip是192.168.1.1, 子网掩码是255.255.255.0 http://objccn.io/issue-10-6/ 当 app 和服务器进行通信的时候,大多数情况下,都是采用 HTTP 协议。HTTP 最初是为 web 浏览器而定制的,如果在浏览器里输入 http://www.objc.io ,浏览器会通过 HTTP 协议和 www.objc.io 所对应的服务器进行通信。 HTTP是运行在应用层上的应用协议,而不同的层级上都有相应的协议在运行。层级的堆栈关系一般可以这么描述: Application Layer - e.g. HTTP – Transport Layer - e.g. TCP – Internet Layer - e.g. IP – Link Layer - e.g. IEEE 802.2 所谓的 OSI (Open Systems Interconnection,开放式系统互联) 模型定义了七层结构。本文会关注应用层 (application layer)、传输层 (transport layer) 和网络层 (internet layer),它们分别代表了典型的 HTTP 的应用的 HTTP,TCP 以及 IP。在 IP 之下的是数据连接和物理层级,比如像 Ethernet 的实现之类的东西 (Ethernet 拥有一个数据连接部分以及一个物理部分) 。 ...

Created 29296-07-29 · Updated 9096-10-09 · 11 min · 2254 words · -

HTTP Methods: GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE, CONNECT, QUERY

HTTP Methods: GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE, CONNECT, QUERY https://www.cnblogs.com/machao/p/5788425.html HTTP Method 的历史: HTTP 0.9 这个版本只有 GET 方法 HTTP 1.0 这个版本有 GET HEAD POST 这三个方法 HTTP 1.1 这个版本是当前版本,包含 GET HEAD POST OPTIONS PUT DELETE TRACE CONNECT 这 8 个方法 之后单独用 RFC 追加的方法:PATCH(RFC 5789,2010 年,部分修改资源)、QUERY(RFC 10008,2026 年 6 月,带请求体的安全查询,见下文 QUERY) 我们先看看HTTP 1.1 规范的中文翻译 方法定义 (Method Definitions) HTTP/1.1常用方法的定义如下。虽然方法可以被展开,但新加的方法不能认为能分享与扩展的客户端和服务器同样的语义。 Hst 请求头域 (见13.23节) 必须能在所有的HTTP/1.1请求里出现。 9.1 安全和等幂 (Idempotent) 方法 9.1.1 安全方法 (Safe Methods) 实现者应当知道软件是代表用户在互联网上进行交互,并且应该小心地允许用户知道任何它们可能采取的动作(action),这些动作可能给他们自己或他人带来无法预料的结果。 ...

Created 29296-09-29 · Updated 29296-09-29 · 6 min · 1210 words · -

spring basic

spring basic @RestController @RestController 是 @Controller 与 @ResponseBody 的组合注解,用于编写 RESTful API:控制器方法的返回值会直接写入 HTTP 响应体(通常是 JSON),而不是交给视图解析器去渲染页面。 @RestController @RequestMapping("/api/comments") public class CommentController { @GetMapping("/{id}") public Comment get(@PathVariable long id) { return commentService.findById(id); } } 上例中,Comment 对象会被 HttpMessageConverter(如 Jackson)序列化为 JSON 返回给客户端。 适用场景: 前后端分离:Vue、React、移动端等通过 HTTP 调用后端接口 微服务之间的 HTTP 调用 任何「请求数据 → 返回 JSON/XML」的 API 不适用场景: 传统的服务端渲染 Web 应用(JSP、Thymeleaf 等):这类应用需要 @Controller 返回视图名或 ModelAndView,由视图解析器渲染 HTML 页面 @Controller public class PageController { @GetMapping("/home") public String home(Model model) { model.addAttribute("title", "Home"); return "home"; // 解析为 home.jsp 或 templates/home.html } } 若把 JSP/Thymeleaf 页面控制器写成 @RestController,返回值会被当作响应体内容(例如字符串 "home" 会原样输出),而不会走视图解析,页面无法正常渲染。 ...

Created 5056-01-05 · Updated 20206-05-20 · 2 min · 352 words · -