`
dicmo
  • 浏览: 69551 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Coder 爱翻译 How Tomcat Works 第九章 第二部分

    博客分类:
  • j2ee
阅读更多
The ManagerBase Class

ManagerBase类是一个从所有Manager抽取出来到的抽象类。这个类给它的子类提供了常见的方法。ManagerBase有createSession方法来创建一个Session对象。每一个session都有一个唯一的标识符,ManagerBase类的protected方法generateSessionId返回一个唯一的标识符。

注意:一个活动状态下的session是一个session仍然是valid对象,而不是expired的。这些活动的session被存储在一个叫做sessions的HashMap中的:

protected HashMap sessions = new HashMap();


add方法把一个Session对象添加到sessions中:
  public void add(Session session) { 
     synchronized (sessions) {
       sessions.put(session.getId(), session); 
     } 
   }

remove方法从sessions中移除一个Session对象。
   public void remove(Session session) { 
     synchronized (sessions) { 
       sessions.remove(session.getId()); 
     } 
   }

没有参数的findSession方法返回在sessions中的活动的所有session对象的实例数组。findSession方法接收一个session标识符作为一个参数返回给出的标识符的Session实例。
   public Session[] findSessions() { 
     Session results[] = null; 
     synchronized (sessions) { 
       results = new Session[sessions.size()]; 
       results = (Session[]) sessions.values().toArray(results); 
     } 
     return (results); 
   } 
   public Session findSession(String id) throws IOException { 
     if (id == null) 
       return (null); 
     synchronized (sessions) { 
 
     Session session = (Session) sessions.get(id); 
     return (session); 
   } 
}

StandardManager

StandardManager类是Manager的标准实现,它用来把Session对象存储到内存中。它实现了Lifecycle接口,所以它可以被启动和停止。stop方法的实现调用unload方法,为每一个context把合法的Session实例以串行化方式存入一个叫做SESSION.ser的文件中。SESSION.ser文件可以在CATALINA_HOME目录下找到。当StandardManager再次启动的时候,使用load方法把这些Session对象被重新加载到内存中去。

一个manager也负责销毁那些不再合法的session对象。Tomcat 4中的StandardManager,它拥有一个指定的线程来实现。所以,StandardManager它实现了java.lang.Runnable接口。
public void run() { 
   // Loop until the termination semaphore is set 
   while (!threadDone) { 
     threadSleep(); 
     processExpires(); 
   } 
}

ThreadSleep方法让这个线程处于睡眠等待checkInterval变量指定的秒数。默认是60秒。你可以调用setCheckInterval方法来设置这个变量值。

ProcessExpire方法循环地把所有的被StandardManager管理的Session对象中的每一个Session对象的lastAccessedTime值和当前的时间值比较。如果这两个时间的差值超过了maxInactiveInterval值,这个方法就调用Session接口的expire方法把这个Session实例设置为超时。maxInactiveInterval值可以通过调用setMaxInactiveInterval方法来改变。StandardManager下默认的maxInactiveInterval变量值是60。不要简单地认为这个值是在Tomcat部署时用到的值,setContainer方法org.apache.catalina.core.ContainerBase 类的setManager方法被调用,重写这个值:
setMaxInactiveInterval(((Context) 
this.container).getSessionTimeout()*60 ); 

注意:在org.apache.catalina.core.StandardContext类的sessionTimeOut变量的默认值是30。

在Tomcat 5中,StandardManager类没有实现java.lang.Runnable.。在Tomcat 5中的StandardManager中的processExpires方法被backgroundprocess方法直接调用。
public void backgroundProcess() { 
   processExpires(); 
}

在StandardManager中的backgroundProcess方法通过org.apache.catalina.core.StandardContext实例的backgroundProcess方法调用,这个容器和这个manager相关联。每隔一段时间StandardContext调用它的backgroundProcess方法。

PersistentManagerBase

PersistentManagerBase类是所有持久化管理器的父类。StandardManager和一个持久化manager主要的不同是:后面有一个store。一个store代表一个辅助存储器用来管理session对象。PersistentManagerBase类使用一个private的叫做store的对象引用。
private Store store = null;

在一个持久化manager中,session对象可以被备份和被清理。当一个session对象被备份,这个session对象被复制到一个store中,原来的session对象还在内存中。如果服务器down掉了,活动的session对象可以在store中重新获取。当一个session对象它被因为活动的session对象的数量超过了指定的数量或者session对象已经空闲了很长一段时间,清理的目的是为了节省内存空间。

在Tomcat 4中PersistentManagerBase实现了java.lang.Runnable来持有一个单独的线程来定期备份和清理活动的session。
public void run() { 
   // Loop until the termination semaphore is set 
   while (!threadDone) { 
     threadSleep(); 
     processExpires(); 
     processPersistenceChecks(); 
   } 
}

processExpired方法,就像在StandardManager中的一样,是检查session对象是否超时。processPersistenceChecks方法调用了其他三个方法:
public void processPersistenceChecks() { 
   processMaxIdleSwaps(); 
   processMaxActiveSwaps(); 
   processMaxIdleBackups(); 
}

在Tomcat 5中,PersistentManagerBase没有实现java.lang.Runnable接口。备份和清理工作是由backgroundProcess manager处理的。它由与它相关联的StandardContext实例定期地调用。
Swap Out

PersistentManagerBase类采用一系列规则来清理session对象。一个session对象在超过最大活动session的maxActiveSessions变量值或者session已经空闲了一段很长时间时被清理。

这种有太多的session对象的情况下,一个PersistentManagerBase实例简单地清理任何一个session知道活动session对象的值等于maxActiveSessions。

在一个session对象空闲了很长一段时间这种情况,PersistentManagerBase类使用两个变量来决定是否这个session对象被清理:minIdleSwap和maxIdleSwap。一个session对象在它的lastAccessedTime超过minIdleSwap和maxIdleSwap时,会被清理掉。为了保护被清理掉,你可以设置maxIdleSwap为负数。

因为一个活动的session可以被清理,它可以被重新加载到内存和存储到一个store中。findSession (String id)方法首先在内存中寻找Session实例,如果没有,就在store中搜索。下面是PersistentManagerBase类方法的实现。
public Session findSession(String id) throws IOException { 
   Session session = super.findSession(id); 
   if (session != null) 
     return (session); 
   // not found in memory, see if the Session is in the Store 
   session = swapIn(id); // swapIn returns an active session in the Store 
   return (session); 
}

Back-up

不是所有活动的session对象会被备份。一个PersistentManagerBase实例只会备份空闲时间比maxIdleBackup的值大的session对象。processMaxIdleBackups方法负责备份session对象。

PersistentManager

PersistentManager继承了PersistentManagerBase:
Listing 9.5: The PersistentManager class   
 
package org.apache.catalina.session; 
public final class PersistentManager extends PersistentManagerBase { 
   // The descriptive information about this implementation. 
   private static final String info = "PersistentManager/1.0"; 
   // The descriptive name of this Manager implementation (for logging). 
   protected static String name = "PersistentManager"; 
   public String getInfo() { 
     return (this.info); 
   } 
   public String getName() { 
     return (name); 
   } 
} 


DistributedManager

Tomcat 4中提供了DistrubutedManager类。是PersistentManagerBase的一个子类,DistributedManager被用在一个集群环境,有两个或更多节点。一个节点代表一个Tomcat的部署。在一个集群中的节点可以存在于不同的计算机中或在同一台计算机中。在集群环境中,
每一个节点必须使用一个DistributedManager实例作为它的Manager来支持session的复制。这个是DistributedManager的主要工作。

为了达到复制的目的,DistributedManager发送通知给其它节点。不管说么么时候一个session对象被创建或销毁。此外,一个节点必须能够接收到其它节点的通知。一个HTTP请求可以在集群中的任何一个节点得到服务。

发送和接收其它节点的DistributedManager实例的通知,Catalina提供org.apache.catalina.cluster包的类。ClusterSender类用来发送通知给其它节点,ClusterReceiver类用来接收通知。

DistrbutedManager的createSession方法必须创建一个session对象存储到当前实例,使用ClusterSender实例发送通知给其它节点。
Listing 9.6: The createSession method   
 
public Session createSession() { 
   Session session = super.createSession(); 
   ObjectOutputStream oos = null; 
   ByteArrayOutputStream bos = null; 
   ByteArraylnputStream bis = null; 
 
   try { 
     bos = new ByteArrayOutputStream(); 
     oos = new ObjectOutputStream(new BufferedOutputStream(bos)); 
 
     ((StandardSession)session).writeObjectData(oos); 
     oos.close(); 
     byte[] obs = bos.toByteArray(); 
     clusterSender.send(obs); 
     if(debug > 0) 
       log("Replicating Session: "+session.getId()); 
   }
   catch (IOException e) { 
     log("An error occurred when replicating Session: " + session.getId()); 
   } 
 
   retun (session); 
} 

首先createSession方法调用父类的createSession方法来创建一个session对象。它发送session对象作为一个字节数组。

DistribubedManager类也实现了java.lang.Runnable,它有一个独立的线程把session对象超时,接收其它节点来的通知。
public void run() { 
   // Loop until the termination semaphore is set 
   while (!threadDone) { 
     threadSleep(); 
     processClusterReceiver(); 
     processExpires(); 
     processPersistenceChecks(); 
   } 
}


Stores

一个store由一个org.apache.catalina.Store接口表示,它是一个提供永久存储session的组件。
Listing 9.7: The Store interface   
 
package org.apache.catalina; 
import java.beans.PropertyChangeListener; 
import java.io.IOException; 
 
public interface Store { 
   public String getInfo(); 
   public Manager getManager(); 
   public void setManager(Manager manager); 
   public int getSize() throws IOException; 
   public void addPropertyChangeListener(PropertyChangeListener  listener); 
   public String[] keys() throws IOException; 
   public Session load(String id) throws ClassNotFoundException, IOException; 
   public void remove(String id) throws IOException; 
   public void clear() throws IOException; 
   pubiic void removePropertyChangeListener(PropertyChangeListener listener); 
   public void save(Session session) throws IOException; 
} 

Store接口中两个最重要的方法:save和load。save方法存储指定的session对象要一个永久存储器。load方法用给出的指定标识符从存储器中加载session对象。keys方法返回一个字符串数组,这个数组包含所有的session标识符。

类图:


StoreBase

StoreBase类是一个抽象类,它为它的两个子类提供了常用的方法:FileStore和JDBCStore。StoreBase类没有实现Store接口的save和load方法,因为这个方法的实现依赖存储类型来存储session。

Tomcat 4中的StoreBase类持有一个单独的线程来定期地检查超时的session和移除活动session集合中超时的session。
public void run() { 
   // Loop until the termination semaphore is set 
   while (!threadDone) { 
     threadSleep(); 
     processExpires(); 
   } 
}

processExpires方法获取所有的活动的session和检查每一个lastAccessedTime的值,移除session对象空闲了很长时间。
Listing 9.7: the processExpires method   
 
protected void processExpires() { 
   long timeNow = System.currentTimeMillis(); 
   String[] keys = null; 
   if (!started) 
     return; 
   try { 
     keys = keys(); 
   } 
   catch (IOException e) { 
     log (e.toString()); 
     e.printStackTrace(); 
     return; 
   }
   for (int i = 0; i < keys.length; i++) { 
     try { 
       StandardSession session = (StandardSession) load(keys[i]); 
       if (!session.isValid()) 
         continue;
       int maxInactiveInterval = session.getMaxInactiveInterval(); 
       if (maxInactiveInterval < 0) 
         continue; 
       int timeIdle = // Truncate, do not round up 
         (int) ((timeNow - session.getLastAccessedTime()) / 1000L); 
       if (timeIdle >= maxInactiveInterval) { 
         if ( ( (PersistentManagerBase) manager).isLoaded( keys[i] )) { 
           // recycle old backup session 
           session.recycle(); 
         } 
         else { 
           // expire swapped out session 
           session.expire(); 
         } 
         remove(session.getId()); 
       } 
     }
     catch (IOException e) { 
       log (e.toString()); 
       e.printStackTrace(); 
 
     } 
     catch (ClassNotFoundException e) { 
       log (e.toString()); 
       e.printStackTrace(); 
     } 
   } 
} 


在Tomcat 5中没有特别的线程来调用processExpires方法。这个方法定期地被与它相关联的PersistentManagerBase实例的backgroundProcess方法调用。

FileStore

FileStore方法把session对象存储到文件中。文件是以session对象的标识符为名字,以.session为后缀名。这个文件位于临时的工作目录中。你可以调用Filestore类的setDirectory方法来更改临时目录。

java.io.ObjectOutputStream类是在sava方法中用来串行化session对象。存储在一个Session实例的所有对象都必须实现java.lang.Serializable。反序列化一个session对象是在load方法,java.io.ObjectInputStream类调用。

JDBCStore

JDBCStore类存储session对象到一个数据库中,是通过JDBC来传输的,使用JDBCStore你需要设置驱动名字和链接URL,通过调用各自的setDriverName和setConnectionURL方法。

The Application

本章的应用程序,使用默认连接器,它有一个context作为它的主容器。
这个应用程序有两个包:ex09.pyrmont.core和ex09.pyrmont.startup,在Catalina中使用不同的类。在ex09.pyrmont.core包下有四个类:SimpleContextConfig, SimplePipeline, SimpleWrapper和SimpleWrapperValve.
ex09.pyrmont.startup包下有一个类:Bootstrap。


The Bootstrap Class

main方法开始是设置catalina.base系统属性和初始化默认连接器。
System.setProperty("catalina.base", 
System.getProperty("user.dir")); 
Connector connector = new HttpConnector();

SessionServlet,它创建一个wrapper,命名为: wrapper1.
Wrapper wrapper1 = new SimpleWrapper(); 
wrapper1.setName("Session"); 
wrapper1.setServletclass("SessionServlet");

然后创建一个StandardContext对象,设置它的路径和docBase属性,添加wrapper到context。
Context context = new StandardContext(); 
context.setPath("/myApp"); 
context.setDocBase("myApp"); 
context.addChild(wrapper1); 

接下来start方法添加一个servlet映射。这个映射和第八章的不同。/Session,我们使用myApp/Session作为。
context.addServletMapping("/myApp/Session", "Session")

请求的url:http://localhost:8080/myApp/Session.

context需要一个监听器和一个加载器。
LifecycleListener listener = new SimpleContextConfig(); 
((Lifecycle) context).addLifecycleListener(listener);
// here is our loader 
Loader loader = new WebappLoader(); 
// associate the loader with the Context 
context.setLoader(loader); 
connector.setContainer (context);

现在我们使用一个StandardManager实例,并把它传递给context。
Manager manager = new StandardManager(); 
context.setManager(manager);


最后,我们初始化和启动链接诶器和启动context。
connector.initialize(); 
((Lifecycle) connector).start(); 
((Lifecycle) context).start();


The SimpleWrapperValve Class

Listing 9.8: The invoke method of the SimpleWrapperValve class   
 
public void invoke(Request request, Response response, 
   ValveContext valveContext) throws IOException, ServletException { 
 
   SimpleWrapper wrapper = (SimpleWrapper) getContainer(); 
   ServletRequest sreq = request.getRequest(); 
   ServletResponse sres = response.getResponse(); 
   Servlet servlet = null; 
   HttpServletRequest hreq = null; 
   if (sreq instanceof HttpServletRequest) 
     hreq = (HttpServletRequest) sreq; 
   HttpServletResponse hres = null; 
   if (sres instanceof HttpServletResponse) 
     hres = (HttpServletResponse) sres;
   // pass the Context to the Request object so that 
   // the Request object can call the Manager 
   Context context = (context) wrapper.getparent(); 
   request.setcontext(context);

   // Allocate a servlet instance to process this request 
   try { 
     servlet = wrapper.allocate(); 
     if (hres!=null && hreq!=null) { 
       servlet.service(hreq, hres); 
     } 
     else { 
       servlet.service(sreq, sres); 
     } 
   } 
   catch (ServletException e) { 
   } 
} 


你要访问wrapper,你可以调用Container接口的getParent方法获取这个context。注意:wrapper被添加到context中了。一旦你有一个context,你可以调用Request接口的setContext方法。

org.apache.catalina.connector.HttpRequestBase类的private的doGetSession方法调用Context接口的getManager方法来获取manager。
// Return the requested session if it exists and is valid 
Manager manager = null; 
if (context != null) 
manager = context.getManager();

当有了一个manager,就可以直接获取一个session对象或创建一个新的session对象。

总结:本章讨论manager,它是在session管理里面的一个管理session的组件。组件类型和一个manager怎么持久化session对象到store中。
  • 大小: 39.7 KB
1
7
分享到:
评论

相关推荐

    tomcat原理解析书(how-tomcat-works)中文版

    适合读者 1.jsp/servlet 开发人员,想了解 tomcat 内部机制的 coder;...2.想加入 tomcat 开发团队的 coder; 3.web 开发人员,但对软件开发很有兴趣的 coder; 4.想要对 tomcat 进行定制的 coder。

    全国计算机等级考试二级openGauss数据库程序设计样题解析

    主要内容涵盖单选题和操作题两大部分。单选题涉及openGauss数据库的基本概念、数据模型、SQL语法、事务管理和用户权限等方面的知识点。操作题则围绕一个名为bookdb的图书购买信息数据库展开,具体任务包括插入图书信息、更新顾客信息、删除购买记录、查询特定图书信息以及创建视图、存储过程和触发器等实际操作。每道题目均附带详细的解题步骤和最终答案。

    新建 Microsoft Word 文档 (9).docx

    新建 Microsoft Word 文档 (9).docx

    Delphi 12.3控件之nrCommLib Pro v9.54 Full Source for D10.3-D12.7z

    Delphi 12.3控件之nrCommLib Pro v9.54 Full Source for D10.3-D12.7z

    三菱PLC FX5U控制四轴伺服系统:硬件配置、参数设置及运动控制详解

    内容概要:本文详细介绍了使用三菱PLC FX5U控制四轴伺服系统的全过程,涵盖硬件配置、电气接线、参数设置以及运动控制逻辑。硬件方面,选用三菱FX5U-64MT作为主控制器,搭配四个MR-JE-20A伺服驱动器和其他必要组件。软件部分则深入探讨了轴参数初始化、原点回归、多轴联动、HMI界面设计及报警处理等关键技术环节。特别针对旋转轴的特殊处理进行了详细说明,如双速原点回归、绝对定位指令的应用等。此外,还提供了调试经验和优化技巧,确保系统的高精度和平稳运行。 适合人群:从事自动化控制系统设计、调试的技术人员,尤其是对三菱PLC和伺服系统有一定了解的研发人员。 使用场景及目标:适用于工业自动化领域的四轴伺服控制系统开发,旨在帮助工程师掌握从硬件选型到软件编程的一整套解决方案,提高项目的成功率和技术水平。 其他说明:文中附有多份参考资料,包括完整的程序文件、界面工程、CAD接线图和伺服参数清单,便于读者进行实际操作和验证。

    分阶段学习:先掌握基础,再深入细分领域 理论与实践结合:学完算法后立刻用代码实现 保持持续学习:AI技术迭代快,需跟踪最新进展

    分阶段学习:先掌握基础,再深入细分领域。 理论与实践结合:学完算法后立刻用代码实现。 保持持续学习:AI技术迭代快,需跟踪最新进展。

    电子硬件课程设计-Word文档

    电子硬件课程设计

    智慧农贸信息化管理平台.zip

    Java项目基于ssm框架的课程设计,包含LW+ppt

    脚本-压测相关-zyx编写

    脚本-压测相关-zyx编写

    jspm机房预约系统lw+ppt.zip

    Java项目基于ssm框架的课程设计,包含LW+ppt

    app.mobileconfig

    app.mobileconfig

    基于MotorCAD的2极12槽永磁直流有刷电机设计与优化教程

    内容概要:本文详细介绍了使用MotorCAD进行2极12槽永磁直流有刷电机的设计与优化方法。首先,通过Python脚本设置电机的基本参数,如外径、轴向长度、额定转速等。接着,深入探讨了磁钢选型、绕组设置、电磁仿真、热分析等多个关键技术环节。针对常见的设计难题,如齿槽转矩、磁钢充磁方向、绕组跨距等提供了具体的解决方案。同时,还分享了一些提高仿真精度和优化性能的实用技巧,如参数扫描、FEA计算、热管理等。最后,通过实测数据分析验证了设计方案的有效性。 适合人群:电机设计工程师、高校相关专业师生、对电机设计感兴趣的开发者。 使用场景及目标:适用于需要精确设计和优化小型永磁直流有刷电机的场合,帮助用户掌握MotorCAD的具体应用,提高设计效率和产品质量。 其他说明:文中提供的Python和VB脚本示例有助于自动化参数设置和批量处理任务,减少重复劳动。此外,还强调了在设计过程中需要注意的关键技术和常见陷阱,确保设计方案的可行性和可靠性。

    三相逆变器基于PI闭环与解耦控制的MATLAB仿真实现

    内容概要:本文详细介绍了三相逆变器在MATLAB/Simulink环境下的PI闭环控制及解耦控制的实现方法。首先,通过坐标变换将三相电流从静止坐标系转换到旋转坐标系,确保功率守恒并实时更新转子位置角。接着,实现了带有抗饱和处理的PI控制器,防止积分风-up现象。然后,针对d轴和q轴之间的耦合问题,引入了解耦控制,通过低通滤波和交叉耦合项来稳定系统。此外,还讨论了PWM生成模块的死区时间和仿真结果的验证方法,强调了参数调试的重要性和具体策略。 适合人群:电力电子工程师、自动化控制领域的研究人员以及对三相逆变器控制感兴趣的高校师生。 使用场景及目标:适用于需要深入了解三相逆变器控制原理和技术实现的研究项目或工程应用。主要目标是掌握PI控制器的设计、解耦控制的应用及其在MATLAB/Simulink中的仿真实现。 其他说明:文中提供了详细的代码示例和调试技巧,帮助读者更好地理解和实践相关理论。同时提醒读者,仿真成功并不代表实际硬件运行无误,建议在实验过程中准备必要的保护措施。

    58面经面试过程和题目.txt

    58面经面试过程和题目.txt

    OceanBase OBCP 实验指导手册V1.3

    OceanBase OBCP 实验指导手册V1.3

    ABB喷涂机器人IRC5P与PLC Profinet通讯配置及程序号启动详解

    内容概要:本文详细介绍了ABB喷涂机器人IRC5P与PLC通过Profinet通讯进行程序号启动的具体步骤和注意事项。主要内容涵盖Profinet通讯的基本配置,包括设备名称、IP地址设置,RAPID代码编写,任务声明,信号映射,以及调试技巧。文中还分享了许多实际调试中的经验和常见错误,如大小写敏感、IP地址分配、程序号有效性和信号防抖处理等。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是负责机器人与PLC通讯配置的技术人员。 使用场景及目标:帮助技术人员正确配置ABB喷涂机器人IRC5P与PLC之间的Profinet通讯,确保程序号能够顺利启动,避免常见的配置错误和调试难题。 其他说明:文章强调了硬件和软件配置相结合的重要性,并提供了详细的代码示例和调试建议,有助于提高系统的稳定性和可靠性。

    电子硬件课后习题题目及要求.docx

    电子硬件课后习题题目及要求.docx

    亲测开源好用的红盟云发卡源码对接支付宝等支持一件搭建

    亲测开源好用的红盟云发卡源码对接支付宝等支持一件搭建,方便建立自己的发卡平台,源码全部开源无加密,可方便而开使用。 测试环境:php7.2+mysql+宝塔面板 安装教程: ①设置public运行目录 ②设置thinkphp伪静态 ③访问域名填写数据库信息根据提示安装

    Delphi 12.3控件之MiTeC-System-Information-Component-Suite-15.1.0-Full-Source.7z

    Delphi 12.3控件之MiTeC_System_Information_Component_Suite_15.1.0_Full_Source.7z

    Delphi 12.3控件之StyleControls 5.80.7z

    Delphi 12.3控件之StyleControls 5.80.7z

Global site tag (gtag.js) - Google Analytics