1. 1 不可撤销
  2. 2 小年兽 程嘉敏
  3. 3 手放开 李圣杰
  4. 4 迷人的危险3(翻自 dance flow) FAFA
  5. 5 山楂树之恋 程佳佳
  6. 6 summertime cinnamons / evening cinema
  7. 7 不谓侠(Cover 萧忆情Alex) CRITTY
  8. 8 神武醉相思(翻自 优我女团) 双笙
  9. 9 空山新雨后 音阙诗听 / 锦零
  10. 10 Wonderful U (Demo Version) AGA
  11. 11 广寒宫 丸子呦
  12. 12 陪我看日出 回音哥
  13. 13 春夏秋冬的你 王宇良
  14. 14 世界が终わるまでは… WANDS
  15. 15 多想在平庸的生活拥抱你 隔壁老樊
  16. 16 千禧 徐秉龙
  17. 17 我的一个道姑朋友 双笙
  18. 18 大鱼  (Cover 周深) 双笙
  19. 19 霜雪千年(Cover 洛天依 / 乐正绫) 双笙 / 封茗囧菌
  20. 20 云烟成雨(翻自 房东的猫) 周玥
  21. 21 情深深雨濛濛 杨胖雨
  22. 22 Five Hundred Miles Justin Timberlake / Carey Mulligan / Stark Sands
  23. 23 斑马斑马 房东的猫
  24. 24 See You Again Wiz Khalifa / Charlie Puth
  25. 25 Faded Alan Walker / Iselin Solheim
  26. 26 Natural J.Fla
  27. 27 New Soul Vox Angeli
  28. 28 ハレハレヤ(朗朗晴天)(翻自 v flower) 猫瑾
  29. 29 像鱼 王贰浪
  30. 30 Bye Bye Bye Lovestoned
  31. 31 Blame You 眠 / Lopu$
  32. 32 Believer J.Fla
  33. 33 书信 戴羽彤
  34. 34 柴 鱼 の c a l l i n g【已售】 幸子小姐拜托了
  35. 35 夜空中最亮的星(翻自 逃跑计划) 戴羽彤
  36. 36 慢慢喜欢你 LIve版(翻自 莫文蔚) 戴羽彤
  37. 37 病变(翻自 cubi) 戴羽彤
  38. 38 那女孩对我说 (完整版) Uu
  39. 39 绿色 陈雪凝
  40. 40 月牙湾 LIve版(翻自 F.I.R.) 戴羽彤
夜空中最亮的星(翻自 逃跑计划) - 戴羽彤
00:00 / 04:10

夜空中最亮的星 能否听清

那仰望的人 心底的孤独和叹息

夜空中最亮的星 能否记起

那曾与我同行 消失在风里的身影

我祈祷拥有一颗透明的心灵

和会流泪的眼睛

给我再去相信的勇气

越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请指引我靠近你

夜空中最亮的星 是否知道

那曾与我同行的身影 如今在哪里

夜空中最亮的星 是否在意

是等太阳先升起 还是意外先来临

我宁愿所有痛苦都留在心底

也不愿忘记你的眼睛

哦 给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行 哒~

我祈祷拥有一颗透明的心灵

和会流泪的眼睛 哦

给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行

post请求阻塞问题回顾

前言

昨天在处理post 请求的时候,遇到了socketinputstream被阻塞的情况,前前后后查了很多资料,试了很多方法,但是问题依然无法解决。

我甚至还去看了Tomcat的源码,也没发现好的解决思路,但是在查资料的过程中,我已经找到问题的原因了,所以今天主要是来梳理下问题的原因,总结下经验,让各位小伙伴在以后遇到类似问题的时候,可以少踩坑,少走弯路。

问题的原因

问题的原因很简单,就是因为我们socket实现用的是传统的I/O流,这种实现有一个显著的缺点——阻塞,因为本身它就是阻塞是通信。

这种实现方式下的socket通信处理过程是这样的:客户端像服务器端发起访问请求(假设服务器已经启动),服务器端接受访问请求后,开始建立通信(InputStreamOutputStream),但是线路只有一条,发送消息的时候不能接收消息,接收消息的时候也是不能发送消息的。所以,在实际数据传输的时候,服务端必须接受完客户端的所有消息后,才能返回响应消息。

在我们的项目中,阻塞就发生在接收消息阶段,服务器端一直在接收客户端消息,消息没有接受完成,通信管路被占用,所以客户端无法接收到响应。

这里还不得不说更详细的原因,也就是消息接收一直不完成的原因。我们都知道,socket通信是依赖InputStreamOutputStream流的,我们这里阻塞就是因为InputStream,在处理客户端请求的时候,我们需要不断地从InputSteam中读取数据,但是InputStreamread方法都是阻塞的,也就是说它读不到数据的时候,就一直等在那里等待客户端的数据,因为它不知道客户端的什么时候可以传完,这样线程就被阻塞了,后续业务也就无法处理。

read方法,按照官方给的文档,读取完成后应该返回null或者-1,在读取文件的的时候,是可以正常终止的,但是由于socket本身传输数据形式的特殊性,这个返回结果基本上是不会出现的。也就是说,如果已经没有数据了,你还在读取,这时候只会让线程阻塞。

如果这个时候,客户端终止请求,服务端就知道数据传输完了,线程就不再阻塞了,但是由于连接断开了,服务器的响应数据也就无法传给客户端了。

针对这个问题,大致有两种解决方案,一种就是客户端在发送数据最开始就告诉服务器,他要发送多少数据,然后服务器按照数据传输大小,终止读取。

我们之前有做过一个和银行对接的项目,用的就是socket,当时的约定的规范就是先在消息最开始发送本次消息大小,然后再拼接上消息内容,这样服务器可以先接收一个int的消息大小,然后后续数据再根据这个大小去读取,也就不会出现阻塞的情况。

另一种解决方案是在消息传输结束加一个结束符号。我们在最开始的get请求处理实现中,就是根据消息最后的空行(\r\n),如果读到这个内容,后续就不再读取在,这样就不会发生阻塞。

不知道大家还记不记得我们昨天说的请求头的知识点:

post请求中,请求头与请求体之间是有一个空行的,但是在请求体结束后,并没有结束标识,所以无法确定啥时候请求体完成,这就导致了我们前面说的阻塞。

也有资料说,在post请求头中增加content-length,可以解决这个问题,从理论上讲应该没啥问题,但是我在实际测试的时候,发现也有问题,有时间再研究下。

总结

任何技术的诞生和出现,都是因为其他技术的缺陷或者局限性。Nio就是在这样的背景之下出现的,Nio全称就是new I/O,表面它是一种新的实现方式的I/O,它是一种非阻塞式流,它可以让你在读的同时,实现的操作,而且目前NIO的应用特别广泛,netty就是基于Nio构建的一个web框架。

说了这么多,其实就想说一句,如果某种实现方式满足不了当下的业务需求,那就换种实现方式继续战斗。只要思想不滑坡,办法总比问题多😹

另外需要补充说明下,后面我会再试下content-length的方式,如果还是解决不了这个问题,就打算直接上NIO

posted @ 2021-06-09 13:41  云中志  阅读(819)  评论(0编辑  收藏  举报