使用协程调用多个 API 会导致错误

Calling multiple APIs using Coroutines causes error

提问人:kotlin_noob 提问时间:3/2/2023 最后编辑:kotlin_noob 更新时间:3/2/2023 访问量:238

问:

我有一个包含 30 个对象的列表,我需要为其调用 API。然后,我将所有 API 调用的结果添加并返回为答案。但是在几次调用后它给出了503错误。

override suspend fun getScoreboard(docId: String): ScoreboardResult {
        val scoreboardResult = ScoreboardResult()
        try {
            withContext(Dispatchers.IO) {
                val cfHandles = getCfHandles(docId = docId)
                val contests = getContests(docId = docId).split(";")
                Log.d(TAG, "contests size = ${contests.size}  ===>  $contests")
                Log.d(TAG, Thread.currentThread().toString())
                for(contest in contests) {
                    val options = hashMapOf("contestId" to contest, "handles" to cfHandles)
                    Log.d(TAG, "Doing contest: $contest")
                    lateinit var contestScore: PartiesScore
                    ////delay(1500)//todo: Avoid using this delay
                    launch {
                        Log.d(TAG, Thread.currentThread().toString())
                        contestScore = getPartiesScore(options= options)//suspend function (Api call)
                        if (contestScore.status == Constants.CF_API_SUCCESS_STATUS) {
                            Log.d(TAG, "Success $contest")
                            scoreboardResult.updateScore(contestScore.result.rows)
                        } else {
                            throw (CustomException(message = "Failed at contest: $contest"))
                        }
                    }
                }
            }
            Log.d(TAG, "Everything went well")
            return scoreboardResult
        } catch (exception: Exception) {
            Log.d(TAG, "Something bad happened : ${exception.message}")
            scoreboardResult.exception = exception
            return scoreboardResult
        }
    }

这是我的logcat:---

18:20:51.491  D  contests size = 30  ===\>  \[1711, 1714, 1713, 1712, 1722, 1717, 1726, 1729, 1733, 1738, 1737, 1736, 1741, 1742, 1746, 1743, 1732, 1759, 1761, 1760, 1758, 1764, 1771, 1766, 1762, 1767, 1774, 1772, 1770, 1731\]
18:20:51.491  D  Thread\[DefaultDispatcher-worker-2,5,main\]
18:20:51.492  D  Doing contest: 1711
18:20:51.493  D  Doing contest: 1714
18:20:51.494  D  Thread\[DefaultDispatcher-worker-3,5,main\]
18:20:51.494  D  Doing contest: 1713
18:20:51.495  D  Thread\[DefaultDispatcher-worker-1,5,main\]
18:20:51.496  D  Doing contest: 1712
18:20:51.496  D  Thread\[DefaultDispatcher-worker-4,5,main\]
18:20:51.497  D  Doing contest: 1722
18:20:51.497  D  Thread\[DefaultDispatcher-worker-7,5,main\]
18:20:51.498  D  Doing contest: 1717
18:20:51.498  D  Thread\[DefaultDispatcher-worker-6,5,main\]
18:20:51.499  D  Doing contest: 1726
18:20:51.501  D  Thread\[DefaultDispatcher-worker-5,5,main\]
18:20:51.502  D  Doing contest: 1729
18:20:51.503  D  Doing contest: 1733
18:20:51.503  D  Thread\[DefaultDispatcher-worker-10,5,main\]
18:20:51.503  D  Thread\[DefaultDispatcher-worker-8,5,main\]
18:20:51.503  D  Doing contest: 1738
18:20:51.503  D  Thread\[DefaultDispatcher-worker-11,5,main\]
18:20:51.504  D  Doing contest: 1737
18:20:51.504  D  Thread\[DefaultDispatcher-worker-9,5,main\]
18:20:51.504  D  Doing contest: 1736
18:20:51.504  D  Thread\[DefaultDispatcher-worker-13,5,main\]
18:20:51.504  D  Doing contest: 1741
18:20:51.505  D  Thread\[DefaultDispatcher-worker-12,5,main\]
18:20:51.506  D  Doing contest: 1742
18:20:51.506  D  Thread\[DefaultDispatcher-worker-14,5,main\]
18:20:51.511  D  Doing contest: 1746
18:20:51.511  D  Thread\[DefaultDispatcher-worker-4,5,main\]
18:20:51.511  D  Thread\[DefaultDispatcher-worker-14,5,main\]
18:20:51.512  D  Doing contest: 1743
18:20:51.512  D  Doing contest: 1732
18:20:51.513  D  Doing contest: 1759
18:20:51.514  D  Thread\[DefaultDispatcher-worker-7,5,main\]
18:20:51.514  D  Doing contest: 1761
18:20:51.515  D  Thread\[DefaultDispatcher-worker-13,5,main\]
18:20:51.516  D  Doing contest: 1760
18:20:51.516  D  Thread\[DefaultDispatcher-worker-12,5,main\]
18:20:51.516  D  Thread\[DefaultDispatcher-worker-16,5,main\]
18:20:51.517  D  Doing contest: 1758
18:20:51.517  D  Thread\[DefaultDispatcher-worker-4,5,main\]
18:20:51.518  D  Doing contest: 1764
18:20:51.518  D  Thread\[DefaultDispatcher-worker-15,5,main\]
18:20:51.518  D  Thread\[DefaultDispatcher-worker-9,5,main\]
18:20:51.520  D  Doing contest: 1771
18:20:51.521  D  Doing contest: 1766
18:20:51.521  D  Thread\[DefaultDispatcher-worker-12,5,main\]
18:20:51.521  D  Thread\[DefaultDispatcher-worker-15,5,main\]
18:20:51.522  D  Doing contest: 1762
18:20:51.523  D  Doing contest: 1767
18:20:51.523  D  Thread\[DefaultDispatcher-worker-14,5,main\]
18:20:51.525  D  Doing contest: 1774
18:20:51.525  D  Thread\[DefaultDispatcher-worker-9,5,main\]
18:20:51.527  D  Doing contest: 1772
18:20:51.527  D  Doing contest: 1770
18:20:51.527  D  Thread\[DefaultDispatcher-worker-4,5,main\]
18:20:51.528  D  Thread\[DefaultDispatcher-worker-12,5,main\]
18:20:51.528  D  Thread\[DefaultDispatcher-worker-14,5,main\]
18:20:51.528  D  Doing contest: 1731
18:20:51.530  D  Thread\[DefaultDispatcher-worker-2,5,main\]
18:20:52.936  D  Success 1712
18:20:52.964  D  Something bad happened : HTTP 503

如果我故意延迟大约 1000-2000 毫秒(就在启动块之前),那么所有 API 调用都成功,但没有延迟,它会出错。 我觉得是创建了太多的协程,导致了 503 响应。

由于我有 30 场比赛,并且每场比赛都使用延迟会给人带来糟糕的用户体验。

有没有办法在不使用延迟的情况下成功完成所有 API 调用?

android kotlin retrofit2 kotlin-coroutines android-networking

评论

0赞 Tenfour04 3/2/2023
503 可能是服务器的一个限制(请参阅下面的答案)。但我也看到了一些错误。所有子协程共享该变量。因此,在任何一个协程中,它都可以写入变量,然后当它读取变量时,它可能已被另一个同级协程更改。其次,如果您以这种方式使用它,则需要通过互斥锁进行内部安全。如果它根本不是线程安全的,它将产生意想不到的结果。如果同步,它将阻塞协程线程,这是不可取的。contestScoreScoreboardResult.updateScore()
0赞 kotlin_noob 3/2/2023
是的,我已经同步了 updateScore() 函数,到目前为止它没有任何问题。
0赞 Tenfour04 3/2/2023
我是说最好让它们挂起并使用互斥锁,这样您就不会不必要地阻止协程线程池中的线程。但是你的变量也不是线程安全的。contestScore

答:

0赞 adn97 3/2/2023 #1

有一个循环并同时启动大量请求不是一个好的做法。503 表示服务器以某种方式超载或阻止您的呼叫。

如果您有权访问 API,则只需一次调用即可处理此请求,其中将所有选项传输到一个选项中,然后 API 应返回一个包含所有分数的数组。

评论

0赞 kotlin_noob 3/2/2023
不幸的是,API 端点一次只提供一个比赛分数。对于“n”次比赛,我需要称它为“n”次。
0赞 adn97 3/2/2023
我想您必须处理服务器限制并使用尽可能小的延迟。糟糕的 API 需要糟糕的客户端解决方案。