1.本来trigger receiver流程的模块和接收者类是放在一个APP Server上的,但由于性能的考虑,这种schedule模块的调度和管理可能会影响业务逻辑的执行,占用业务逻辑执行的系统资源,所以将它放到单独的JVM上运行,作为一个Standalone的java application。这样schedule模块就不能直接通过内存调用接收者流程,接收者必须开放远程rpc服务,让trigger通过远程调用的方法主动调用消息接收者去接受消息。
原来的系统通过MessageReceiverFactory获得一个MessageReceiver 然后主动接收消息。
MessageReceiver:
public interface MessageReceiver {
void invokeProcessFlow(String processId) throws ServerReceiverException;
}
|
ServerMessageReceiver:
public class ServerMessageReceiver implements MessageReceiver {
ServerMessageReceiver() {
}
public void invokeProcessFlow(String processId) throws ServerReceiverException {
//receive message
}
|
MessageReceiverFactory:
public class MessageReceiverFactory {
private static MessageReceiver messageReceiver;
private static void init() throws ServerReceiverException {
messageReceiver = new ServerMessageReceiver();
}
public synchronized static MessageReceiver getMessageReceiver() throws ServerReceiverException {
if(messageReceiver == null) {
init();
}
return messageReceiver;
}
}
|
2.增加RMI服务后:
客户端:
· 客户端通过MessageReceiverFactory获得MessageReceiver的远程版本:RemoteMessageReceiver
· 客户端使用远程版本的MessageReceiver look up出RemotableMessageReceiver的RMI Stub进行远程的RPC调用,通知服务器端接收消息。
public class RemoteMessageReceiver implements MessageReceiver {
private RemotableMessageReceiver messageReceiver;
private String rmiHost;
private int rmiPort;
private String serviceName;
public RemoteMessageReceiver(String host, int port, String serviceName) throws ServerReceiverException {
try{
this.rmiHost = host;
this.rmiPort = port;
this.serviceName = serviceName;
Registry registry = LocateRegistry.getRegistry(rmiHost, rmiPort);
messageReceiver = (RemotableMessageReceiver) registry.lookup(this.serviceName);
}catch(Exception ex) {
throw new ServerReceiverException("look up remote message receiver failed!", this, ex);
}
}
public void invokeProcessFlow(String processId) throws ServerReceiverException {
try {
this.messageReceiver.invokeProcessFlow(processId);
} catch (RemoteException e) {
throw new ServerReceiverException(e.getMessage(), this, e);
}
}
}
|
这里用了适配器模式,对RemotableMessageReceiver进行适配,从而满足MessageReceiver接口的标准,方便MessageReceiverFactory的统一生产,并且使客户端使用的RemoteMessageReceiver和具体使用的通信方法解耦,将来如果不使用RMI, 只需要替换RemotableMessageReceiver就可以了。不会影响客户端的代码。
服务器端:
- 服务器端设置开关,可以开启和关闭远程服务。
- 如果开启远程服务,就需要注册服务,注册的服务对象是提供给客户端用的远程对象,服务端本身使用的MessageReceiver不需要实现RemotableMessageReceiver接口和原来一样实现MessageReceiver接口,从而原有的应用并没有太大影响。
- 服务器端通过MessageReceiverFactory获得MessageReceiver也可以主动接受消息,如果需要提供远程服务,就必须注册远程服务。
这样,服务器端首先增加了RemotableMessageReceiver接口,所有远程对象实现该接口,RMIMessageReceiver提供RMI服务的远程对象,供客户端远程调用。RMIMessageReceiver必须满足RemotableMessageReceiver接口的契约,所以也使用了适配器模式。增加了RMIMessageReceiver后,服务器端使用的MessageReceiver就和RMIMessageReceiver耦合在一起了,为了解耦,我又新增了一个StdMessageReceiver类,作为服务器端本地的MessageReceiver,供服务器端本地调用,StdMessageReceiver用了装饰器模式,对已有的MessageReceiver进行修饰,支持服务器端本地调用,如果以后本地调用加了新的功能就不会影响RMIMessageReceiver的功能了,比如凡是本地调用都需要在服务器端记log,这样就只需要在StdMessageReceiver添加打log的功能,而不会影响RMIMessageReceiver。
MessageReceiverFactory简单工厂用于生产MessageReceiver对象,可能是客户端的RemoteMessageReceiver也可能是服务器端的StdMessageReceiver。
为了在deploy时候就启动RMI服务,我们可以在servlet的init方法中初始化并注册RMI服务,在deetroy方法中相应的取消RMI服务。
RemotableMessageReceiver: 远程服务对象接口
public interface RemotableMessageReceiver extends Remote {
void invokeProcessFlow(String processId) throws ServerReceiverException,
RemoteException;
}
|
RMIMessageReceiver:提供RMI服务的远程对象
public class RMIMessageReceiver implements RemotableMessageReceiver {
private MessageReceiver messageReceiver;
RMIMessageReceiver(MessageReceiver messageReceiver) throws RemoteException {
this.messageReceiver = messageReceiver;
SystemInfo sysInfo = ContextFactory.getSystemConfigContext().getSystemInfo();
System.out.println("beign to bind at rmiport: " + sysInfo.getRmiport());
RMIUtils.bind(sysInfo.getRmiport(), sysInfo
.getReceiverRmiBindName(), this);
}
public void invokeProcessFlow(String processId)
throws ServerReceiverException, RemoteException {
this.messageReceiver.invokeProcessFlow(processId);
}
}
|
SystemInfo存储的是一些配置信息,比如是不是服务器端,是不是需要开启远程服务,如果开启的话相应的host,port和rmi远程对象绑定的服务名
StdMessageReceiver:服务器端使用的MessageReceiver。
public class StdMessageReceiver implements MessageReceiver {
private MessageReceiver messageReceiver;
public StdMessageReceiver(MessageReceiver messageReceiver) {
this.messageReceiver = messageReceiver;
}
public void invokeProcessFlow(String processId) throws ServerReceiverException {
//do some log
this.messageReceiver.invokeProcessFlow(processId);
}
}
|
分享到:
相关推荐
尽管国外已有成熟的邮件系统,但国内的邮件服务仍有待完善和普及。因此,设计一个简单易用的Java邮件系统,既能满足用户需求,也能推动国内邮件服务的发展。 2. 文献综述 J2EE架构是目前企业级应用开发的主流选择,...
- **与现有REST服务集成**:如果已有REST服务,Dubbo-rpc-rest可以方便地与这些服务集成,实现微服务间的互通。 3. **RESTful服务与Dubbo的结合** 将RESTful服务与Dubbo结合,可以充分利用两者的优势。RESTful...
Java Management Extensions(JMX)是Java平台提供的一种标准管理框架,用于管理和监控应用程序、系统和服务。在本场景中,我们关注的是如何利用JMX来远程监控服务器上的关键资源,如CPU利用率、内存状态、已加载类...
java.security.interfaces 提供的接口用于生成 RSA Laboratory Technical Note PKCS#1 中定义的 RSA(Rivest、Shamir 和 Adleman AsymmetricCipher 算法)密钥,以及 NIST 的 FIPS-186 中定义的 DSA(数字签名算法)...
- **LTO(线性磁带开放标准)**:指的是线性磁带开放标准,目前已有多个版本,比如 LTO-4,每一代都提供了更高速的数据传输能力和更大的存储容量。 - **KMIP(密钥管理互操作性协议)**:KMIP 是一种网络协议,用于...
- 使用网络工具如`netstat`或`telnet`等验证端口是否已被正确占用,并确保服务正常运行。 #### 四、示例代码 为了更好地理解上述步骤,下面提供一个简单的示例来展示如何修改`bindings.xml`文件中的端口配置: ``...
java.security.interfaces 提供的接口用于生成 RSA Laboratory Technical Note PKCS#1 中定义的 RSA(Rivest、Shamir 和 Adleman AsymmetricCipher 算法)密钥,以及 NIST 的 FIPS-186 中定义的 DSA(数字签名算法...
- **方法引用**:直接引用已有的方法,如`::`操作符,减少冗余代码。 - **默认方法**:接口中可以定义带有默认实现的方法,增强了接口的功能。 - **Stream API**:提供了一种新的集合操作方式,方便进行数据过滤...
java.security.interfaces 提供的接口用于生成 RSA Laboratory Technical Note PKCS#1 中定义的 RSA(Rivest、Shamir 和 Adleman AsymmetricCipher 算法)密钥,以及 NIST 的 FIPS-186 中定义的 DSA(数字签名算法)...
与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。...
8. **就业服务**:与多家企业有合作关系,确保学员毕业后一周内找到工作,合作企业包括IBM、中国移动等。 9. **培训课程详解**:针对Oracle和MySQL数据库进行深入讲解,并根据市场需求和合作企业的要求定制课程内容...
java.security.interfaces 提供的接口用于生成 RSA Laboratory Technical Note PKCS#1 中定义的 RSA(Rivest、Shamir 和 Adleman AsymmetricCipher 算法)密钥,以及 NIST 的 FIPS-186 中定义的 DSA(数字签名算法)...
jdk_api_1_6帮助开发 java.applet 提供创建 applet 所必需的类和 applet 用来与其 applet 上下文通信的类。 java.awt 包含用于创建用户界面和绘制图形图像的所有类。 java.awt.color 提供用于颜色空间的类。 ...
连接器可以是基于HTTP的,也可以是基于RMI的,甚至是通过Java消息服务(JMS)的连接。 4. 通知系统(Notifications System):通知系统是JMX中用于异步事件传播的机制。MBeans能够产生各种类型的事件或通知,这些...
java.security.interfaces 提供的接口用于生成 RSA Laboratory Technical Note PKCS#1 中定义的 RSA(Rivest、Shamir 和 Adleman AsymmetricCipher 算法)密钥,以及 NIST 的 FIPS-186 中定义的 DSA(数字签名算法)...
J2EE(Java 2 Platform, Enterprise Edition)是Sun Microsystems(现已被Oracle收购)推出的一个企业级应用开发平台,专为构建分布式、多层的、面向服务的(SOA,Service-Oriented Architecture)应用程序而设计。...