• Tornado之自定义session


     

    面向对象基础

    面向对象中通过索引的方式访问对象,需要内部实现 __getitem__ 、__delitem__、__setitem__方法

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
       
    class Foo(object):
       
        def __getitem__(self, key):
            print  '__getitem__',key
       
        def __setitem__(self, key, value):
            print '__setitem__',key,value
       
        def __delitem__(self, key):
            print '__delitem__',key
       
       
       
    obj = Foo()
    result = obj['k1']
    #obj['k2'] = 'wupeiqi'
    #del obj['k1']

    Tornado扩展

    在tornado的源码中,默认执行Handler的get/post等方法之前默认会执行 initialize方法,所以可以通过自定义的方式使得所有请求在处理前执行操作.

    class BaseHandler(tornado.web.RequestHandler):
       
        def initialize(self):
            self.xxoo = "wupeiqi"
       
       
    class MainHandler(BaseHandler):
       
        def get(self):
            print(self.xxoo)
            self.write('index')
     
    class IndexHandler(BaseHandler):
       
        def get(self):
            print(self.xxoo)
            self.write('index')

    session

    session其实就是定义在服务器端用于保存用户回话的容器,其必须依赖cookie才能实现。

    自定义session_1

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import config
    from hashlib import sha1
    import os
    import time
    
    #生成一个随机的session_id
    create_session_id = lambda: sha1(bytes('%s%s' % (os.urandom(16), time.time()), encoding='utf-8')).hexdigest()
    
    #根据定义好的session存储方式,选择对应的处理方式
    class SessionFactory:
    
        @staticmethod
        def get_session_obj(handler):
            obj = None
    
            if config.SESSION_TYPE == "cache":
                obj = CacheSession(handler)
            elif config.SESSION_TYPE == "memcached":
                obj = MemcachedSession(handler)
            elif config.SESSION_TYPE == "redis":
                obj = RedisSession(handler)
            return obj
    
    
    class CacheSession:
        session_container = {}
        session_id = "__sessionId__"
    
        def __init__(self, handler):
            self.handler = handler
            client_random_str = handler.get_cookie(CacheSession.session_id, None)
            if client_random_str and client_random_str in CacheSession.session_container:
                self.random_str = client_random_str
            else:
                self.random_str = create_session_id()
                CacheSession.session_container[self.random_str] = {}
    
            expires_time = time.time() + config.SESSION_EXPIRES
            handler.set_cookie(CacheSession.session_id, self.random_str, expires=expires_time)
    
        def __getitem__(self, key):
            ret = CacheSession.session_container[self.random_str].get(key, None)
            return ret
    
        def __setitem__(self, key, value):
            CacheSession.session_container[self.random_str][key] = value
    
        def __delitem__(self, key):
            if key in CacheSession.session_container[self.random_str]:
                del CacheSession.session_container[self.random_str][key]
    
    
    class RedisSession:
        def __init__(self, handler):
            pass
    
    
    class MemcachedSession:
        def __init__(self, handler):
            pass

    其中os.urandom(n): 返回n个随机byte值的string,作为加密使用

    自定义session_2(定义存储方式)

    session_app.py:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # pip3 install tornado
    import tornado.ioloop
    import tornado.web
    from Session.session import SessionHandler
    class MainHandler(SessionHandler,tornado.web.RequestHandler):
    
        def get(self):
            self.render('login.html')
    
        def post(self, *args, **kwargs):
            user = self.get_argument('username')
            pwd = self.get_argument('password')
            if user == 'alex' and pwd == '123':
                self.session_obj['is_login'] = True
                self.session_obj['user'] = user
                self.redirect('/index')
            else:
                self.redirect('/main')
    
    class IndexHandler(SessionHandler,tornado.web.RequestHandler):
        def get(self):
            current_user = self.session_obj['user']
            del self.session_obj['user']
            if current_user:
                self.write(current_user)
            else:
                self.write('滚')
    
    class MainHandler1(SessionHandler,tornado.web.RequestHandler):
        def get(self):
    
            self.write('ok')
    
    class MainHandler2(SessionHandler,tornado.web.RequestHandler):
        def get(self):
            print('ok')
            self.write('ok')
    # obj = MainHandler() # 执行构造方法
    # obj.get()
    # func = getattr(obj, 'get')
    # func()
    application = tornado.web.Application([
        (r"/main", MainHandler),
        (r"/index", IndexHandler),
    ])
    
    if __name__ == "__main__":
        application.listen(8888)
        tornado.ioloop.IOLoop.instance().start()

    Session/session.py:

    import hashlib
    import time
    from Session import conf
    
    class SessionHandler:
        def initialize(self):
            self.session_obj = SessionFacotory.get_session_obj(self)
    
    
    class SessionFacotory:
        @staticmethod
        def get_session_obj(handler):
            if conf.session_type == 'redis':
                return RedisSession(handler)
            elif conf.session_type == 'memcache':
                return RedisSession(handler)
            else:
                return MemorySession(handler)
    
    
    def md5():
        m = hashlib.md5()
        m.update(bytes(str(time.time()),encoding='utf-8'))
        return m.hexdigest()
    
    class MemorySession:
        container = {
    
        }
        # self.r_str当前用户的随机字符串
        def __init__(self,handler):
    
            random_str = handler.get_cookie('___session_id___')
            if random_str:
                # 客户端有cookie
                # 合法cookie
                if random_str in MemorySession.container:
                    self.r_str = random_str
    
                else:
                    # 非法cookie
                    random_str = md5()
                    MemorySession.container[random_str] = {}
                    self.r_str = random_str
            else:
                # 客户端无cookie,表示是新用户的到来
                random_str = md5()
                MemorySession.container[random_str] = {}
                self.r_str = random_str
    
            handler.set_cookie('___session_id___', random_str, expires=time.time() + 200)
    
        def __setitem__(self, key, value):
            MemorySession.container[self.r_str][key] = value
    
        def __getitem__(self, item):
            return MemorySession.container[self.r_str].get(item,None)
    
        def __delitem__(self, key):
            del MemorySession.container[self.r_str][key]
    
    
    class RedisSession:
        def __init__(self):
            pass
        def __getitem__(self, item):
            pass
    
        def __setitem__(self, key, value):
            pass
    
        def __delitem__(self, key):
            pass

    Session/conf.py:

    session_type = 'redis'

    分布式session

    一致性哈希:

    #!/usr/bin/env python
    #coding:utf-8
    
    import sys
    import math
    from bisect import bisect
    
    
    if sys.version_info >= (2, 5):
        import hashlib
        md5_constructor = hashlib.md5
    else:
        import md5
        md5_constructor = md5.new
    
    
    class HashRing(object):
        """一致性哈希"""
        
        def __init__(self,nodes):
            '''初始化
            nodes : 初始化的节点,其中包含节点已经节点对应的权重
                    默认每一个节点有32个虚拟节点
                    对于权重,通过多创建虚拟节点来实现
                    如:nodes = [
                            {'host':'127.0.0.1:8000','weight':1},
                            {'host':'127.0.0.1:8001','weight':2},
                            {'host':'127.0.0.1:8002','weight':1},
                        ]
            '''
            
            self.ring = dict()
            self._sorted_keys = []
    
            self.total_weight = 0
            
            self.__generate_circle(nodes)
            
                
                
        def __generate_circle(self,nodes):
            for node_info in nodes:
                self.total_weight += node_info.get('weight',1)
                
            for node_info in nodes:
                weight = node_info.get('weight',1)
                node = node_info.get('host',None)
                    
                virtual_node_count = math.floor((32*len(nodes)*weight) / self.total_weight)
                for i in xrange(0,int(virtual_node_count)):
                    key = self.gen_key_thirty_two( '%s-%s' % (node, i) )
                    if self._sorted_keys.__contains__(key):
                        raise Exception('该节点已经存在.')
                    self.ring[key] = node
                    self._sorted_keys.append(key)
                
        def add_node(self,node):
            ''' 新建节点
            node : 要添加的节点,格式为:{'host':'127.0.0.1:8002','weight':1},其中第一个元素表示节点,第二个元素表示该节点的权重。
            '''
            node = node.get('host',None)
            if not node:
                    raise Exception('节点的地址不能为空.')
                    
            weight = node.get('weight',1)
            
            self.total_weight += weight
            nodes_count = len(self._sorted_keys) + 1
            
            virtual_node_count = math.floor((32 * nodes_count * weight) / self.total_weight)
            for i in xrange(0,int(virtual_node_count)):
                key = self.gen_key_thirty_two( '%s-%s' % (node, i) )
                if self._sorted_keys.__contains__(key):
                    raise Exception('该节点已经存在.')
                self.ring[key] = node
                self._sorted_keys.append(key)
            
        def remove_node(self,node):
            ''' 移除节点
            node : 要移除的节点 '127.0.0.1:8000'
            '''
            for key,value in self.ring.items():
                if value == node:
                    del self.ring[key]
                    self._sorted_keys.remove(key)
        
        def get_node(self,string_key):
            '''获取 string_key 所在的节点'''
            pos = self.get_node_pos(string_key)
            if pos is None:
                return None
            return self.ring[ self._sorted_keys[pos]].split(':')
        
        def get_node_pos(self,string_key):
            '''获取 string_key 所在的节点的索引'''
            if not self.ring:
                return None
                
            key = self.gen_key_thirty_two(string_key)
            nodes = self._sorted_keys
            pos = bisect(nodes, key)
            return pos
        
        def gen_key_thirty_two(self, key):
            
            m = md5_constructor()
            m.update(key)
            return long(m.hexdigest(), 16)
            
        def gen_key_sixteen(self,key):
            
            b_key = self.__hash_digest(key)
            return self.__hash_val(b_key, lambda x: x)
    
        def __hash_val(self, b_key, entry_fn):
            return (( b_key[entry_fn(3)] << 24)|(b_key[entry_fn(2)] << 16)|(b_key[entry_fn(1)] << 8)| b_key[entry_fn(0)] )
    
        def __hash_digest(self, key):
            m = md5_constructor()
            m.update(key)
            return map(ord, m.digest())
    
    
    """
    nodes = [
        {'host':'127.0.0.1:8000','weight':1},
        {'host':'127.0.0.1:8001','weight':2},
        {'host':'127.0.0.1:8002','weight':1},
    ]
    
    ring = HashRing(nodes)
    result = ring.get_node('98708798709870987098709879087')
    print result
    
    """

    分布式session:

    from hashlib import sha1
    import os, time
    
    
    create_session_id = lambda: sha1('%s%s' % (os.urandom(16), time.time())).hexdigest()
    
    
    class Session(object):
    
        session_id = "__sessionId__"
    
        def __init__(self, request):
            session_value = request.get_cookie(Session.session_id)
            if not session_value:
                self._id = create_session_id()
            else:
                self._id = session_value
            request.set_cookie(Session.session_id, self._id)
    
        def __getitem__(self, key):
            # 根据 self._id ,在一致性哈西中找到其对应的服务器IP
            # 找到相对应的redis服务器,如: r = redis.StrictRedis(host='localhost', port=6379, db=0)
            # 使用python redis api 链接
            # 获取数据,即:
            # return self._redis.hget(self._id, name)
    
        def __setitem__(self, key, value):
            # 根据 self._id ,在一致性哈西中找到其对应的服务器IP
            # 使用python redis api 链接
            # 设置session
            # self._redis.hset(self._id, name, value)
    
    
        def __delitem__(self, key):
            # 根据 self._id 找到相对应的redis服务器
            # 使用python redis api 链接
            # 删除,即:
            return self._redis.hdel(self._id, name)
  • 相关阅读:
    将博客搬至CSDN
    操作excel文件爬取nvd.nist数据
    windows下如何制作和应用数字签名证书 全流程
    python虚拟环境
    Linux系统中python默认版本为python2.7,修改为python3 项目上传码云
    删除github中某个文件夹
    国外的一些测试技术网站
    PYTHON读取EXCEL内容再转变成HTML添加到OUTLOOK中
    数据结构之顺序表概念篇
    Python内置类型性能分析
  • 原文地址:https://www.cnblogs.com/shiluoliming/p/6659734.html
Copyright © 2020-2023  润新知