使用 Typescript/JS 测试并发性

问题描述 投票:0回答:1

我正在开发一个 TS 应用程序,我需要测试一些并发代码以及它如何与数据库交互(代码处理幂等性)。我想验证修改同一资源的多个请求是否会正确应用更改或失败,而不是丢失更新或处理两次。

我在 Java 中测试这一点有很多经验(因为它有大量并发原语,如信号量、屏障和其他控制并发和并行性的东西),但我正在努力弄清楚如何在 TS 中做到这一点。

例如,在 Java 中,我会启动 2 个线程,与 2 方传递

CyclicBarrier
。两个线程都会执行到屏障,互相等待,然后继续。通过这种方式,我通常可以确保代码按预期工作。如果我不能 100% 确保代码并行运行,我会多次运行同一时间或使用更多线程来增加并行执行的机会。

我在 JS 中找不到任何并发原语可以让我做类似的事情。我发现最好的方法是对共享值进行繁忙的等待。有些博客建议使用工作线程。

通常如何完成此操作有什么建议吗?这是一个困难的话题,因此感谢博客、文章和书籍的链接!

javascript typescript testing concurrency
1个回答
0
投票

需要指出的是,与 Java 或其他语言不同,JS(本例中为 TS)是单线程的。意味着同一时间只有一行TS/JS在运行。有很多方法可以解决这个问题(例如 WebWorkers),但我假设您在这种情况下没有使用它们。

如果您计划在运行两个应用程序实例的任何环境中使用您的库,那么您就有两个真正的并行系统。对于第一部分,我假设情况并非如此。

测试单节点进程并发度

本例非常简单,全部依赖于 JS 事件循环。 Philip Roberts 在 JSConf 上就这个主题做了一次精彩的演讲。

使用单节点进程和(我假设)“异步”函数,Promise 是并发执行的。但是,当您执行某些异步操作(IO、Web 请求等...)时,会发生异步函数的让步(让其他代码运行)

在这种情况下测试你的库的最简单方法可能是:

function test() {
    Promise.all([
        doSomething(),
        doSomething(),
    ]);
}

在多进程环境中测试并发

也许您的应用程序同时在多台计算机上运行。在这种情况下,事情就变得非常复杂。我们无法轻松测试这一点,主要是因为我们无法启动直接调用该函数的测试。我们需要启动两个进程并“同时”调用它们。

我强烈建议不要这样做,如果您正在测试的操作非常快,则可能会导致不稳定的测试。确保事情完全同时执行确实很难。

也许更好的解决方案是引入人为延迟。使关键部分花费相当多的时间(可能几秒钟)并依次调用两个实例。您还可以

Promise.all()
调用以获得最大并发性。尽管这并不是真正的问题,但如果关键部分需要几秒钟的时间。这样你就可以确定事情不会出现问题。

我将把“生成和调用两个进程”部分留给您。您可以创建一个 Web Worker,它在节点中创建一个新的 V8 执行上下文。或者制作一个简单的 http 服务器并通过它发送。

如果您不喜欢第二种解决方案

我不知道有什么比 JS 的单线程本质更并行的了。最简单的解决方案可能是用其他东西编写一个小脚本来测试此行为。我不太了解 Java,但 Rust 的并发原语非常好。虽然“调用 JS”部分变得有点困难。

    

© www.soinside.com 2019 - 2024. All rights reserved.