python使用redis实现session_tornado使用redis来实现session分布式存储

原文作者: rfyiamcool 51CTO博客,原文链接:http://blog.51cto.com/rfyiamcool/1406378

为了提供让tornado更接近c10的能力,只能用nginx来处理tornado不太擅长的静态文件及用多app方案来提高负载能力。

我人比较的懒,把接口和平台的页面都做成一个py了,用upstream不好做负载,如果你用ip_hash,或者insert cookie的方式,虽然保证了针对后端服务器的命中,但是哥还就不想命中。

我还就想rr轮训,为啥? 因为页面上大量的耗时间的io和计算请求,这个时候我总是命中调度到一台服务器,那我就会一直的等待,后面还有一堆的任务也都在同步堵塞着。。。太痛快啦,这个时候就需要rr轮训,session如何的一致性,这个时候就需要一个快速的存储来保证session cookie的存储。

以前更多是用tornado memcached来存储session或者cookie,因为报警平台中已经在用redis、mongodb这些nosql数据库,没必要再配置memcached了。 这次用我钟爱的redis了。

这里导入了相关的类和库,login_required是装饰器,专门来判断用户登录了没有,没有的话把访问扔给login.html页面。

#xiaorui.cc

from base importBaseHandlerfrom tornado.web importHTTPErrordeflogin_required(f):def _wrapper(self,*args, **kwargs):printself.get_current_user()

logged=self.get_current_user()if logged ==None:

self.write('no login')

self.finish()else:

ret= f(self,*args, **kwargs)return_wrapperclassApplication(tornado.web.Application):def __init__(self):

settings=dict(

cookie_secret= "e446976943b4e8442f099fed1f3fea28462d5832f483a0ed9a3d5d3859f==78d",

session_secret= "3cdcb1f00803b6e78ab50b466a40b9977db396840c28307f428b25e2277f1bcc",

session_timeout= 60,

store_options={'redis_host': 'localhost','redis_port': 6379,'redis_pass': '',

},

)

handlers=[

(r"/", MainHandler),

(r"", MainHandler),

(r"/login", LoginHandler)

]

tornado.web.Application.__init__(self, handlers, **settings)

self.session_manager= session.SessionManager(settings["session_secret"], settings["store_options"], settings["session_timeout"])

关联的两个类:

classMainHandler(BaseHandler):

@login_requireddefget(self):

username=self.get_current_user()print 'start..'

printusernameprint self.session['nima']if username==None:

self.write('nima')else:

self.write("What's up," + username + "?")classLoginHandler(BaseHandler):defget(self):

self.session["user_name"] = self.get_argument("name")

self.session["nima"] = 'xiaorui.cc'self.session.save()

self.write('你的session已经欧了')

处理session的文件 !

#/usr/bin/python#coding: utf-8

importuuidimporthmacimportujsonimporthashlibimportredisclassSessionData(dict):def __init__(self, session_id, hmac_key):

self.session_id=session_id

self.hmac_key=hmac_key#@property#def sid(self):#return self.session_id#@x.setter#def sid(self, value):#self.session_id = value

classSession(SessionData):def __init__(self, session_manager, request_handler):

self.session_manager=session_manager

self.request_handler=request_handlertry:

current_session=session_manager.get(request_handler)exceptInvalidSessionException:

current_session=session_manager.get()for key, data incurrent_session.iteritems():

self[key]=data

self.session_id=current_session.session_id

self.hmac_key=current_session.hmac_keydefsave(self):

self.session_manager.set(self.request_handler, self)classSessionManager(object):def __init__(self, secret, store_options, session_timeout):

self.secret=secret

self.session_timeout=session_timeouttry:if store_options['redis_pass']:

self.redis= redis.StrictRedis(host=store_options['redis_host'], port=store_options['redis_port'], password=store_options['redis_pass'])else:

self.redis= redis.StrictRedis(host=store_options['redis_host'], port=store_options['redis_port'])exceptException as e:printedef_fetch(self, session_id):try:

session_data= raw_data =self.redis.get(session_id)if raw_data !=None:

self.redis.setex(session_id, self.session_timeout, raw_data)

session_data=ujson.loads(raw_data)if type(session_data) ==type({}):returnsession_dataelse:return{}exceptIOError:return{}def get(self, request_handler =None):if (request_handler ==None):

session_id=None

hmac_key=Noneelse:

session_id= request_handler.get_secure_cookie("session_id")

hmac_key= request_handler.get_secure_cookie("verification")if session_id ==None:

session_exists=False

session_id=self._generate_id()

hmac_key=self._generate_hmac(session_id)else:

session_exists=True

check_hmac=self._generate_hmac(session_id)if hmac_key !=check_hmac:raiseInvalidSessionException()

session=SessionData(session_id, hmac_key)ifsession_exists:

session_data=self._fetch(session_id)for key, data insession_data.iteritems():

session[key]=datareturnsessiondefset(self, request_handler, session):

request_handler.set_secure_cookie("session_id", session.session_id)

request_handler.set_secure_cookie("verification", session.hmac_key)

session_data=ujson.dumps(dict(session.items()))

self.redis.setex(session.session_id, self.session_timeout, session_data)def_generate_id(self):

new_id= hashlib.sha256(self.secret +str(uuid.uuid4()))returnnew_id.hexdigest()def_generate_hmac(self, session_id):returnhmac.new(session_id, self.secret, hashlib.sha256).hexdigest()classInvalidSessionException(Exception):pass

tornado每个控制器相关的class ~

importtornado.webimportsysimportsessionclassBaseHandler(tornado.web.RequestHandler):def __init__(self, *argc, **argkw):

super(BaseHandler, self).__init__(*argc, **argkw)

self.session=session.Session(self.application.session_manager, self)defget_current_user(self):return self.session.get("user_name")

对于登录注册session:

self.session["user_name"] = self.get_argument("name")

self.session["nima"] = 'xiaorui.cc'self.session.save()

对于退出登录:

self.session["nima"] =None

self.session.save()

其实就改成None就行了,匹配都在装饰器那边搞好了。

偶了,这就可以了。用之前要配置下相关的组件!

pip installujson redis

pipinstall tornado

session.py 代码来自:

git clone https://github.com/zs1621/tornado-redis-session

这老外写的有点简陋,说明几乎没有,还好tornado redis session本身就是不难的东西,看看就能搞定。

单个tornado我现在已经可以顶到1500个长连接不崩溃了,如果加上ngixn做tornado的分发负载,估计连接在6k问题不大。就算是接入所有业务的邮件转发问题也不大,估计问题都在邮件网关上了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值