文档章节

Linux系统Nginx+Tomcat+Codis实现session共享

衣带渐宽终不悔1
 衣带渐宽终不悔1
发布于 2016/05/17 02:26
字数 2225
阅读 117
收藏 1

Linux系统Nginx+Tomcat+Codis实现session共享

  • 修改源码使用Eclipse+Maven
  • pom依赖
  • <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>listen</groupId>
      <artifactId>com.listen.org</artifactId>
      <packaging>war</packaging>
      <version>0.0.1-SNAPSHOT</version>
      <name>com.listen.org Maven Webapp</name>
      <url>http://maven.apache.org</url>
      <dependencies>
    <!--     <dependency> -->
    <!--     	<groupId>org.apache.httpcomponents</groupId> -->
    <!--     	<artifactId>httpclient</artifactId> -->
    <!--     	<version>4.3.1</version> -->
    <!--     </dependency> -->
    <!--     <dependency> -->
    <!-- 		<groupId>redis.clients</groupId> -->
    <!-- 		<artifactId>jedis</artifactId> -->
    <!-- 		<version>2.8.0</version> -->
    <!-- 	</dependency> -->
    <!-- 	<dependency> -->
    <!-- 		<groupId>junit</groupId> -->
    <!-- 		<artifactId>junit</artifactId> -->
    <!-- 		<version>4.12</version> -->
    <!-- 	</dependency> -->
    	<dependency>
    	  <groupId>io.codis.jodis</groupId>
    	  <artifactId>jodis</artifactId>
    	  <version>0.3.0</version>
    	</dependency>
    	<dependency>
    		<groupId>org.apache.curator</groupId>
    		<artifactId>curator-framework</artifactId>
    		<version>3.1.0</version>
    	</dependency>
      </dependencies>
      <build>
        <finalName>com.listen.org</finalName>
      </build>
    </project>
    
  • 第三方依赖,由于修改源码需要gradle编译生成的jar包作为依赖包且这些jar包无法使用pom依赖的方式添加到工程中,所以只能将dist目录下的所有jar包以referenced的方式添加到工程中,且无法使用Maven的install生成class文件,所以只能写一个main方式,运行,以实现class文件的生成,如下图
  •  
  •  编辑源码,并编译
  • package com.orangefunction.tomcat.redissessions;
    
    import io.codis.jodis.JedisResourcePool;
    import io.codis.jodis.RoundRobinJedisPool;
    
    import java.io.IOException;
    import java.util.Arrays;
    import java.util.EnumSet;
    import java.util.Enumeration;
    import java.util.Iterator;
    import java.util.Set;
    
    import org.apache.catalina.Lifecycle;
    import org.apache.catalina.LifecycleException;
    import org.apache.catalina.LifecycleListener;
    import org.apache.catalina.LifecycleState;
    import org.apache.catalina.Loader;
    import org.apache.catalina.Session;
    import org.apache.catalina.Valve;
    import org.apache.catalina.session.ManagerBase;
    import org.apache.catalina.util.LifecycleSupport;
    import org.apache.juli.logging.Log;
    import org.apache.juli.logging.LogFactory;
    
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPoolConfig;
    import redis.clients.jedis.Protocol;
    
    
    public class RedisSessionManager extends ManagerBase implements Lifecycle {
    	
    	public static void main(String[] a){
    		System.out.println("aaa");
    	}
    
      enum SessionPersistPolicy {
        DEFAULT,
        SAVE_ON_CHANGE,
        ALWAYS_SAVE_AFTER_REQUEST;
    
        static SessionPersistPolicy fromName(String name) {
          for (SessionPersistPolicy policy : SessionPersistPolicy.values()) {
            if (policy.name().equalsIgnoreCase(name)) {
              return policy;
            }
          }
          throw new IllegalArgumentException("Invalid session persist policy [" + name + "]. Must be one of " + Arrays.asList(SessionPersistPolicy.values())+ ".");
        }
      }
    
      protected byte[] NULL_SESSION = "null".getBytes();
    
      private final Log log = LogFactory.getLog(RedisSessionManager.class);
    
      protected int timeout = Protocol.DEFAULT_TIMEOUT;
    
      protected RedisSessionHandlerValve handlerValve;
      protected ThreadLocal<RedisSession> currentSession = new ThreadLocal<>();
      protected ThreadLocal<SessionSerializationMetadata> currentSessionSerializationMetadata = new ThreadLocal<>();
      protected ThreadLocal<String> currentSessionId = new ThreadLocal<>();
      protected ThreadLocal<Boolean> currentSessionIsPersisted = new ThreadLocal<>();
      protected Serializer serializer;
    
      protected static String name = "RedisSessionManager";
    
      protected String serializationStrategyClass = "com.orangefunction.tomcat.redissessions.JavaSerializer";
    
      protected EnumSet<SessionPersistPolicy> sessionPersistPoliciesSet = EnumSet.of(SessionPersistPolicy.DEFAULT);
    
      /**
       * The lifecycle event support for this component.
       */
      protected LifecycleSupport lifecycle = new LifecycleSupport(this);
    
    
      public int getTimeout() {
        return timeout;
      }
    
      public void setTimeout(int timeout) {
        this.timeout = timeout;
      }
    
      public void setSerializationStrategyClass(String strategy) {
        this.serializationStrategyClass = strategy;
      }
    
      public String getSessionPersistPolicies() {
        StringBuilder policies = new StringBuilder();
        for (Iterator<SessionPersistPolicy> iter = this.sessionPersistPoliciesSet.iterator(); iter.hasNext();) {
          SessionPersistPolicy policy = iter.next();
          policies.append(policy.name());
          if (iter.hasNext()) {
            policies.append(",");
          }
        }
        return policies.toString();
      }
    
      public void setSessionPersistPolicies(String sessionPersistPolicies) {
        String[] policyArray = sessionPersistPolicies.split(",");
        EnumSet<SessionPersistPolicy> policySet = EnumSet.of(SessionPersistPolicy.DEFAULT);
        for (String policyName : policyArray) {
          SessionPersistPolicy policy = SessionPersistPolicy.fromName(policyName);
          policySet.add(policy);
        }
        this.sessionPersistPoliciesSet = policySet;
      }
    
      public boolean getSaveOnChange() {
        return this.sessionPersistPoliciesSet.contains(SessionPersistPolicy.SAVE_ON_CHANGE);
      }
    
      public boolean getAlwaysSaveAfterRequest() {
        return this.sessionPersistPoliciesSet.contains(SessionPersistPolicy.ALWAYS_SAVE_AFTER_REQUEST);
      }
    
      protected Jedis acquireConnection() {
    //    Jedis jedis = connectionPool.getResource();
    	  JedisPoolConfig poolConfig = new JedisPoolConfig();
    		poolConfig.setMaxTotal(4096);
    		poolConfig.setMaxIdle(200);
    		poolConfig.setMaxWaitMillis(3000);
    		poolConfig.setTestOnBorrow(true);
    		poolConfig.setTestOnReturn(true);
    		poolConfig.setMinIdle(20);
    		JedisResourcePool jedisPool = RoundRobinJedisPool.create()
    				.curatorClient("192.168.75.141:2181,192.168.75.141:2182,192.168.75.141:2183,192.168.75.141:2184,192.168.75.141:2185", 60000)
    				.zkProxyDir("/zk/codis/db_codis/proxy").poolConfig(poolConfig).build();
    		Jedis jedis = jedisPool.getResource();
    		log.info("current jedis:" + jedisToString(jedis));
    		System.out.println("current jedis:" + jedisToString(jedis));
        return jedis;
      }
      
      private String jedisToString(Jedis jedis){
    	  StringBuffer sb = new StringBuffer();
    	  try{
    		  if(jedis != null){
    			  sb.append(jedis.info());
    		  }
    	  }
    	  catch (Exception e){
    		  e.printStackTrace();
    	  }
    	  return sb.toString();
      }
    
      /**
       * Add a lifecycle event listener to this component.
       *
       * @param listener The listener to add
       */
      @Override
      public void addLifecycleListener(LifecycleListener listener) {
        lifecycle.addLifecycleListener(listener);
      }
    
      /**
       * Get the lifecycle listeners associated with this lifecycle. If this
       * Lifecycle has no listeners registered, a zero-length array is returned.
       */
      @Override
      public LifecycleListener[] findLifecycleListeners() {
        return lifecycle.findLifecycleListeners();
      }
    
    
      /**
       * Remove a lifecycle event listener from this component.
       *
       * @param listener The listener to remove
       */
      @Override
      public void removeLifecycleListener(LifecycleListener listener) {
        lifecycle.removeLifecycleListener(listener);
      }
    
      /**
       * Start this component and implement the requirements
       * of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
       *
       * @exception LifecycleException if this component detects a fatal error
       *  that prevents this component from being used
       */
      @Override
      protected synchronized void startInternal() throws LifecycleException {
        super.startInternal();
    
        setState(LifecycleState.STARTING);
    
        Boolean attachedToValve = false;
        for (Valve valve : getContainer().getPipeline().getValves()) {
          if (valve instanceof RedisSessionHandlerValve) {
            this.handlerValve = (RedisSessionHandlerValve) valve;
            this.handlerValve.setRedisSessionManager(this);
            log.info("Attached to RedisSessionHandlerValve");
            attachedToValve = true;
            break;
          }
        }
    
        if (!attachedToValve) {
          String error = "Unable to attach to session handling valve; sessions cannot be saved after the request without the valve starting properly.";
          log.fatal(error);
          throw new LifecycleException(error);
        }
    
        try {
          initializeSerializer();
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
          log.fatal("Unable to load serializer", e);
          throw new LifecycleException(e);
        }
    
        log.info("Will expire sessions after " + getMaxInactiveInterval() + " seconds");
    
        setDistributable(true);
      }
    
    
      /**
       * Stop this component and implement the requirements
       * of {@link org.apache.catalina.util.LifecycleBase#stopInternal()}.
       *
       * @exception LifecycleException if this component detects a fatal error
       *  that prevents this component from being used
       */
      @Override
      protected synchronized void stopInternal() throws LifecycleException {
        if (log.isDebugEnabled()) {
          log.debug("Stopping");
        }
    
        setState(LifecycleState.STOPPING);
    
        // Require a new random number generator if we are restarted
        super.stopInternal();
      }
    
      @Override
      public Session createSession(String requestedSessionId) {
        RedisSession session = null;
        String sessionId = null;
        String jvmRoute = getJvmRoute();
    
        Boolean error = true;
        Jedis jedis = null;
        try {
          jedis = acquireConnection();
    
          // Ensure generation of a unique session identifier.
          if (null != requestedSessionId) {
            sessionId = sessionIdWithJvmRoute(requestedSessionId, jvmRoute);
            if (jedis.setnx(sessionId.getBytes(), NULL_SESSION) == 0L) {
              sessionId = null;
            }
          } else {
            do {
              sessionId = sessionIdWithJvmRoute(generateSessionId(), jvmRoute);
            } while (jedis.setnx(sessionId.getBytes(), NULL_SESSION) == 0L); // 1 = key set; 0 = key already existed
          }
    
          /* Even though the key is set in Redis, we are not going to flag
             the current thread as having had the session persisted since
             the session isn't actually serialized to Redis yet.
             This ensures that the save(session) at the end of the request
             will serialize the session into Redis with 'set' instead of 'setnx'. */
    
          error = false;
    
          if (null != sessionId) {
            session = (RedisSession)createEmptySession();
            session.setNew(true);
            session.setValid(true);
            session.setCreationTime(System.currentTimeMillis());
            session.setMaxInactiveInterval(getMaxInactiveInterval());
            session.setId(sessionId);
            session.tellNew();
          }
    
          currentSession.set(session);
          currentSessionId.set(sessionId);
          currentSessionIsPersisted.set(false);
          currentSessionSerializationMetadata.set(new SessionSerializationMetadata());
    
          if (null != session) {
            try {
              error = saveInternal(jedis, session, true);
            } catch (IOException ex) {
              log.error("Error saving newly created session: " + ex.getMessage());
              currentSession.set(null);
              currentSessionId.set(null);
              session = null;
            }
          }
        } finally {
          if (jedis != null) {
          }
        }
    
        return session;
      }
    
      private String sessionIdWithJvmRoute(String sessionId, String jvmRoute) {
        if (jvmRoute != null) {
          String jvmRoutePrefix = '.' + jvmRoute;
          return sessionId.endsWith(jvmRoutePrefix) ? sessionId : sessionId + jvmRoutePrefix;
        }
        return sessionId;
      }
    
      @Override
      public Session createEmptySession() {
        return new RedisSession(this);
      }
    
      @Override
      public void add(Session session) {
        try {
          save(session);
        } catch (IOException ex) {
          log.warn("Unable to add to session manager store: " + ex.getMessage());
          throw new RuntimeException("Unable to add to session manager store.", ex);
        }
      }
    
      @Override
      public Session findSession(String id) throws IOException {
        RedisSession session = null;
    
        if (null == id) {
          currentSessionIsPersisted.set(false);
          currentSession.set(null);
          currentSessionSerializationMetadata.set(null);
          currentSessionId.set(null);
        } else if (id.equals(currentSessionId.get())) {
          session = currentSession.get();
        } else {
          byte[] data = loadSessionDataFromRedis(id);
          if (data != null) {
            DeserializedSessionContainer container = sessionFromSerializedData(id, data);
            session = container.session;
            currentSession.set(session);
            currentSessionSerializationMetadata.set(container.metadata);
            currentSessionIsPersisted.set(true);
            currentSessionId.set(id);
          } else {
            currentSessionIsPersisted.set(false);
            currentSession.set(null);
            currentSessionSerializationMetadata.set(null);
            currentSessionId.set(null);
          }
        }
    
        return session;
      }
    
      public void clear() {
        Jedis jedis = null;
        Boolean error = true;
        try {
          jedis = acquireConnection();
          jedis.flushDB();
          error = false;
        } finally {
          if (jedis != null) {
          }
        }
      }
    
      public int getSize() throws IOException {
        Jedis jedis = null;
        Boolean error = true;
        try {
          jedis = acquireConnection();
          int size = jedis.dbSize().intValue();
          error = false;
          return size;
        } finally {
          if (jedis != null) {
          }
        }
      }
    
      public String[] keys() throws IOException {
        Jedis jedis = null;
        Boolean error = true;
        try {
          jedis = acquireConnection();
          Set<String> keySet = jedis.keys("*");
          error = false;
          return keySet.toArray(new String[keySet.size()]);
        } finally {
          if (jedis != null) {
          }
        }
      }
    
      public byte[] loadSessionDataFromRedis(String id) throws IOException {
        Jedis jedis = null;
        Boolean error = true;
    
        try {
          log.trace("Attempting to load session " + id + " from Redis");
    
          jedis = acquireConnection();
          byte[] data = jedis.get(id.getBytes());
          error = false;
    
          if (data == null) {
            log.trace("Session " + id + " not found in Redis");
          }
    
          return data;
        } finally {
          if (jedis != null) {
          }
        }
      }
    
      public DeserializedSessionContainer sessionFromSerializedData(String id, byte[] data) throws IOException {
        log.trace("Deserializing session " + id + " from Redis");
    
        if (Arrays.equals(NULL_SESSION, data)) {
          log.error("Encountered serialized session " + id + " with data equal to NULL_SESSION. This is a bug.");
          throw new IOException("Serialized session data was equal to NULL_SESSION");
        }
    
        RedisSession session = null;
        SessionSerializationMetadata metadata = new SessionSerializationMetadata();
    
        try {
          session = (RedisSession)createEmptySession();
    
          serializer.deserializeInto(data, session, metadata);
    
          session.setId(id);
          session.setNew(false);
          session.setMaxInactiveInterval(getMaxInactiveInterval());
          session.access();
          session.setValid(true);
          session.resetDirtyTracking();
    
          if (log.isTraceEnabled()) {
            log.trace("Session Contents [" + id + "]:");
            Enumeration en = session.getAttributeNames();
            while(en.hasMoreElements()) {
              log.trace("  " + en.nextElement());
            }
          }
        } catch (ClassNotFoundException ex) {
          log.fatal("Unable to deserialize into session", ex);
          throw new IOException("Unable to deserialize into session", ex);
        }
    
        return new DeserializedSessionContainer(session, metadata);
      }
    
      public void save(Session session) throws IOException {
        save(session, false);
      }
    
      public void save(Session session, boolean forceSave) throws IOException {
        Jedis jedis = null;
        Boolean error = true;
    
        try {
          jedis = acquireConnection();
          error = saveInternal(jedis, session, forceSave);
        } catch (IOException e) {
          throw e;
        } finally {
          if (jedis != null) {
          }
        }
      }
    
      protected boolean saveInternal(Jedis jedis, Session session, boolean forceSave) throws IOException {
        Boolean error = true;
    
        try {
          log.trace("Saving session " + session + " into Redis");
    
          RedisSession redisSession = (RedisSession)session;
    
          if (log.isTraceEnabled()) {
            log.trace("Session Contents [" + redisSession.getId() + "]:");
            Enumeration en = redisSession.getAttributeNames();
            while(en.hasMoreElements()) {
              log.trace("  " + en.nextElement());
            }
          }
    
          byte[] binaryId = redisSession.getId().getBytes();
    
          Boolean isCurrentSessionPersisted;
          SessionSerializationMetadata sessionSerializationMetadata = currentSessionSerializationMetadata.get();
          byte[] originalSessionAttributesHash = sessionSerializationMetadata.getSessionAttributesHash();
          byte[] sessionAttributesHash = null;
          if (
               forceSave
               || redisSession.isDirty()
               || null == (isCurrentSessionPersisted = this.currentSessionIsPersisted.get())
                || !isCurrentSessionPersisted
               || !Arrays.equals(originalSessionAttributesHash, (sessionAttributesHash = serializer.attributesHashFrom(redisSession)))
             ) {
    
            log.trace("Save was determined to be necessary");
    
            if (null == sessionAttributesHash) {
              sessionAttributesHash = serializer.attributesHashFrom(redisSession);
            }
    
            SessionSerializationMetadata updatedSerializationMetadata = new SessionSerializationMetadata();
            updatedSerializationMetadata.setSessionAttributesHash(sessionAttributesHash);
            log.info("current jedis:" + jedisToString(jedis));
    		System.out.println("current jedis:" + jedisToString(jedis));
            jedis.set(binaryId, serializer.serializeFrom(redisSession, updatedSerializationMetadata));
    
            redisSession.resetDirtyTracking();
            currentSessionSerializationMetadata.set(updatedSerializationMetadata);
            currentSessionIsPersisted.set(true);
          } else {
            log.trace("Save was determined to be unnecessary");
          }
    
          log.trace("Setting expire timeout on session [" + redisSession.getId() + "] to " + getMaxInactiveInterval());
          jedis.expire(binaryId, getMaxInactiveInterval());
    
          error = false;
    
          return error;
        } catch (IOException e) {
          log.error(e.getMessage());
    
          throw e;
        } finally {
          return error;
        }
      }
    
      @Override
      public void remove(Session session) {
        remove(session, false);
      }
    
      @Override
      public void remove(Session session, boolean update) {
        Jedis jedis = null;
        Boolean error = true;
    
        log.trace("Removing session ID : " + session.getId());
    
        try {
          jedis = acquireConnection();
          jedis.del(session.getId());
          error = false;
        } finally {
          if (jedis != null) {
          }
        }
      }
    
      public void afterRequest() {
        RedisSession redisSession = currentSession.get();
        if (redisSession != null) {
          try {
            if (redisSession.isValid()) {
              log.trace("Request with session completed, saving session " + redisSession.getId());
              save(redisSession, getAlwaysSaveAfterRequest());
            } else {
              log.trace("HTTP Session has been invalidated, removing :" + redisSession.getId());
              remove(redisSession);
            }
          } catch (Exception e) {
            log.error("Error storing/removing session", e);
          } finally {
            currentSession.remove();
            currentSessionId.remove();
            currentSessionIsPersisted.remove();
            log.trace("Session removed from ThreadLocal :" + redisSession.getIdInternal());
          }
        }
      }
    
      @Override
      public void processExpires() {
        // We are going to use Redis's ability to expire keys for session expiration.
    
        // Do nothing.
      }
    
    
      private void initializeSerializer() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        log.info("Attempting to use serializer :" + serializationStrategyClass);
        serializer = (Serializer) Class.forName(serializationStrategyClass).newInstance();
    
        Loader loader = null;
    
        if (getContainer() != null) {
          loader = getContainer().getLoader();
        }
    
        ClassLoader classLoader = null;
    
        if (loader != null) {
          classLoader = loader.getClassLoader();
        }
        serializer.setClassLoader(classLoader);
      }
    
    @Override
    public void load() throws ClassNotFoundException, IOException {
    }
    
    @Override
    public void unload() throws IOException {
    }
    
    
      // Connection Pool Config Accessors
    
      // - from org.apache.commons.pool2.impl.GenericObjectPoolConfig
    }
    
    class DeserializedSessionContainer {
      public final RedisSession session;
      public final SessionSerializationMetadata metadata;
      public DeserializedSessionContainer(RedisSession session, SessionSerializationMetadata metadata) {
        this.session = session;
        this.metadata = metadata;
      }
    }
    

    将编译后的class文件替换到tomcat-redis-session-manager-master-2.0.0.jar中,是有两个class文件

  • 将替换后的tomcat-redis-session-manager-master-2.0.0.jar包覆盖到{tomat_home}/libs中(2个tomcat都要替换)
  • 修改tomcat配置文件content.xml
  • <?xml version='1.0' encoding='utf-8'?>
    <!--
      Licensed to the Apache Software Foundation (ASF) under one or more
      contributor license agreements.  See the NOTICE file distributed with
      this work for additional information regarding copyright ownership.
      The ASF licenses this file to You under the Apache License, Version 2.0
      (the "License"); you may not use this file except in compliance with
      the License.  You may obtain a copy of the License at
    
          http://www.apache.org/licenses/LICENSE-2.0
    
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      See the License for the specific language governing permissions and
      limitations under the License.
    -->
    <!-- The contents of this file will be loaded for each web application -->
    <Context>
    
        <!-- Default set of monitored resources -->
        <WatchedResource>WEB-INF/web.xml</WatchedResource>
    
        <!-- Uncomment this to disable session persistence across Tomcat restarts -->
        <!--
        <Manager pathname="" />
        -->
    
        <!-- Uncomment this to enable Comet connection tacking (provides events
             on session expiration as well as webapp lifecycle) -->
        <!--
        <Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
        -->
    
    <!--以下为增加的内容-->
    <Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />  
    <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"  
             
             maxInactiveInterval="60" />  
    
    </Context>
    
  • 先启动Codis集群。然后重启两个tomcat,别忘了启动Nginx。
  • 测试session共享,先使用Redis客户端连接到Codis集群,查询sessionId是保存在哪台master上的,然后主从切换对应的master,查看session页面是否还能正常显示,结果是可以正常显示。
  • 总结:修改源码其实就是修改Redis连接的获取方式,将之前的单机连接修改为集群获取连接的方式,其他没有改变。
  • 核心技术:Maven,Springmvc mybatis shiro, Druid, Restful, Dubbo, ZooKeeper,Redis,FastDFS,ActiveMQ,Nginx 
    1.     项目核心代码结构截图

    分布式框架介绍 - kafkaee - kafkaee的博客

       项目模块依赖分布式框架介绍 - kafkaee - kafkaee的博客

    特别提醒:开发人员在开发的时候可以将自己的业务REST服务化或者Dubbo服务化

    2.    项目依赖介绍

       2.1 后台管理系统、Rest服务系统、Scheculer定时调度系统依赖如下图:
     

    分布式框架介绍 - kafkaee - kafkaee的博客

           2.2 Dubbo独立服务项目依赖如下图:

     分布式框架介绍 - kafkaee - kafkaee的博客

    3.  项目功能部分截图:

    分布式框架介绍 - kafkaee - kafkaee的博客

     

    分布式框架介绍 - kafkaee - kafkaee的博客

     

    分布式框架介绍 - kafkaee - kafkaee的博客

     

    分布式框架介绍 - kafkaee - kafkaee的博客

     

    分布式框架介绍 - kafkaee - kafkaee的博客

     

    分布式框架介绍 - kafkaee - kafkaee的博客

     

    分布式框架介绍 - kafkaee - kafkaee的博客
     

    zookeeper、dubbo服务启动 

    分布式框架介绍 - kafkaee - kafkaee的博客

     

    分布式框架介绍 - kafkaee - kafkaee的博客
     

    dubbo管控台 

    分布式框架介绍 - kafkaee - kafkaee的博客

     

    分布式框架介绍 - kafkaee - kafkaee的博客

     

    分布式框架介绍 - kafkaee - kafkaee的博客

     

    分布式框架介绍 - kafkaee - kafkaee的博客

     

    分布式框架介绍 - kafkaee - kafkaee的博客

     

    分布式框架介绍 - kafkaee - kafkaee的博客

     

    分布式框架介绍 - kafkaee - kafkaee的博客

     REST服务平台

    分布式框架介绍 - kafkaee - kafkaee的博客

     

    分布式框架介绍 - kafkaee - kafkaee的博客

     

    分布式框架介绍 - kafkaee - kafkaee的博客

     

    分布式框架介绍 - kafkaee - kafkaee的博客

     评论这张

     

© 著作权归作者所有

衣带渐宽终不悔1
粉丝 0
博文 6
码字总数 16628
作品 0
南昌
私信 提问
加载中

评论(1)

衣带渐宽终不悔1
衣带渐宽终不悔1 博主
  Linux系统Nginx+Tomcat+Codis实现session共享
Linux系统Nginx+Tomcat+Codis实现session共享

用户:root Tomcat版本:apache-tomcat-7.0.52 接上篇,本篇是将单机Redis替换为Codis集群实现session共享。 请先配置Codis集群,可参考Linux系统Codis集群安装配置。 修改Redis源码 修改源码...

Listen_ing
2016/05/16
1K
3
在window下与linux虚拟机建立共享文件夹

使用vmware下shared folders功能实现vmware中文件传输,可参考vmware帮助中setting up shared folders。 1.安装vmtools for linux: 选择vmware workstation程序菜单中VM >install VMware to......

huangnie
2014/01/27
59
0
JavaWeb24-HTML篇笔记(二)

1.1 Linux系统上安装tomcat:1.1.1 安装tomcat:1.1.1.1 上传tomcat的安装文件: 1.1.1.2 创建tomcat的安装路径: 在/usr/local 下mkdir tomcat 1.1.1.3 解压tomcat tar –xvf xxx.tar.gz –C...

我是小谷粒
2018/06/12
0
0
Linux下编译按装memcache分布式环境(

Linux下编译按装memcache分布式环境(笔记) Linux下编译按装memcache分布式环境(笔记) @author 流水孟春 121169238(at)qq.com Memcache用到了libevent这个库用于Socket的处理,所以还需要...

石头哥哥
2013/01/18
183
0
Nginx+Tomcat关于Session的管理

系列文章 Nginx+Tomcat关于Session的管理 Tomcat Session管理分析 Spring-Session基于Redis管理Session 前言 Nginx+Tomcat对Session的管理一直有了解,但是一直没有实际操作一遍,本文从最简...

ksfzhaohui
2018/05/31
585
6

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周六乱弹 —— 早上儿子问我他是怎么来的

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @凉小生 :#今日歌曲推荐# 少点戾气,愿你和这个世界温柔以待。中岛美嘉的单曲《僕が死のうと思ったのは (曾经我也想过一了百了)》 《僕が死の...

小小编辑
今天
2.4K
15
Excption与Error包结构,OOM 你遇到过哪些情况,SOF 你遇到过哪些情况

Throwable 是 Java 中所有错误与异常的超类,Throwable 包含两个子类,Error 与 Exception 。用于指示发生了异常情况。 Java 抛出的 Throwable 可以分成三种类型。 被检查异常(checked Exc...

Garphy
今天
41
0
计算机实现原理专题--二进制减法器(二)

在计算机实现原理专题--二进制减法器(一)中说明了基本原理,现准备说明如何来实现。 首先第一步255-b运算相当于对b进行按位取反,因此可将8个非门组成如下图的形式: 由于每次做减法时,我...

FAT_mt
昨天
40
0
好程序员大数据学习路线分享函数+map映射+元祖

好程序员大数据学习路线分享函数+map映射+元祖,大数据各个平台上的语言实现 hadoop 由java实现,2003年至今,三大块:数据处理,数据存储,数据计算 存储: hbase --> 数据成表 处理: hive --> 数...

好程序员官方
昨天
61
0
tabel 中含有复选框的列 数据理解

1、el-ui中实现某一列为复选框 实现多选非常简单: 手动添加一个el-table-column,设type属性为selction即可; 2、@selection-change事件:选项发生勾选状态变化时触发该事件 <el-table @sel...

everthing
昨天
21
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部