Java web server http 请求的一个疑惑
事情是这样,我们现在的 web server 遇到了问题,准备用 java 重写一个,现在有一个疑惑想问大家遇到这种情况如何处理
用户打开连接,进来一个 http 请求,按照我们技术说的,这个 http 请求必须在这个连接内返回。但是有可能这次请求加载的数据很慢,比如要读写数据库,那么问题来了:
1.一个 http 请求必须要在这个连接内返回完成吗?不管需要多长时间?是否可以过后再同步数据
2.如果必须要在一个连接内完成,那么一个 http 请求就对应一个线程?(不管是用线程池还是其他方案实现)
3.如果一个 http 请求对应一个线程,是不是在 web server 领域没有所谓的数据库线程?每次操作都在当前的线程内完成
原谅问这么入门级的问题,因为原来不是搞 web server 的,现在突然紧急,硬头皮上
----------------------- 以下是精选回复-----------------------
答:1. 可以不在一个连接里完成,这种叫异步接口
2. web server 的服务端的并发模型可以是多进程、多线程、reative io 、协程、或者两种模型的混合,Java 主流是 Servlet,是多线程的模型,在不讨论线程池这样的细节的情况下,一般一个请求对应一个线程,当然你可以在这个线程里创建出另外一个线程,这也是实现异步接口的一种方式
3. 一般数据库操作和其他逻辑是在同一个线程里的
答:后台的业务处理用异步处理就行了,用线程池去执行任务也行,响应能立刻返回,那么给前端的提示可能就是正在处理,请稍后查询。
答:对,连接断了,后面客户端主动再次发起新的请求来查询处理结果;你说的这种推送方式也可以,可以用 websocket 来保持独立的长连接,你的逻辑处理完了需要查找到使用的 websocket 连接来推送数据,另外一种推送是 comet,基于 http 的长连接,这个本质上其实是同步的,所以连接不能关,但是客户端可以实现异步的流程效果
答:同步异步 bionio 是看业务设计,性能优化可以使用线程池 Completablefuture 等等
答:tomcat nio 或者 arp 都是这样的协议,如果你的服务需要处理大量连接,但是每个连接的的负载很小,通过 IO 多路复用的方式,acceptor 线程绑定端口获取新的连接,然后将连接注册到一个或几个 selector 上,selector 通过 poll 或者 epoll 的方式管理多个连接,当 IO 事件到达时,将从连接中拿到实际的请求分配给实际的工作线程处理。这样连接和线程不是绑定。一个 http 请求肯定需要通过一个工作线程去处理,问题在于是在请求到达时分配工作线程还是连接建立时分配。BIO 的方式在连接到达时分配,每个线程管理一个连接,连接不关闭且负载不高时,这部分资源就是浪费的。NIO 是用少量的线程管理大量的连接。负载取决与实际的 http 请求而非连接数。
答:这不是什么代码实现问题,是业务逻辑和产品设计的问题。
答:你说这个 web server 不会是 web 容器吧?
答:按照楼主的业务需求,异步通信是一个解决办法:A 、B 两个服务(或者父子线程)的通信,B 的业务处理时长很长的时候,A 通过异步调用 B 以后,让 B 自己去处理复杂的业务,而 A 可以立即反馈给客户端一个结果,而不是阻塞等待 A 的执行结果的反馈。至于后期 B 执行成功或者失败,可以再发起一次查询请求,或者 B 执行完以后,由 B 的业务逻辑发起一个客户端的通知反馈都是可以的。
答:这和你的业务逻辑有关啊,如果客户端或前端逻辑就是同步等待响应结果,那必然是等服务端响应了才行,如果能接受异步逻辑,那就建长连或者长轮询搞成异步就可以了,当然靠用户手动刷新获取结果也是个方案。要是怕服务端出现线程和连接耗尽的问题,可以使用 nio 实现的 web 容器替代 bio 的,比如 jetty 之类的,然后调大 backlog,增加业务线程池上限就可以了。
答:说个楼上没提到的解决方案:server sent event 。可以做到一次请求长链接多次响应。浏览器端和 spring mvc 服务器端都有标准实现,细节我就不说了。
答:问题基本是你们的业务研发太菜……
对于慢返回的连异步请求都不会
0条评论