Веб-сайты Tornado с mysql и redis

93
12

У меня есть сервер торнадо, который создаст веб-соединение с клиентами. Всякий раз, когда клиент запрашивает некоторые данные, мне нужно получить его из Redis или MySQL-DB. В дополнение к этому мне нужно слушать трансляцию с сервера торнадо, получать сетевые пакеты и отправлять их клиентам, если они подписаны на данные. Эта передача широковещательных пакетов клиенту зависит от токена, который будет присутствовать в пакете. Если клиенты подписаны на токен, мы должны отправить ему пакет.

Ставка запроса:

5000 активных сетевых разъемов (что может увеличиться) 1-БД-запрос на сокет-соединение в секунду, так что всего 5000 DB-запросов/секунду 1-Redis-запрос на сокет-соединение в секунду, так что сумма 5000 Redis-запросов/секунду. В широковещательном режиме я должен прослушивать 1000 пакетов в секунду и проверять, подписан ли какой-либо из подписчиков на токен.

Я знаю, что redis однопоточный и работает асинхронно (исправьте меня, если я ошибаюсь). Для асинхронного драйвера MySQL-DB, который я использую, является "tormysql" (большинство моих вызовов в БД - это выбор запросов и никаких сложных операций с БД).

Мой вопрос:

Будет ли вызов в MySQL-DB блокироваться? Если они блокируют вызов, я могу запустить другой поток/процесс только для запросов БД? Есть ли шанс, что торнадо упадет в эфир? У меня может быть балансировка нагрузки перед моими ресурсами и серверы, но возможно ли, что я могу использовать один процессор с 2-ядерным 8-ГБ оперативной памятью?

Обновление 1:
Я написал код для MySQL:
Server.py

import logging
import tornado.escape
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.websocket
import os.path
import uuid
import sys
from tornado import gen

from tornado.options import define, options

import tormysql ## MySQL async driver
pool = tormysql.ConnectionPool(
max_connections = 20, #max open connections
idle_seconds = 7200, #conntion idle timeout time, 0 is not timeout
wait_connection_timeout = 3, #wait connection timeout
host = "127.0.0.1",
user = "test",
passwd = "",
db = "testdb",
charset = "utf8"
)

define("port", default=8000, help="run on the given port", type=int)

class Application(tornado.web.Application):
def __init__(self):
handlers = [
(r"/", MainHandler),
(r"/dataSock", ChatSocketHandler),
]
settings = dict(
cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__",
template_path=os.path.join(os.path.dirname(__file__), "templates"),
static_path=os.path.join(os.path.dirname(__file__), "static"),
xsrf_cookies=True,
)
super(Application, self).__init__(handlers, **settings)

class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render("indexWS.html")

class ChatSocketHandler(tornado.websocket.WebSocketHandler):
openConnCount = 0
def get_compression_options(self):
# Non-None enables compression with default options.
return {}

def open(self):
# print("Socket open:%s"%(self))
ChatSocketHandler.openConnCount += 1
None
def on_close(self):
# print("Socket closed:%s"%(self))
ChatSocketHandler.openConnCount -= 1
None

async def on_message(self, message):
logging.info("open conn count %r", ChatSocketHandler.openConnCount)
returnDB = await getDataFromDB()
self.write_message("server got this from you:%s"%(str(returnDB)))

@gen.coroutine
def getDataFromDB():
with (yield pool.Connection()) as conn:
try:
with conn.cursor() as cursor:
yield cursor.execute("SHOW TABLES;")
# print(cursor.fetchall())
except:
yield conn.rollback()
else:
yield conn.commit()

with conn.cursor() as cursor:
yield cursor.execute("SELECT * FROM theme;")
datas = cursor.fetchall()

return datas

# yield pool.close()
def main():
tornado.options.parse_command_line()
app = Application()
# print "options:", options
# sys.exit()
app.listen(options.port)
print("PORT:%s"%(options.port))
tornado.ioloop.IOLoop.current().start()

if __name__ == "__main__":
main()

Теперь, когда я тестирую этот код с помощью этого:
Client.py

import asyncio
import websockets

async def hello(i):
async with websockets.connect('ws://localhost:8000/dataSock') as websocket:
name = 'A'#input("What your name? ")
print("******************************%s******************************"%(i))
for j in range(100):
await websocket.send(name)
# print("> {}".format(name))

greeting = await websocket.recv()
print("{}: {}".format(i, len(greeting)))
asyncio.sleep(10)

async def start():
for i in range(10):
await hello(i)
print("end")
asyncio.sleep(20)
asyncio.get_event_loop().run_until_complete(start())
# asyncio.get_event_loop().run_forever()

Если я запускаю один экземпляр кода, все работает хорошо. Когда я увеличиваю количество клиентов до 70 (70 экземпляров клиента), есть задержка в ответе, который я получаю.

2-е объяснение вопроса:
Сервер Tornado должен прослушивать какой-то порт, на котором я буду получать сетевые пакеты, которые я должен отправить на клиентов, если они подписаны. Так будет ли вероятность того, что эти пакеты будут удалены?

спросил(а) 2018-04-26T11:40:00+03:00 2 года, 7 месяцев назад
1
Решение
59

Будет ли вызов в MySQL-DB блокироваться? Если они блокируют вызов, я могу запустить другой поток/процесс только для запросов БД?

Как вы уже упоминали, вы используете tormysql в качестве драйвера, поэтому нет, вызовы не будут блокироваться, поскольку tormysql является асинхронным.

Есть ли шанс, что торнадо упадет в эфир?

Я не совсем понимаю, что вы подразумеваете под этим. Но так как протокол websocket построен на TCP, поэтому доставка всех пакетов гарантирована. TCP позаботится об этом.

У меня может быть балансировка нагрузки перед моими ресурсами и серверы, но возможно ли, что я могу использовать один процессор с 2-ядерным 8-ГБ оперативной памятью?

Да.

Я думаю, что вы задумываетесь над своим выражением. Преждевременная оптимизация - зло. Вы еще не написали код, и вы думаете о производительности. Это просто тратит ваше время.

Сначала напишите код, затем стресс проверите его, чтобы увидеть, сколько нагрузки может обрабатывать ваше приложение. Затем сделайте профилирование, чтобы увидеть, где вещи замедляются. Затем вы оптимизируете код или меняете настройки и, возможно, обновляете свое оборудование.

Но просто думать о производительности без написания и стресс-тестирования кода - это просто пустая трата времени.

ответил(а) 2018-04-27T11:26:00+03:00 2 года, 7 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема