`

基于xmlrpc的远程控制管理

阅读更多

此文转自:http://hellohank.iteye.com/blog/773894

前段时间在做一个日终系统(统一管理所有客户端系统中各定时任务的一个系统)时,实现了其中一个远程管理客户端程序运行状态的模块。这里写出来与大家共享,如有不足之处,希望大家指出共同探讨完善!
在这个远程控制的模块中,对其的基本的需求如下:
· 启动/终止等远程客户端系统中指定的程序;
· 请求要异步,不能占用服务端系统(即日终系统)的资源,即启动客户端程序之后,就与客户端断开连接,让客户端自己运行;
· 可以随时查看指定客户端的指定程序的运行状态,便于监控;
· 如果客户端程序有发生线程死琐、无法连接服务等环境异常时,能够自动预警(即实时监控);
· 程序执行过程中(包括执行成功后)各种对应的状态可以返回到服务端;

根据上面的需求,首先想到的是这个模块的结构将是服务器/客户端模式。考虑使用这种模式的设计,则接下来应该考虑选择什么样的远程方式。当然,如果自己实现一个远程连接功能,小弟自认为能力还不足,呵呵,所以不得不从现有的远程连接方式中选择一个作为自己远程连接的基础。
在对比各种远程方式的对比中,我发现两种远程技术满足我的要求(可以用于异构系统间、调用方式灵活、使用上可以无限扩展):xmlrpc和JMX。
再继续对比这两种技术的优缺点:
优点:
 xmlrpc:配置简单、使用方便;
 JMX:JDK中自带的,因此不需要第三方jar包支持即可使用;同时也可以动态加载/卸载客户端bean(这是我最想要的功能)
缺点:
 xmlrpc:需要第三方jar包支持;
 JMX:需要服务端开通相应的端口支持,因此可能会存在很大的安全隐患;
对比上面主要、简单的优缺点之后,考虑到在企业应用中安全问题往往是占优先位置的,而且最主要的是,JMX在企业应用的发布时,需要开端口,这个过程挺痛苦的。因此,这里不得不摒弃JMX(虽然我也用JMX验证并实现了整个模块的控制功能)。
在选择了xmlrpc为远程连接的工具之后,就着手设计整个结构了:

整体设计
从使用角度来划分其总体设计:先在服务端发起一个操作请求,传输到客户端,客户端作相应的响应,然后将操作的最终结果返回服务端,便于服务端的后续操作。在额外的角度来说,还有一个实时监控功能。从这里来看,由于在请求方面来说,服务端与客户端都相互有信息传递的功能,因此,这里的整体分为三个模块:服务端——公共端——客户端。
其总体设计的UML图如下:

 

 

在上图中,灰色表示服务端的系统(即日终系统)、深蓝色表示服务端模块、淡黄色表示公共模块、桔黄色表示客户端模块、青色表示客户端系统。其中,灰色和青色是在具体使用时的结合部分。真正的该远程控制模块的部分为:深蓝色、淡黄色和桔黄色。

详细设计
服务端模块
在服务端模块中主要的功能是主动发起请求与实时监控!这两个类分别是OssXmlrpcClientFactory、OssListenClientStatusExcutor。
OssXmlrpcClientFactory类主要是提供对客户端操作的主要一些接口,当然,也有方便扩展的接口。
在上面的代码中,其方法中主要提供了常用的操作!再看监听程序:OssListenClientStatusExcutor。从其中的代码(见附件中的代码)也可以看出,这里是监控指定的客户端系统中指定的方法。
客户端模块
在客户端需要说明客户端受控程序遵守的规则,即需要继承OssXmlClientSupport类,表示该类接受服务端的控制,也就是相当于接受协议一样,这样可以防止一些不愿意被控制的类也被误控!
为了将程序执行的状态返回到服务端,客户端需要一个执行回返状态的功能类:ConnectServerExcutor。
这两个类的详细功能请参考代码!
公共模块
除了上面两个模块所说的功能以外,其余的功能(如:线程管理、远程连接响应处理等)都属于公共模块中内容,这一模块在客户端/服务端都需要!
在这个模块中,重要的类有如下:
· OssXmlrpcRemoteExcutor。这是远程响应的类。
· OssXmlrpcServlet。这是初始化OssXmlrpcRemoteExcutor到xmlrpc的环境中以及将每次远程请求转为单例模式。xmlrpc执行时是需要将被调用的类的信息存放到它的容器中,这里有比较详细的说明:http://former.iteye.com/blog/223673,我这里因为只需要通过OssXmlrpcRemoteExcutor作为“网关”,因此我因需要将它加入到xmlrpc中即可,其关键代码如下:

Java代码 复制代码
  1. mapping.load(Thread.currentThread().getContextClassLoader(), getDefaultProps());   
  2. ……   
  3.      /**  
  4.   * 将提供服务的类,从系统中加载进来  
  5.   */  
  6.  protected Properties getDefaultProps() {   
  7.   Properties props = new Properties();   
  8.   props.put(OssXmlrpcRemoteExcutor.class.getSimpleName(), OssXmlrpcRemoteExcutor.class.getName());   
  9.   return props;   
  10.  }  
mapping.load(Thread.currentThread().getContextClassLoader(), getDefaultProps());
……
     /**
  * 将提供服务的类,从系统中加载进来
  */
 protected Properties getDefaultProps() {
  Properties props = new Properties();
  props.put(OssXmlrpcRemoteExcutor.class.getSimpleName(), OssXmlrpcRemoteExcutor.class.getName());
  return props;
 }

 

使用说明
服务端系统
1、环境配置
· 加载xmlrpc的三个jar包。
· 服务端需要实现:OssXmlrpcRemoteResponse接口的类。如果不是Spring容器的话,需要重新实现FindInstanceClass接口并在OssXmlrpcUtils中重新指定。
· 由于需要接受客户端传递回来的请求,因此需要在web.xml中配置如下:

Xml代码 复制代码
  1. <servlet>  
  2.  <servlet-name>XmlRpcServlet</servlet-name>  
  3.  <servlet-class>com.cloudtech.xmlrpc.common.OssXmlrpcServlet   
  4.  </servlet-class>  
  5. </servlet>  
  6. <servlet-mapping>  
  7.  <servlet-name>XmlRpcServlet</servlet-name>  
  8.  <url-pattern>/xmlrpc</url-pattern>  
  9. </servlet-mapping>  
 <servlet>
  <servlet-name>XmlRpcServlet</servlet-name>
  <servlet-class>com.cloudtech.xmlrpc.common.OssXmlrpcServlet
  </servlet-class>
 </servlet>
 <servlet-mapping>
  <servlet-name>XmlRpcServlet</servlet-name>
  <url-pattern>/xmlrpc</url-pattern>
 </servlet-mapping>

 
2、初始化
这里的初始化其实是初始化两个内容:远程连接的连接配置信息,即xmlrpc远程配置信息;监听程序。具体的初始化方式示例如下:

Java代码 复制代码
  1. import java.net.URL;   
  2.   
  3. import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;   
  4.   
  5. import com.cloudtech.xmlrpc.common.OssXmlrpcPoolManager;   
  6. import com.cloudtech.xmlrpc.server.OssListenClientStatusExcutor;   
  7.   
  8. public class OssXmlrpcRemoteInit {   
  9.     public void init() {   
  10.         // TODO 如果不希望影响系统启动速度,可以启用新线程执行下面的过程   
  11.         initRemote();   
  12.         initListener();   
  13.     }   
  14.   
  15.     /**  
  16.      * 初始化监听器  
  17.      */  
  18.     protected void initListener() {   
  19.         // TODO 先初始化需要监听的程序,这里就不实现了   
  20.         OssListenClientStatusExcutor.startListen();   
  21.     }   
  22.   
  23.     /**  
  24.      * 初始化远程连接。  
  25.      */  
  26.     protected void initRemote() {   
  27.         XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();   
  28.         try {   
  29.             // 连接到客户端。   
  30.             config.setServerURL(new URL("http://tfc.vemic.com:8081/xmlrpc"));// 这里是客户端的xmlrpc配置   
  31.             config.setEnabledForExtensions(true);   
  32.             config.setEnabledForExceptions(true);   
  33.             config.setBasicEncoding("GBK");   
  34.             config.setConnectionTimeout(30000);   
  35.             config.setContentLengthOptional(false);   
  36.             config.setReplyTimeout(0);   
  37.             OssXmlrpcPoolManager.createXmlRpcClient("localhost", config);// 这是连接池管理类。   
  38.         } catch (Exception e) {   
  39.             e.printStackTrace();   
  40.         }   
  41.     }   
  42. }  
import java.net.URL;

import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;

import com.cloudtech.xmlrpc.common.OssXmlrpcPoolManager;
import com.cloudtech.xmlrpc.server.OssListenClientStatusExcutor;

public class OssXmlrpcRemoteInit {
	public void init() {
		// TODO 如果不希望影响系统启动速度,可以启用新线程执行下面的过程
		initRemote();
		initListener();
	}

	/**
	 * 初始化监听器
	 */
	protected void initListener() {
		// TODO 先初始化需要监听的程序,这里就不实现了
		OssListenClientStatusExcutor.startListen();
	}

	/**
	 * 初始化远程连接。
	 */
	protected void initRemote() {
		XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
		try {
			// 连接到客户端。
			config.setServerURL(new URL("http://tfc.vemic.com:8081/xmlrpc"));// 这里是客户端的xmlrpc配置
			config.setEnabledForExtensions(true);
			config.setEnabledForExceptions(true);
			config.setBasicEncoding("GBK");
			config.setConnectionTimeout(30000);
			config.setContentLengthOptional(false);
			config.setReplyTimeout(0);
			OssXmlrpcPoolManager.createXmlRpcClient("localhost", config);// 这是连接池管理类。
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 
客户端系统
1、环境配置
· 加载xmlrpc三个jar包。
· 加载远程控制模块的公共模块包、客户端模块包。
· 由于需要被服务端连接操作,因此需要对外提供xmlrpc远程服务,因此需要在web.xml中配置如下:
 

Java代码 复制代码
  1. <servlet>   
  2.   <servlet-name>XmlRpcServlet</servlet-name>   
  3.   <servlet-class>com.cloudtech.xmlrpc.common.OssXmlrpcServlet   
  4.   </servlet-class>   
  5.  </servlet>   
  6.  <servlet-mapping>   
  7.   <servlet-name>XmlRpcServlet</servlet-name>   
  8.   <url-pattern>/xmlrpc</url-pattern><!-- 注意这里的配置与上面的代码的客户端连接的对应关系 -->   
  9.  </servlet-mapping>  
<servlet>
  <servlet-name>XmlRpcServlet</servlet-name>
  <servlet-class>com.cloudtech.xmlrpc.common.OssXmlrpcServlet
  </servlet-class>
 </servlet>
 <servlet-mapping>
  <servlet-name>XmlRpcServlet</servlet-name>
  <url-pattern>/xmlrpc</url-pattern><!-- 注意这里的配置与上面的代码的客户端连接的对应关系 -->
 </servlet-mapping>

 
· 为了将执行的状态返回到服务端,这里还需要配置ConnectServerExcutor类到系统环境中(如果该类中的默认值与服务端的配置是一致的,则倒可以不需要配置),其配置示例:
 

Xml代码 复制代码
  1. <bean class="com.cloudtech.xmlrpc.client.ConnectServerExcutor">  
  2.  <property name="serverURL" value="http://tfc.vemic.com/xmlrpc" />  
  3. </bean>  
 <bean class="com.cloudtech.xmlrpc.client.ConnectServerExcutor">
  <property name="serverURL" value="http://tfc.vemic.com/xmlrpc" />
 </bean>

2、编写代码
接下来就可以使用它的控制功能了:

Java代码 复制代码
  1. import org.springframework.stereotype.Service;   
  2.   
  3. import com.cloudtech.xmlrpc.client.OssXmlClientSupport;   
  4.   
  5. @Service  
  6. public class OssTriggerDemo extends OssXmlClientSupport {//注意这里继承了OssXmlClientSupport   
  7.  public void execute() {   
  8.   System.err.println("executeDemo...");   
  9.   for (int i = 1true; i++) {   
  10.    System.out.println("第" + i + "次循环!");   
  11.    try {   
  12.     Thread.sleep(100);   
  13.    } catch (InterruptedException e) {   
  14.     e.printStackTrace();   
  15.    }   
  16.   }   
  17.  }   
  18. }  
import org.springframework.stereotype.Service;

import com.cloudtech.xmlrpc.client.OssXmlClientSupport;

@Service
public class OssTriggerDemo extends OssXmlClientSupport {//注意这里继承了OssXmlClientSupport
 public void execute() {
  System.err.println("executeDemo...");
  for (int i = 1; true; i++) {
   System.out.println("第" + i + "次循环!");
   try {
    Thread.sleep(100);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
 }
}

 注意:上面的@Service是使用Spring的注解将该类扫描到Spring容器中去,这样“网关”类OssXmlrpcRemoteExcutor就可以通过Spring获取到该类。
3、控制演示
在服务端,发起控制请求:

Java代码 复制代码
  1. public void testRemote() {   
  2.  try {   
  3.   OssXmlrpcClientFactory.execute("localhost""OssTriggerDemo.execute");   
  4.  } catch (OssXmlrpcException e) {   
  5.   e.printStackTrace();   
  6.  }   
  7. }  
 public void testRemote() {
  try {
   OssXmlrpcClientFactory.execute("localhost", "OssTriggerDemo.execute");
  } catch (OssXmlrpcException e) {
   e.printStackTrace();
  }
 }

 
说明
· 如果需要认证,则可以在OssXmlrpcServlet、ConnectServerExcutor有对应的用户名、密码设置。
· 客户端受控的类需要加载到环境中,或者,可以重新实现接口FindInstanceClass来获取到指定类的实例化。

结语
· 这是一开始的雏形,现在应用于公司的日终系统中之后,有些地方已经完善过了,具体改的地方也不记得了……
· 由于能力有限,写出的也点这个水平了,希望大家能够给出建议完善它!

分享到:
评论

相关推荐

    波士顿房价数据集Boston House Price

    波士顿房价数据集Boston House Price 全网最便宜

    FPGA实现UDP协议(包括ARP、ICMP)

    三种实现FPGA实现UDP协议的代码工程(包括ARP、ICMP),包含使用设计文档。 第一种,米联客的DCP封装包 第二种,正点原子的源码工程 第三种,基于正点原子的赛灵思MAC核的代码工程。

    Red-Hat-Enterprise-Linux-7-RPM-Packaging-Guide-en-US

    Red_Hat_Enterprise_Linux-7-RPM_Packaging_Guide-en-US

    Matlab 三维人脸识别系统 V 4.3.zip

    Matlab 三维人脸识别系统 V 4.3.zip

    信捷XD PLC MODBUS控制阀岛通信 案例程序

    信捷XD PLC MODBUS控制阀岛通信 案例程序

    常用进制转换器16进制10进制2进制转换计算器..exe

    大家好呀!今天来介绍一款常用进制转换器,也就是 16 进制、10 进制、2 进制转换计算器。有了它,你可以轻松实现不同进制之间的快速转换。无论是将 16 进制转换为 10 进制或 2 进制,还是从其他进制转换过来,它都能准确而高效地完成。无论是在计算机编程、数字电路等领域,还是日常对进制转换有需求的时候,它都能成为你的得力小助手,让进制转换不再麻烦,快来试试吧!

    微信小程序:智能排队取号系统 - 地图组件集成

    这款微信小程序是一个创新的智能排队取号系统,专为提高服务行业的效率和顾客满意度而设计。它通过集成地图组件,为用户提供了一个直观、易用的排队和取号解决方案。用户可以在小程序中查看各个服务点的位置,实时了解排队情况,并进行远程取号。 小程序的主要功能包括: 实时排队信息:用户可以实时查看各个服务点的排队情况,包括当前排队人数、预计等待时间等。 远程取号:用户无需到现场即可通过小程序远程取号,节省了排队等待的时间。 地图导航:集成的地图组件可以帮助用户快速找到服务点的具体位置,并提供导航服务。 取号管理:用户可以在小程序中管理自己的取号信息,包括查看、取消等操作。 此外,小程序还支持多种场景,如餐饮、医疗、银行、政府服务等,适用于各种需要排队取号的服务场合。它不仅提高了服务效率,减少了顾客的等待时间,还为商家提供了客流管理和数据分析的工具。

    520节日520节日表白神器.zip

    520节日520节日表白神器520节日520节日表白神器520节日520节日表白神器520节日520节日表白神器

    JAVA语言考试系统的设计与实现(LW+源代码+文献综述+外文翻译+开题报告).zip

    JAVA语言考试系统的设计与实现(LW+源代码+文献综述+外文翻译+开题报告)

    相移法偏移MATLAB代码.zip

    相移法偏移MATLAB代码.zip

    directx修复工具directx修复工具directx修复工具.txt

    directx修复工具directx修复工具directx修复工具directx修复工具

    基于matlab的三维地球建模,需联网.zip

    基于matlab的三维地球建模,需联网.zip

    字符串处理-I.MX6U嵌入式Linux C应用编程学习笔记基于正点原子阿尔法开发板

    字符串处理-I.MX6U嵌入式Linux C应用编程学习笔记基于正点原子阿尔法开发板

    蓝桥杯-基础题C++: 其压缩包中为C++ code

    参加比赛的一些心得:感觉把比赛得那一门语言基础学会,输入输出([我写的python输入输出](https://blog.csdn.net/qq_41392228/article/details/123614298)),([C++的STL](https://blog.csdn.net/qq_41392228/article/details/124825895)),熟练里面的数据结构,如数组,map等,==主要还是基础==。熟悉了后,可以在刷一下基础题,巩固哈学了的基础知识。把基础学好了,拿个奖是没问题的,正常发挥即可。想那个好的名词,就要看看相关的算法了,主要就是暴力的+优化,BFS,DFS,比较难的就是动态规划,得找转换方程。 python版本的可见:https://blog.csdn.net/qq_41392228/article/details/123616441

    基于 Rust + eBPF 丢弃 GFW DNS 污染包

    基于 Rust + eBPF 丢弃 GFW DNS 污染包 GFW 污染 DNS 的方式为抢答,我们只需要丢弃投毒响应即可获得正确的解析结果。通过 eBPF 我们可以在内核中插入代码,相比在用户态启动代理,这样可以获得更好的性能。 要丢弃投毒响应,重点是找到它们的特征。 以 twitter.com 为例,当向 8.8.8.8 请求 twitter.com 的 A 记录时,正常的响应会返回 2 条结果(1Q2A);而 GFW 只会返回 1 条,但是使用了 2 次抢答。2 次抢答包其中一个 IP Identification = 0x0000,另一个 IP Flags = 0x40(Don't fragment);而正常的响应 IPID 不会是 0 并且 IP Flags = 0。 我们只要 Drop 掉符合对应特征的包即可。这时我们可以验证,twitter.com 可以正确解析(fb 等非 google 服务也正常)。

    分数阶傅里叶变换数字水印matlab程序.zip

    分数阶傅里叶变换数字水印matlab程序.zip

    “互动课堂”微信小程序需求.md

    “互动课堂”微信小程序需求.md“互动课堂”微信小程序需求.md“互动课堂”微信小程序需求.md“互动课堂”微信小程序需求.md“互动课堂”微信小程序需求.md“互动课堂”微信小程序需求.md“互动课堂”微信小程序需求.md“互动课堂”微信小程序需求.md“互动课堂”微信小程序需求.md“互动课堂”微信小程序需求.md“互动课堂”微信小程序需求.md“互动课堂”微信小程序需求.md“互动课堂”微信小程序需求.md“互动课堂”微信小程序需求.md“互动课堂”微信小程序需求.md“互动课堂”微信小程序需求.md“互动课堂”微信小程序需求.md

    身高体重等2个文件.zip

    身高体重等2个文件.zip

    ACM 题目、测试用例及参考答案汇编-一次 ACM 协会内部测试.zip

    ACM 题目、测试用例及参考答案汇编——一次 ACM 协会内部测试.zip

Global site tag (gtag.js) - Google Analytics