V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
fireleaves
V2EX  ›  程序员

关于 HTTP 服务器实现的小白级别的问题

  •  
  •   fireleaves · 2021-03-10 16:32:00 +08:00 via Android · 2453 次点击
    这是一个创建于 1136 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我也是一个后端开发,但是做的都是和客户端直接建立长连接的,例如 TCP 或者 Web socket 。所以对 HTTP 的服务端的实现方式有点好奇。

    主要问题在于,如果一个 HTTP 请求是需要去数据库取数据的或者耗时较长的,那么服务器怎么异步的处理这个请求呢?还是说不管请求是什么类型的,都同步的处理完,然后再返回?

    举个栗子:

    客户端发起登录,服务器收到请求需要去数据库中获取玩家数据。

    对于长链接,可以在收到客户端请求之后,发起数据库操作,流程就此中止,服务器可以在此时处理其他请求,异步等数据库返回结果,再回调完成登录的后续处理,返回给客户端下行协议。

    HTTP 好像不能把请求缓存起来,等待后边数据库触发之后再处理。是可以缓存再处理而我不知道呢?还是大家用 Redis 等查询耗时低的数据库解决呢?

    纯小白,还请大家不吝赐教去。

    23 条回复    2021-03-11 13:50:37 +08:00
    lidongyo
        1
    lidongyo  
       2021-03-10 16:38:45 +08:00
    所以类似场景都一般不用 HTTP
    fireleaves
        2
    fireleaves  
    OP
       2021-03-10 16:40:15 +08:00 via Android
    @lidongyo 那对于网站来说,像登录这种请求,都是先建立好长链接吗? Web socket ?
    j0hnj
        3
    j0hnj  
       2021-03-10 16:40:19 +08:00
    这种一般是先请求创建一个任务,服务端返回一个任务 ID,之后客户端轮询这个任务 ID,直到任务完成
    fireleaves
        4
    fireleaves  
    OP
       2021-03-10 16:41:22 +08:00 via Android
    @j0hnj 牛啊,这种方式可以的
    lidongyo
        5
    lidongyo  
       2021-03-10 16:47:04 +08:00
    @j0hnj 楼主钻牛角尖,非得从现代回到远古时期
    hello2060
        6
    hello2060  
       2021-03-10 16:50:15 +08:00 via iPhone
    @fireleaves 登录应该就是同步的啊,登陆能用多久,没有异步的登录吧
    clayyj1210
        7
    clayyj1210  
       2021-03-10 16:51:52 +08:00
    你可以从长连接的角度来看 HTTP,每次 HTTP 请求①相当于长连接中的客户端请求,HTTP 请求到服务器端之后流程中止,中止之后(如果业务场景允许,就是等待长时间的操作;如果业务场景不允许,那可能就是返回失败或者采用别的方式如 Redis 来减小时间)。
    这时候客户端可以发起其它的 HTTP 请求②,不过这两个 HTTP 请求是相互独立的,没有采用相同的 TCP 链接。
    当前面的中止结束之后,通过 HTTP 请求①链接将数据返回。
    HTTP 请求②的处理同理返回。
    fireleaves
        8
    fireleaves  
    OP
       2021-03-10 16:58:59 +08:00
    @lidongyo 我是真的不懂呀,不知道网站那种的 HTTP 请求是怎么实现的
    fireleaves
        9
    fireleaves  
    OP
       2021-03-10 17:02:26 +08:00
    @clayyj1210 理解了,就是类似于#4 的那种任务 ID,不断轮询,直到服务器完成的时候在某次的轮询中下行结果
    baiyi
        10
    baiyi  
       2021-03-10 17:05:34 +08:00   ❤️ 2
    对于 HTTP 协议本身来说是有异步这个响应结果的,它的 202 Accepted 状态码的响应就是告诉客户端请求已经接受了,但还没有处理,并且不保证在处理的过程中是否一定能成功。

    从这个角度来说,只用 HTTP 就需要服务端再提供一个查询的接口,客户端在请求结束后不断的查询请求的处理状态。

    还有一种情况是你的处理结果可以分批次传输,比如去数据库读取数据需要较长时间,那么就分别读取,分批次交给客户端,这时是可以在一个 HTTP 连接中完成的,通过 chunked 传输编码,让客户端和服务端保持长连接。
    kikione
        11
    kikione  
       2021-03-10 17:35:52 +08:00
    异步的话,不是应该有个回调地址么
    yamasa
        12
    yamasa  
       2021-03-10 17:39:39 +08:00
    楼上哥们儿说的很好了。我们的服务里 chunked transfer encoding 和异步接口轮询两种做法都涉及了。
    acmore
        13
    acmore  
       2021-03-10 17:54:11 +08:00
    一种简单的异步任务 HTTP 请求方案:

    1. 第一次请求返回 202 Accepted 和一个 Job ID;
    2. 之后轮询这个 Job ID,直到拿到结果为止;
    YokitCoder
        14
    YokitCoder  
       2021-03-10 17:59:07 +08:00
    HTTP 一般不处理耗时较长的请求,非要处理一个是可以采用 redis 缓存加快查询结果,另一个就是借助 js 的 ajax 异步处理。
    ikas
        15
    ikas  
       2021-03-10 19:11:26 +08:00
    依赖的是操作系统 IO 的支持,想真的搞明白就看下 IO 模型,http 只不过是个上层应用协议
    also24
        16
    also24  
       2021-03-10 19:41:27 +08:00 via Android
    关键词:
    1 、长连接
    2 、轮询
    3 、长轮询
    FucUrFrd
        17
    FucUrFrd  
       2021-03-10 21:48:48 +08:00 via Android
    Oltp 大部分 200ms 以下,而 http nginx 尽量配成 10s 超时
    fireleaves
        18
    fireleaves  
    OP
       2021-03-10 22:47:57 +08:00 via Android
    @baiyi 感谢
    fireleaves
        19
    fireleaves  
    OP
       2021-03-10 22:48:58 +08:00 via Android
    @also24 老哥稳,我去了解一下。
    laowudxf
        20
    laowudxf  
       2021-03-11 08:43:04 +08:00
    比如我用 php 开发后台,就比较简单了,php-fpm 有个连接池,比如可以同时处理 10 个请求,其他的框架的话我知道有些是非阻塞类型的框架这种阻塞操作也不会影响下一个请求。
    wangritian
        21
    wangritian  
       2021-03-11 10:05:52 +08:00
    http 本质是一来一回的 tcp 包,访问数据库或其他 IO 操作时一般会切换线程 /转让协程,让服务器同时处理其他请求,拿到 IO 结果再给客户端返回 tcp 包
    mmdsun
        22
    mmdsun  
       2021-03-11 12:46:47 +08:00 via Android
    了解下 SSE(Sever-Sent Event)
    muzuiget
        23
    muzuiget  
       2021-03-11 13:50:37 +08:00
    HTTP 也可以长时间等待,没说一定要马上返回,一样可以做长时间请求。

    说白了你要做到在呈现在用户界面这一层,不要样用户有“卡住”的感觉,服务端和客户端做都行,但是客户端责任更大,毕竟服务器挂掉时,也是相当于一次长时间请求。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2839 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 13:31 · PVG 21:31 · LAX 06:31 · JFK 09:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.