采用两级缓存。先访问session,<br/>
如果存在，则直接使用，并更新 threadlocal <br/>
如果不存在，则访问 redis，<br/>
如果redis存在，则更新session和threadlocal<br/>
如果redis也不存在，则认为没有登录
977270
@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        //
        // 去掉不需拦截的path
        //
        String requestPath = request.getRequestURI();

        // 显示所有用户的请求
        LOG.info(request.getRequestURI());

        if (notInterceptPathList != null) {

            // 更精确的定位
            for (String path : notInterceptPathList) {
                if (requestPath.contains(path)) {
                    return true;
                }
            }
        }

        /**
         * 种植Cookie
         */
        plantCookie(request, response);

        /**
         * 登录与否判断
         */

        //
        // 判断session中是否有visitor
        //
        HttpSession session = request.getSession();
        Visitor visitor = (Visitor) session.getAttribute(UserConstant.USER_KEY);

        //
        // session中没有该信息,则从 redis上获取，并更新session的数据
        //
        if (visitor == null) {

            Visitor redisVisitor = redisLogin.isLogin(request);

            //
            // 有登录信息
            //
            if (redisVisitor != null) {

                // 更新session中的登录信息
                redisLogin.updateSessionVisitor(session, redisVisitor);

            } else {

                // 还是没有登录
                returnJsonSystemError(request, response, "login.error", ErrorCode.LOGIN_ERROR);
                return false;
            }
        } else {

            // 每次都更新session中的登录信息
            redisLogin.updateSessionVisitor(session, visitor);
        }

        return true;
    }
406447
@Memoized
  Session session() {
    Session result = sessionFactory().create(this);
    provisioned = true;
    return result;
  }
1300243
synchronized public void initSingle() {
		if (setting == null) {
			try {
				setting = new Setting(MONGO_CONFIG_PATH, true);
			} catch (Exception e) {
				// 在single模式下，可以没有配置文件。
			}
		}

		String group = StrUtil.EMPTY;
		if (null == this.serverAddress) {
			//存在唯一分组
			if (groups != null && groups.length == 1) {
				group = groups[0];
			}
			serverAddress = createServerAddress(group);
		}

		final MongoCredential credentail = createCredentail(group);
		try {
			if (null == credentail) {
				mongo = new MongoClient(serverAddress, buildMongoClientOptions(group));
			} else {
				mongo = new MongoClient(serverAddress, credentail, buildMongoClientOptions(group));
			}
		} catch (Exception e) {
			throw new DbRuntimeException(StrUtil.format("Init MongoDB pool with connection to [{}] error!", serverAddress), e);
		}

		log.info("Init MongoDB pool with connection to [{}]", serverAddress);
	}
908800
protected void initServer(TServerTransport serverTransport) {
		ThriftServerConfiguration configuration = getServerConfiguration();
		// 使用TThreadPoolServer方式启动Thrift服务器,对每个连接都会单独建立一个线程.
		TThreadPoolServer.Args args = new TThreadPoolServer.Args(serverTransport)
				.transportFactory(configuration.getTransportFactory())
				.protocolFactory(configuration.getProtocolFactory());
		// 如果不设置ExecutorService,则默认使用ThreadPoolExecutor实现.
		if (configuration.getExecutorService() != null)
			args.executorService(configuration.getExecutorService());
		server = new TThreadPoolServer(
				configuration.getServerArgsAspect().tThreadPoolServerArgsAspect(args).processor(getProcessor()));
		if (configuration.getServerEventHandler() != null)
			server.setServerEventHandler(configuration.getServerEventHandler());
	}
430898
function (connection, sessionRead) {
        connection = OT.Connection.fromHash(connection);
        if (sessionRead || session.connection && connection.id !== session.connection.id) {
          session.connections.add( connection );
          delayedSessionEvents.triggerConnectionCreated(connection);
        }

        OT.$.forEach(OT.$.keys(unconnectedStreams), function(streamId) {
          var stream = unconnectedStreams[streamId];
          if (stream && connection.id === stream.connection.id) {
            // dispatch streamCreated event now that the connectionCreated has been dispatched
            parseAndAddStreamToSession(stream, session);
            delete unconnectedStreams[stream.id];
            
            var payload = {
              debug: sessionRead ? 'connection came in session#read' :
                'connection came in connection#created',
              streamId : stream.id,
              connectionId : connection.id
            };
            session.logEvent('streamCreated', 'warning', payload);
          }
        });
        
        return connection;
      }
1056756
function(err, results) {

        if (!err) {

          self.sessionSubscriber = new SessionSubscriber(
            self.conf && self.conf.redis && self.conf.redis ? self.conf.redis : undefined,
            self.serverName,
            function(err) {
              if (!err) {

                console.info(' (init) REDIS     is connected  (for pub/sub)');
                console.info('        REDIS     is subscribed (C-' + self.serverName + ')');

                self._startup(server, io);

                if (cb) cb();

              } else {
                console.error(err);
                process.exit(1);
              }
            }
          );

        } else {

          for (var errNum in results) {
            if (results.hasOwnProperty(errNum) && results[errNum]) {
              console.error('  - ' + results[errNum] + '\n');
            }
          }
          process.exit(1);
        }
      }
882928
private void executeQuery(
      long index,
      long sequence,
      long timestamp,
      RaftSession session,
      PrimitiveOperation operation,
      CompletableFuture<OperationResult> future) {
    // If the service has been deleted then throw an unknown service exception.
    if (deleted) {
      log.warn("Service {} has been deleted by another process", serviceName);
      future.completeExceptionally(new RaftException.UnknownService("Service " + serviceName + " has been deleted"));
      return;
    }

    // If the session is not open, fail the request.
    if (!session.getState().active()) {
      log.warn("Inactive session: " + session.sessionId());
      future.completeExceptionally(new RaftException.UnknownSession("Unknown session: " + session.sessionId()));
      return;
    }

    // Otherwise, sequence the query.
    sequenceQuery(index, sequence, timestamp, session, operation, future);
  }
325110
private Object writeOnly(CacheAopProxyChain pjp, Cache cache) throws Throwable {
        DataLoaderFactory factory = DataLoaderFactory.getInstance();
        DataLoader dataLoader = factory.getDataLoader();
        CacheWrapper<Object> cacheWrapper;
        try {
            cacheWrapper = dataLoader.init(pjp, cache, this).getData().getCacheWrapper();
        } catch (Throwable e) {
            throw e;
        } finally {
            factory.returnObject(dataLoader);
        }
        Object result = cacheWrapper.getCacheObject();
        Object[] arguments = pjp.getArgs();
        if (scriptParser.isCacheable(cache, pjp.getTarget(), arguments, result)) {
            CacheKeyTO cacheKey = getCacheKey(pjp, cache, result);
            // 注意：这里只能获取AutoloadTO，不能生成AutoloadTO
            AutoLoadTO autoLoadTO = autoLoadHandler.getAutoLoadTO(cacheKey);
            try {
                writeCache(pjp, pjp.getArgs(), cache, cacheKey, cacheWrapper);
                if (null != autoLoadTO) {
                    // 同步加载时间
                    autoLoadTO.setLastLoadTime(cacheWrapper.getLastLoadTime())
                            // 同步过期时间
                            .setExpire(cacheWrapper.getExpire());
                }
            } catch (Exception ex) {
                log.error(ex.getMessage(), ex);
            }
        }
        return result;
    }
636146
function saveStateToLocalStorage(delay) {
    let timeId = null;

    // 同步存储
    if (delay < 1) {
        return function save(key, data) {
            try {
                localStorage.setItem(key, JSON.stringify(data));
            } catch (error) {
                // do nothing;
            }
        };
    }

    // 返回保存函数
    return function save(key, data) {
        timeId && clearTimeout(timeId);
        timeId = setTimeout(() => {
            try {
                localStorage.setItem(key, JSON.stringify(data));
            } catch (error) {
                // do nothing;
            } finally {
                timeId = null;
            }
        }, delay);
    };
}
967539
@Override
  public AppSession getNewSession(String sessionId, Class<? extends AppSession> aClass, ApplicationId applicationId, Object[] args) {
    try {
      // FIXME: add proper handling for SessionId
      if (aClass == ClientShSession.class) {
        ShClientSessionImpl clientSession = null;

        if (sessionId == null) {
          if (args != null && args.length > 0 && args[0] instanceof Request) {
            Request request = (Request) args[0];
            sessionId = request.getSessionId();
          }
          else {
            sessionId = this.sessionFactory.getSessionId();
          }
        }

        IShClientSessionData sessionData = (IShClientSessionData) this.sessionDataFactory.getAppSessionData(ClientShSession.class, sessionId);
        sessionData.setApplicationId(applicationId);
        clientSession = new ShClientSessionImpl(sessionData, this.getMessageFactory(), sessionFactory, this.getClientShSessionListener());
        sessionDataSource.addSession(clientSession);
        clientSession.getSessions().get(0).setRequestListener(clientSession);
        return clientSession;
      }
      else if (aClass == ServerShSession.class) {
        ShServerSessionImpl serverSession = null;

        if (sessionId == null) {
          if (args != null && args.length > 0 && args[0] instanceof Request) {
            Request request = (Request) args[0];
            sessionId = request.getSessionId();
          }
          else {
            sessionId = this.sessionFactory.getSessionId();
          }
        }
        IShServerSessionData sessionData = (IShServerSessionData) this.sessionDataFactory.getAppSessionData(ServerShSession.class, sessionId);
        sessionData.setApplicationId(applicationId);
        serverSession = new ShServerSessionImpl(sessionData, this.getMessageFactory(), sessionFactory, getServerShSessionListener());
        sessionDataSource.addSession(serverSession);
        serverSession.getSessions().get(0).setRequestListener(serverSession);
        return serverSession;
      }
      else {
        throw new IllegalArgumentException("Wrong session class: [" + aClass + "]. Supported[" + ClientShSession.class + "]");
      }
    }
    catch (IllegalArgumentException iae) {
      throw iae;
    }
    catch (Exception e) {
      logger.error("Failure to obtain new Sh Session.", e);
    }

    return null;
  }
537800
function init(){
    self.type = config.type || 'redis';
    if(config.redisMock){
      self.db = config.redisMock;
    }
    else{
      if(config.redisUrl){
        self.redisData = config.redisUrl || null;
      }
      else if(config.redisEnv){
        self.redisData = process.env[config.redisEnv] || null;
      }
      else if(config.redisData){
        self.redisData = config.redisData;
      }
      self.readOnly = (typeof config.readOnly === 'boolean') ? config.readOnly : false;
      try {
        if (self.redisData) {
          if(typeof self.redisData === 'string'){
            self.db = redis.createClient(self.redisData,
              {'no_ready_check': true,
              retry_strategy: retryStrategy});
          } else {
            self.db = redis.createClient(self.redisData.port,
              self.redisData.hostname, {'no_ready_check': true,
              retry_strategy: retryStrategy});

            // don't call redis auth method if no auth info passed
            if (self.redisData.auth) {
              self.db.auth(self.redisData.auth);
            }
          }
          self.db.on('error', function(err) {
            console.log('Error ' + err);
          });
          process.on('SIGTERM', function() {
            self.db.quit();
          });
          log(false, 'Redis client created with the following defaults:', {expiration: self.defaultExpiration, verbose: self.verbose, readOnly: self.readOnly});
        } else {
          self.db = false;
          log(false, 'Redis client not created: no redis config provided');
        }
      } catch (err) {
        self.db = false;
        log(true, 'Redis client not created:', err);
      }
    }
  }
536998
public function onReady()
    {
        $this->redis = \PHPDaemon\Clients\Redis\Pool::getInstance();

        $this->redis->hmset('myset', 'field1', 'value1', 'field2', 'value2', 'field3', 'value3', 'field4', 'value4',
            'field5', 'value5', function ($redis) {
                $this->redis->hgetall('myset', function ($redis) {
                    D('TEST 1: HGETALL');
                    foreach ($redis as $key => $value) {
                        D($key . ' - ' . $value);
                    }
                    D($redis->assoc);
                });

                $this->redis->hmget('myset', 'field2', 'field4', function ($redis) {
                    D('TEST 2: HMGET');
                    foreach ($redis as $key => $value) {
                        D($key . ' - ' . $value);
                    }
                    D($redis->assoc);
                });
            });

        $this->redis->zadd('myzset', 100, 'one', 150, 'two', 325, 'three', function ($redis) {
            $this->redis->zrange('myzset', 0, -1, function ($redis) {
                D('TEST 3: ZRANGE');
                foreach ($redis as $key => $value) {
                    D($key . ' - ' . $value);
                }
                D($redis->assoc);
            });

            $this->redis->zrange('myzset', 0, -1, 'WITHSCORES', function ($redis) {
                D('TEST 4: ZRANGE WITHSCORES');
                foreach ($redis as $key => $value) {
                    D($key . ' - ' . $value);
                }
                D($redis->assoc);
            });
        });

        $this->redis->subscribe('mysub', function ($redis) {
            D('TEST 5: SUB & PUB');
            foreach ($redis as $key => $value) {
                D($key . ' - ' . $value);
            }
            D($redis->channel, $redis->msg, $redis->assoc);
        });

        $this->redis->publish('mysub', 'Test message!');
    }
902528
@Override
	protected ThriftConnection<T> getConnectionInternal() throws ThriftConnectionPoolException {
		ThriftConnection<T> result = pollConnection();
		// 如果立即获取连接失败 则换一个分区继续获取
		// TODO 设置当连接获取超时返回null？
		if (result == null) {
			if (this.pool.getThriftServerCount() == 0) {
				throw new ThriftConnectionPoolException("当前没有可用的服务器  无法获取连接");
			}
			int partition = (int) (Thread.currentThread().getId() % this.pool.thriftServerCount);

			ThriftConnectionPartition<T> thriftConnectionPartition = this.pool.partitions.get(partition);

			try {
				result = thriftConnectionPartition.poolFreeConnection(this.pool.connectionTimeoutInMs,
						TimeUnit.MILLISECONDS);
				if (result == null) {

					throw new ThriftConnectionPoolException("Timed out waiting for a free available connection.");
				}
			} catch (InterruptedException e) {
				throw new ThriftConnectionPoolException(e);
			}
		}
		return result;
	}
80994
public static SqlSession getSession() throws IOException {
		SqlSession session = (SqlSession) THREAD_SESSION.get();  
	    try {  
	        if (session == null) {  
	        	session = getSessionFactory().getSession();
	        	THREAD_SESSION.set(session);  
	        }  
	    } catch (Exception e) {  
	        throw new IOException(e);  
	    }  
	    return session;  
	}
1265027
@Override
	public void run() {
		ThriftConnectionHandle<T> connection;
		long tmp;
		long nextCheckInMs = this.maxConnectionAge;

		int partitionSize = this.thriftConnectionPartition.getAvailableConnections();
		long currentTime = System.currentTimeMillis();
		for (int i = 0; i < partitionSize; i++) {
			try {
				connection = this.thriftConnectionPartition.poolFreeConnection();

				if (connection != null) {
					connection.setOriginatingPartition(this.thriftConnectionPartition);

					tmp = this.maxConnectionAge - (currentTime - connection.getConnectionCreationTimeInMs());

					if (tmp < nextCheckInMs) {
						nextCheckInMs = tmp;
					}

					// 判断连接是否过期
					if (connection.isExpired(currentTime)) {
						// 关闭连接
						closeConnection(connection);
						continue;
					}

					if (lifoMode == ServiceOrder.LIFO) {
						if (!(connection.getConnectionPartition().getFreeConnections().offer(connection))) {
							connection.internalClose();
						}
					} else {
						this.thriftConnectionPool.putConnectionBackInPartition(connection);
					}
					// 避免cpu使用率过高 进行一段时间休眠
					Thread.sleep(20L);
				}
			} catch (Throwable e) {
				logger.error("Connection max age thread exception.", e);
			}
		}

	}
862949
private ThriftConnectionPartition<T> createThriftConnectionPartition(ThriftServerInfo thriftServerInfo)
			throws ThriftConnectionPoolException {
		// 队列模式
		ServiceOrder serviceOrder = this.config.getServiceOrder();

		ThriftConnectionPartition<T> thriftConnectionPartition = new ThriftConnectionPartition<>(this,
				thriftServerInfo);
		// 添加空闲连接队列
		BlockingQueue<ThriftConnectionHandle<T>> connectionHandles = new LinkedBlockingQueue<>(
				this.config.getMaxConnectionPerServer());
		thriftConnectionPartition.setFreeConnections(connectionHandles);

		if (!this.config.isLazyInit()) {
			for (int i = 0; i < this.config.getMinConnectionPerServer(); i++) {
				// 初始化连接代理对象
				thriftConnectionPartition
						.addFreeConnection(new ThriftConnectionHandle<T>(null, thriftConnectionPartition, this, false));
			}

		}

		// 连接过期时间监控
		if (this.config.getIdleConnectionTestPeriod(TimeUnit.SECONDS) > 0
				|| this.config.getIdleMaxAge(TimeUnit.SECONDS) > 0) {

			final TimerTask connectionTester = new ThriftConnectionTesterThread<T>(thriftConnectionPartition, this,
					this.config.getIdleMaxAge(TimeUnit.MILLISECONDS),
					this.config.getIdleConnectionTestPeriod(TimeUnit.MILLISECONDS), serviceOrder);
			long delayInSeconds = this.config.getIdleConnectionTestPeriod(TimeUnit.SECONDS);
			if (delayInSeconds == 0L) {
				delayInSeconds = this.config.getIdleMaxAge(TimeUnit.SECONDS);
			}
			if (this.config.getIdleMaxAge(TimeUnit.SECONDS) < delayInSeconds
					&& this.config.getIdleConnectionTestPeriod(TimeUnit.SECONDS) != 0
					&& this.config.getIdleMaxAge(TimeUnit.SECONDS) != 0) {
				delayInSeconds = this.config.getIdleMaxAge(TimeUnit.SECONDS);
			}
			TaskEngine.getInstance().scheduleAtFixedRate(connectionTester, delayInSeconds, delayInSeconds);
		}

		// 连接最长存活时间监控
		if (this.config.getMaxConnectionAgeInSeconds() > 0) {
			final TimerTask connectionMaxAgeTester = new ThriftConnectionMaxAgeThread<T>(thriftConnectionPartition,
					this, this.config.getMaxConnectionAge(TimeUnit.MILLISECONDS), serviceOrder);
			TaskEngine.getInstance().scheduleAtFixedRate(connectionMaxAgeTester,
					this.config.getMaxConnectionAgeInSeconds(), this.config.getMaxConnectionAgeInSeconds());
		}
		// 连接数量监控
		TaskEngine.getInstance().submit(new PoolWatchThread<T>(thriftConnectionPartition, this));

		return thriftConnectionPartition;

	}
56878
public static void cleanupThreadLocals(Thread thread)
   {
      if (!OperatingSystemUtils.isJava8())
      {
         return;
      }
      try
      {
         if (thread != null)
         {
            cleanField(thread, Thread.class.getDeclaredField("threadLocals"));
            cleanField(thread, Thread.class.getDeclaredField("inheritableThreadLocals"));
         }
      }
      catch (Exception e)
      {
         log.log(Level.WARNING, "Failed to cleanup ThreadLocal instances for Thread [" + thread + "]", e);
      }
   }