Reputation: 139
I have a tornado server which will create web-socket connection with clients. Whenever a client requests for some data I need to get it from either Redis or MySQL-DB. In addition to this I need to listen to broadcast from the tornado server, receive the network packets and send them to the clients if they are subscribed for the data. This sending of broadcast packets to client depends on the token which will be there in the packet. If clients are subscribed to the token we should send the packet to him.
Request rate:
I know redis is single threaded and work asynchronously(correct me if I am wrong). For MySQL-DB asynchronous driver which I am using is `tormysql`(Most of my calls to DB are select queries and no complex DB operations.).
My Question:
Update 1:
I have written a code for 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()
Now when I test this code with this :
Client.py
import asyncio
import websockets
async def hello(i):
async with websockets.connect('ws://localhost:8000/dataSock') as websocket:
name = 'A'#input("What's 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()
If I run a single instance of the code every thing is working good. When I increase the number of clients to 70 (70 instance of the client) there is a delay in the response that I get.
2nd question explanation:
Tornado server has to listen on some port in which I will be receiving the network packets the one which I have to send it to clients if they are subscribed. So will there be a possibility that these packets will be dropped ?
Upvotes: 0
Views: 500
Reputation: 21744
- Will the call to MySQL-DB is blocking? If they are blocking call can I run different thread/process just for DB queries?
As you mentioned you're using tormysql
as the driver, so no, the calls won't block since tormysql
is asynchronous.
- Is there a chance that tornado drop packets on the broadcast?
I don't quite understand what you mean by that. But since the websocket protocol is built on TCP, so delivery of all the packets is guaranteed. TCP takes care of that.
- I can have a load-balancer in front of my resources and server them but is it possible that I can use a single CPU with 2-cores 8-GB RAM?
Yes.
I think you're overthinking your application at this point. Premature optimization is evil. You haven't written any code yet and you're thinking about performance. It's just wasting your time.
Write the code first, then stress test it to see how much load can your application handle. Then do profiling to see where the things are slowing down. Then you optimize the code, or change your setup and maybe upgrade your hardware.
But just thinking about performance without writing and stress testing the code is just a waste of time.
Upvotes: 1