场景:
行为:
当用户进入网站时,他们会收到一份图书列表。其中一些已经出现在他们的“稍后阅读”列表中,有些则没有。
用户在每本书旁边都有一个指示,告诉他们是否将书添加到列表中。
我的问题
我正在辩论哪一种选择是我的理想选择。
选项1:
Pro:对服务器的请求非常小,并且响应非常容易(真或假)。
Con:在一个包含30本书的页面中,我将发送30个单独的http请求,这些请求可以阻止套接字,并且考虑到浏览器和服务器必须对每个事务执行整个握手,速度相当慢。
备选方案2:
Pro:我只提出一个请求,并同时更新所有书籍的指示符。
Con:“稍后阅读”列表可能有数百本书,而传递一个大数组可能会被证明是缓慢和过度的。特别是当屏幕上没有出现30本书,但只有2-3本时.(也就是说,我想检查列表中是否有一本书,为此,我让服务器从列表中向客户机发送整个图书列表)。
So,
你会用哪种方式来最大化性能:1还是2?
我还有其他选择吗?
发布于 2017-04-29 07:40:26
选项1听起来不错,但在可伸缩性方面有一个很大的问题。
选项2缓解了这个可伸缩性问题,我们可以改进它的设计:
客户端,通过javascript,只收集一次显示的图书ids和查询一次,通过ajax获取一系列阅读--稍后的信息,仅用于这30本书。通过这种方式,您仍然可以快速地为页面提供服务,并请求一小组附加信息,一次只需一个http请求。
服务器端,您可以进一步提高缓存内存中的每个用户的读-后ids数组。
发布于 2017-04-29 04:42:19
我认为2017年及以后,解决方案更多的不是关于整体性能,而是关于用户体验和用户期望。
现在,用户不允许,而不是,可以容忍延迟。在这个意义上,复杂的用户界面试图尽快响应。因此:如果您可以使用这些小请求来使用户能够快速完成某件事情(而不是等待2秒来等待这个大请求的返回),那么您应该更喜欢这个解决方案。
据我所知,有许多“高保真度”的网站,其中一个网页可能发送50,100个请求。因此,我认为这是常见的做法!
也许它在这里是有帮助的:SE-Radi.net播客第277集在尾部延迟的背景下深入讨论了这个主题。
发布于 2022-05-17 11:56:19
实时测试、解决方案和真实世界数据
这个答案是用JavaScript编写的,包括易于理解的代码示例。
引言
OP询问了向“稍后阅读”API发出请求的最有效方法,每个请求都需要等待一段时间,而后端保存了这本书。
对于这个答案,我创建了一个“读取后”API端点的演示,每个请求都随机地等待从70-130毫秒来保存每本书。
我每一次都在测试30本书。
最后,我们将通过测量我们将采取的每一个操作的专业实际运行时来看到每个方法的最佳结果。
同步请求(OP的选项1)
在这里,我们将通过JS来运行每个调用,一个接一个同步运行。
守则:
async function saveBooksSync() {
console.time('save-books-sync');
// creates 30 book IDs
const booksIds = Array.from({length: 30}, (_, i) => i + 1);
// creates 30 API links for each request
const urls = booksIds.map(bookId => `http://localhost:7777/books/read-later?bookId=${bookId}`);
for(let url of urls) {
const response = await fetch(url);
const json = await response.json();
console.log(json);
}
console.timeEnd('save-books-sync');
}

运行时: 3712.40087890625 ms
一个大请求
虽然我们不会创建到服务器的许多请求连接,但运行时本身就说明了这一点。
守则:
async function saveAllBooksAtOnce() {
console.time('save-all-books')
const booksIds = Array.from({length: 30}, (_, i) => i + 1);
const url = `http://localhost:7777/books/read-later?all=1`;
const response = await fetch(url);
const json = await response.json();
console.timeEnd('save-all-books');
}


运行时: 3486.71484375 ms
并行异步请求(解决方案)
这里发生了神奇的事情,解决方案来问,什么是最有效的请求方法。
这里我们制作了30并行小请求,并取得了惊人的效果。
守则:
async function saveBooksParallel() {
console.time('save-books')
const booksIds = Array.from({length: 30}, (_, i) => i + 1);
const urls = booksIds.map(bookId => `http://localhost:7777/books/read-later?bookId=${bookId}`);
const promises = urls.map((url) =>
fetch(url).then((response) => response.json())
);
const data = await Promise.all(promises);
console.log(data);
console.timeEnd('save-books');
}

在这个异步并行示例中,我使用了Promise.all方法。
Promise.all()方法将可迭代的承诺作为输入,并返回一个解析为输入承诺的结果数组的承诺
运行时: 668.47705078125 ms
结论
结果很清楚,发出这些多个请求的最有效方法是在异步并行中这样做。
更新:我遵循@Iglesias的请求删除数据输出的console.log(),因为(大概)它占用了大量的资源。
--这些是运行时的结果:
更新结论:运行时几乎保持不变,从而反映了并行异步请求被速度无法匹配的现实

https://stackoverflow.com/questions/43691808
复制相似问题