1 / 20

实验室实习报告

实验室实习报告. 刘澜涛 00848200. 收获. java RMI机制 Jmeter测试工具 java 线程池机制 工作进展情况. java RMI机制. java RMI机制通俗的说就是客户端利用服务器端对象的替身(Stub),像调用本地对象的方法一样来调用服务器端对象的方法。 服务器段方法执行完毕后,客户端像获得本地对象参数一样获得服务器端返回的参数 RMI机制为开发者屏蔽了底层的通信细节。. 编写java RMI程序. 远程对象接口 需要继承Remote类 服务器端远程对象实现 实现远程对象接口的方法 此类中实现的方法在服务器端执行

Download Presentation

实验室实习报告

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 实验室实习报告 刘澜涛 00848200

  2. 收获 • java RMI机制 • Jmeter测试工具 • java 线程池机制 • 工作进展情况

  3. java RMI机制 • java RMI机制通俗的说就是客户端利用服务器端对象的替身(Stub),像调用本地对象的方法一样来调用服务器端对象的方法。 • 服务器段方法执行完毕后,客户端像获得本地对象参数一样获得服务器端返回的参数 • RMI机制为开发者屏蔽了底层的通信细节。

  4. 编写java RMI程序 • 远程对象接口 • 需要继承Remote类 • 服务器端远程对象实现 • 实现远程对象接口的方法 • 此类中实现的方法在服务器端执行 • 服务器端程序 • 利用Naming.bind注册服务器端对象

  5. 编写java RMI程序 • 客户端程序 • 通过Naming.lookup()查找指定服务器上的对象 • 查找到对象后则可直接调用该对象的方法 • 客户端代码存根 • 利用rmic生成服务器端的代码存根*_Stub.class

  6. Jmeter测试工具 • Jmeter测试工具是Apache公司开发的基于java的开源压力测试工具,是100%用java实现的。 • 其利用大量的客户端线程来模拟大量的客户端请求,从而进行压力测试。

  7. 利用Jmeter进行测试 • 建立线程组(Thread Group) • Thread Group是任何一个测试计划的开始点,可以设置线程数量,建立所有线程的最短时间,每一个线程循环的次数 • 建立取样器(Sampler) • Sampler 告知JMeter 发送请求到server 端 • JMeter自带的Sampler有FTP、HTTP、JDBC、Java Object、LDAP、SOAP/XML-RPC、Web Service • 可以利用java request sampler来实现自己的取样器,我的RMI测试就是利用JMeter的API自己实现取样器来实现的。

  8. 利用Jmeter进行测试 • 建立监听器(Listener) • 用来统计测试结果。 • JMeter中有大量的自带监听器,可以方便地生成测试数据图表。 • 对于复杂的测试计划还可使用controller等工具来实现复杂的测试逻辑。

  9. Java线程池机制 • Java的线程池类为java.util.concurrent.ThreadPoolExecutor • ThreadPoolExecutor的常用构造方法为: • ThreadPoolExecutor( int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler)

  10. Java线程池机制 参数作用: • corePoolSize: 线程池维护线程的最少数量 • maximumPoolSize:线程池维护线程的最大数量 • keepAliveTime: 线程池维护线程所允许的空闲时间 • unit: 线程池维护线程所允许的空闲时间的单位 • workQueue: 线程池所使用的缓冲队列 • handler: 线程池对拒绝任务的处理策略

  11. Java线程池机制 • 当一个任务通过execute(Runnable)方法欲添加到线程池时: • 如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。 • 如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。

  12. java线程池机制 • l 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。 • l 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。 • l 当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。

  13. Java线程池机制 • 也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。 • 通过向ThreadPoolExecutor的构造方法中传入不同的参数,我们可以建立各种各样的线程池。

  14. 工作进展情况 • 第一阶段自己实现多线程客户端程序,进行压力测试,得到的初步结论是: • RMI的线程池大小非固定 • 当客户端请求过多时,服务器端会拒绝客户端的链接 • 存在问题:手动实现的客户端测试程序可信度不高,需利用工具进行测试。

  15. 工作进展情况 • 第二阶段工作,利用JMeter压力测试工具,自己实现RMI取样器,对RMI服务器进行压力测试,测试结论: • RMI线程池大小非固定 • 客户端请求多于1200个后,服务器端不稳定,开始有错误率出现(即出现服务器端拒绝连接的情况) • 明显观察到RMI服务器端的处理线程和连接线程在实现上有所区别:处理线程早于连接线程半分钟左右销毁。

  16. 工作进展情况 • 第三阶段工作,通过阅读RMI源代码,比照结果程序取得最终结论。 • Java RMI的线程池传入的参数是: • corePoolSize = 0 • maximumPoolSize = Integer.MAX_VALUE • keepAliveTime = 60000ms • unit = TimeUnit.MILLISECONDS • workQueue = new SynchronousQueue<Runnable>() • threadFactory = new ThreadFactory() {....}

  17. 工作进展情况 • 源码与测试结果相符: • 初始情况下线程池中没有线程(corePoolSize == 0) • 当有客户端请求后,线程数量迅速增加(因为工作队列 SynchronousQueue将任务直接提交给线程而不保持它们,是直接提交队列。) • 当客户端请求结束后约1分钟内,若没有新的请求,则线程池中所有线程全部销毁(corePoolSize == 0)

  18. 工作进展情况 • 当前最大问题:服务器端为何会拒绝客户端的连接 • 针对该问题的进展: • 经过分析应该是在TCPTransport.java的下述代码中出现了Exception • try { connectionThreadPool.execute( new ConnectionHandler(socket, clientHost)); } catch (RejectedExecutionException e) { closeSocket(socket); tcpLog.log(Log.BRIEF, "rejected connection from " + clientHost); }

  19. 工作进展情况 • 而ThreadPoolExecutor.java中的execute方法如下: • public void execute(Runnable command) { • if (command == null) • throw new NullPointerException(); • if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) { • if (runState == RUNNING && workQueue.offer(command)) { • if (runState != RUNNING || poolSize == 0) • ensureQueuedTaskHandled(command); • } • else if (!addIfUnderMaximumPoolSize(command)) • reject(command); // is shutdown or saturated • } • } 其中reject方法抛出Exception

  20. 工作进展情况 • 根据RMI线程池的参数配置情况,很可能是在addIfUnderMaximumPoolSize(command)方法中出现了问题 • 这个问题还有待进一步查看源码来解决。

More Related