diff --git a/data/config.example.ini b/data/config.example.ini index 27ac741..28384ae 100644 --- a/data/config.example.ini +++ b/data/config.example.ini @@ -48,7 +48,7 @@ translation_cache_size = 50000 # **The following is for translation team. Leave it default if you don't know its meaning** # ------------------------------------------------------------------------------------------------- -# 翻译器配置,索引到下面的配置节。可以以逗号分隔配置多个翻译器,翻译时会使用当前第一个可用的翻译器 +# 翻译器配置,索引到下面的配置节。可以以逗号分隔配置多个翻译器,翻译时会自动负载均衡 # 配置多个翻译器可以增加额度、增加QPS、容灾 # 不同配置可以使用同一个类型,但要使用不同的账号,否则还是会遇到额度、调用频率限制 translator_configs = tencent_translate_free,bilibili_translate_free diff --git a/models/translate.py b/models/translate.py index 7ca74a2..928d083 100644 --- a/models/translate.py +++ b/models/translate.py @@ -103,14 +103,25 @@ def translate(text) -> Awaitable[Optional[str]]: future.set_result(res) return future + # 负载均衡,找等待时间最少的provider + min_wait_time = None + min_wait_time_provider = None for provider in _translate_providers: - if provider.is_available: - _text_future_map[key] = future - future.add_done_callback(functools.partial(_on_translate_done, key)) - provider.translate(text, future) - return future + if not provider.is_available: + continue + wait_time = provider.wait_time + if min_wait_time is None or wait_time < min_wait_time: + min_wait_time = wait_time + min_wait_time_provider = provider - future.set_result(None) + # 没有可用的 + if min_wait_time_provider is None: + future.set_result(None) + return future + + _text_future_map[key] = future + future.add_done_callback(functools.partial(_on_translate_done, key)) + min_wait_time_provider.translate(text, future) return future @@ -137,6 +148,10 @@ class TranslateProvider: def is_available(self): return True + @property + def wait_time(self): + return 0 + def translate(self, text, future): raise NotImplementedError @@ -155,6 +170,10 @@ class FlowControlTranslateProvider(TranslateProvider): def is_available(self): return not self._text_queue.full() + @property + def wait_time(self): + return self._text_queue.qsize() * self._query_interval + def translate(self, text, future): try: self._text_queue.put_nowait((text, future))