PrimeFaces 6.1中p:remoteCommand异步请求为何按6组执行?
这个6个一组的并发限制其实是浏览器的同源HTTP/1.1请求并发数限制,和PrimeFaces的p:remoteCommand或者jQuery本身没有直接关系——你试了autoRun或者手动调用都一样,就是因为这个底层限制在起作用。
为什么会有这个限制?
现代浏览器(比如Chrome、Firefox、Edge)默认对同一域名的HTTP/1.1请求设置了6个左右的并发连接上限——这是HTTP/1.1协议的设计限制,目的是避免单个客户端对服务器造成过大压力。哪怕你用async="true"开启了异步请求,浏览器也会把超出这个数量的请求放进队列,等前面的请求完成后再依次执行。
PrimeFaces 6.1的remoteCommand本质上是封装了jQuery的Ajax请求,而jQuery并不会修改浏览器的这个底层限制,所以不管你怎么配置remoteCommand的属性,都绕不开浏览器的并发数限制。
解决办法:
这里给你几个可行的技术方案,按推荐程度排序:
切换到HTTP/2协议
HTTP/2支持请求多路复用,同一个TCP连接可以同时传输多个请求和响应,完全突破了HTTP/1.1的并发数限制。如果你的服务器支持(比如Tomcat 8.5+、Jetty 9+、WildFly 10+),只需要在服务器配置中开启HTTP/2(通常需要配置SSL证书,因为大部分浏览器只支持HTTPS下的HTTP/2),不需要修改任何PrimeFaces代码,就能让所有异步请求并发执行。合并请求,减少并发数
如果暂时无法切换到HTTP/2,最实用的办法是把多个组件的加载请求合并成一个批量请求。比如:- 修改你的
remoteCommand,让它支持一次性接收多个需要加载的Widget ID:<p:remoteCommand async="true" id="rcLoadWidgets" actionListener="#{dashboardController.loadBatchWidgets}" process="panelGroup" autoRun="true" partialSubmit="true" update="panelWidget @form:btSave" /> - 前端用JavaScript收集所有需要加载的Widget ID,作为参数传给这个命令:
// 假设你有多个需要加载的Widget,先收集它们的ID var targetWidgetIds = ['widget_1', 'widget_2', 'widget_3', ...]; // 调用remoteCommand,传递批量参数 rcLoadWidgets([{name: 'widgetIds', value: targetWidgetIds.join(',')}]); - 后端的
dashboardController里新增loadBatchWidgets方法,拆分传入的ID列表,批量加载数据,最后统一更新对应的组件。这样只需要一个请求就能完成多个Widget的加载,自然不需要担心并发排队的问题。
- 修改你的
域名分片(备选方案)
把请求分散到多个子域名(比如api1.yourdomain.com、api2.yourdomain.com),浏览器会把每个子域名当成独立的源,每个源都有6个并发限制,这样整体并发数就能提升到6×N(N是子域名数量)。不过这个方案需要额外配置服务器和DNS,还要处理跨域请求的问题(比如在PrimeFaces中配置跨域支持),相对麻烦一些。
补充说明
PrimeFaces的p:remoteCommand确实没有提供直接设置并发数的属性,因为这个限制根本不在它的控制范围内——它完全由浏览器和HTTP协议决定。你之前尝试的autoRun、手动调用等操作,只是改变了请求的触发方式,并没有改变浏览器处理请求的底层规则。
内容的提问来源于stack exchange,提问作者paulo.bing

