Асинхронная конечная точка Tornado не работает

#asynchronous #tornado

#асинхронный #tornado

Вопрос:

У меня есть два микросервиса:

  • служба

Служба Tornado с двумя конечными точками: /foo и /bar

/foo

 async def get(...):
   x = await test()
   return x

async def test():
    y = call to b service, FooBar rpc
    return y
  

/bar

  def get(...):
   return True
  
  • служба b

Служба gRPC с rpc FooBar

 rpc FooBar

def FooBar(...):
   return requests.get("/bar")

  

Если клиент попадает в конечную /foo точку в службе:

  1. Код попадает в rpc FooBar в службе b.
  2. FooBar rpc не может попасть /bar в конечную точку службы, поскольку эта служба заблокирована.

AFAIK, использование x= await test() должно предотвратить такую блокировку, что я пропустил?

Комментарии:

1. await автоматически не делает ваш код неблокирующим. Являются ли эти вызовы rpc асинхронными? Если нет, то это вызовет блокировку.

2. @xyres да, вызов rpc является синхронным. Но проблема в том, что служба tornado заблокирована, а не служба grpc

3. Да, если вызовы rpc не являются асинхронными, они заблокируют процесс tornado (потому что вы выполняете эти вызовы из процесса tornado).

4. @xyres нет способа «обойти» его с помощью вызова rpc sync?

Ответ №1:

Поскольку вызовы rpc не являются асинхронными, это заблокирует процесс Tornado.

Вы можете избежать блокировки основного процесса, запустив вызовы rpc в отдельном потоке.

Во-первых, сделайте test() метод обычной функцией, а не сопрограммой (удалите async ключевое слово).

Пример кода:

 async def get(...): 
    x = await IOLoop.current().run_in_executor(None, test)
    return x

# regular function, not async
def test(...):
    # make calls
    return x