`
abruzzi
  • 浏览: 454412 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

基于总线的消息服务(BBMS)的设计与实现

阅读更多

前言

异步事件的通知机制在比较有规模的软件设计中必然会有涉及,比如GUI程序中的事件监听器,应用程序模块之间的通信,以及分布式应用中的消息机制等。如果使用语言原生的对象注册通信,则耦合度不可避免的会增大,也就是说,当时间发生时,A要通知B,则A必须知道B的存在。耦合度的增大在一定程度上必然会影响灵活性。所以,另一种模式就是今天要说的总线模式(BUS Based),即所有的监听器将自己挂在总线上,这些监听器互相之间是无法直接通信的,它们可以向总线上push消息,或者从总线上得到消息,从而实现相互间的通信,当然,这种模式会在性能上有一定的额外开销。

BBMS的主页在google code上:http://code.google.com/p/bbms/

总线机制

bbms的客户端程序通过将自己注册在BUS Server上来等待异步事件,这个过程可以是本地的,也可以是远程的。本地的BUS可以作为GUI框架中的事件分发者(dispatcher).JMS(Java Message Service)提供企业级的软件模块之间的通信机制,可以使得多个不同的应用集成为一个大型的应用。通过使用BBMS的远程接口,同样可以达到这样的效果。

BBMS的API

 

/**
 * 
 * 
@author juntao.qiu
 *
 
*/
public class Test{
    
public static void main(String[] args) throws RemoteException{
        
/*
         * create a notifiable entry, declare that it's care of
         * TIMEOUT, CLOSE, and READY event.
         
*/
        Configuration config 
= new RMIServerConfiguration(null0);
        CommonNotifiableEntry entry1 
= 
            
new CommonNotifiableEntry(config, "client1"
                MessageTypes.MESSAGE_TIMEOUT 
| 
                MessageTypes.MESSAGE_CLOSE 
| 
                MessageTypes.MESSAGE_READY);
        
        
/*
         * create another notifiable entry, declare that it's care of
         * OPEN, CLOSE, and TIMEOUT event.
         
*/
        CommonNotifiableEntry entry2 
= 
            
new CommonNotifiableEntry(config, "client2"
                MessageTypes.MESSAGE_OPEN 
| 
                MessageTypes.MESSAGE_CLOSE 
| 
                MessageTypes.MESSAGE_TIMEOUT);
        
        
// register them to the remote Message BUS to listener events
        entry1.register();
        entry2.register();
        
        
// new a message, of type MESSAGE_OPEN.
        Message msg = new CommonMessage(
                entry1.getId(),
                entry2.getId(),
                MessageTypes.MESSAGE_OPEN,
                
"busying now");
        
        
// deliver it to entry2, which is from entry1
        entry1.post(msg);
        
        
// create a message, of type MESSAGE_CLICKED, the entry2
        
// does not handle this type, it'll not be deliver to entry2
        Message msgCannotBeReceived = new CommonMessage(
                entry1.getId(),
                entry2.getId(),
                MessageTypes.MESSAGE_CLICKED,
                
"cliked evnet");
        entry1.post(msgCannotBeReceived);
        
        
try {
            Thread.sleep(
2000);
        } 
catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        
// re use the message object to send another message entry
        msg.setSource(entry2.getId());
        msg.setTarget(entry1.getId());
        msg.setType(MessageTypes.MESSAGE_READY);
        msg.setBody(
"okay now");
        entry2.post(msg);
        
        
// unregister self when all works are done or 
        
// don't want to listen any more
        entry1.unregister();
        entry2.unregister();
    }
}
API的设计,最好可以做到简单,易用。BBMS也尽力要做到这一点,每一个notifiable(可别通知的)的对象,可以将自己注册到BUS上,当消息抵达时,BUS管理器会调用这个对象上的update方法,进行通知。
This is client2, get message from : client1, it said that : busying now
This is client1, get message from : client2, it said that : okay now

这个是MS运行的一个简单流程图。

BUS的实现

BUS接口的定义,可以向BUS上注册一个notifiableEntry(可被通知的对象),或者卸载这个对象,同时,可以向BUS中post一条消息。

package bbms.framework;

/**
 * 
@author juntao.qiu
 
*/
public interface Bus extends java.rmi.Remote{
    
/**
     * mount an notifiable entry on bus
     * 
@param entry
     
*/
    
public void mount(NotifiableEntry entry) throws java.rmi.RemoteException;
    
    
/**
     * unmount the notifiable entry on bus
     * 
@param entry
     
*/
    
public void unmount(NotifiableEntry entry) throws java.rmi.RemoteException;
    
    
/**
     * post a new message to Message Bus
     * 
@param message
     
*/
    
public void post(Message message) throws java.rmi.RemoteException;
}
BUS的实现比较有意思,其中维护两个链表,一个是监听器链表,一个是消息链表,挂载在总线上的实体向BUS发送一条消息,这个过程会立即返回。因为发送消息的过程可能由于网络原因或其他原因而延迟,而消息的发送者没有必要等待消息的传递,所以BUS中有一个主动线程,这个线程在BUS中放入新的消息时被唤醒,并对监听器链表进行遍历,将消息分发出去。由于BUS是一个服务级的程序,所以这个主动线程被设计成为一个daemon线程,除非显式的退出或者出错,否则BUS将会一直运行。
    /**
     * 
     * 
@author juntao.qiu
     * worker thread, dispatch message to appropriate listener
     *
     
*/
    
private class Daemon implements Runnable{
        
private boolean loop = true;
        
public void run(){
            
while(loop){
                
if(messages.size() == 0){
                    
synchronized(messages){
                        
try {messages.wait();} 
                        
catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
                processIncomingMessage();
            }
        }
    }
BUS中的内部工作者线程。它被作为一个Daemon线程:
    private MessageBus() throws RemoteException{
        listeners 
= new LinkedList<NotifiableEntry>();
        messages 
= new LinkedList<Message>();
        Daemon daemon 
= new Daemon();
        daemonThread 
= new Thread(daemon);
        daemonThread.setPriority(Thread.NORM_PRIORITY 
+ 3);
        daemonThread.setDaemon(
true);
        daemonThread.start();
        
        
while(!daemonThread.isAlive());
    }

消息的定义

 

public interface Message{
    
public int getType();
    
public void setType(int type);
    
    
public String getTarget();
    
public void setTarget(String target);
    
    
public String getSource();
    
public void setSource(String source);
    
    
public Object getBody();
    
public void setBody(Object body);
}
为了更通用起见,消息体部分可以包含任何对象。消息类型参考了windows的消息机制,可以将消息进行复合:
    /*
     * 0x8000 = 1000 0000 0000 0000
     * 0x4000 = 0100 0000 0000 0000
     * 0x2000 = 0010 0000 0000 0000
     * 0x1000 = 0001 0000 0000 0000
     * 
     * it's very useful when you want to combine some messages
     * together, and the user can simply determine what exactly
     * what you want. Refer the implementation of MessageBus.java
     * for more details.
     
*/
    
public static final int MESSAGE_TIMEOUT = 0x8000;
    
public static final int MESSAGE_CLICKED = 0x4000;
    
public static final int MESSAGE_CLOSE = 0x2000;
    
public static final int MESSAGE_OPEN = 0x1000;
    
    
public static final int MESSAGE_READY = 0x0800;
    
public static final int MESSAGE_BUSY = 0x0400;
    
public static final int MESSAGE_WAIT = 0x0200;
    
public static final int MESSAGE_OKAY = 0x0100;

总结

BBMS如果进行适当的扩展,可以完全实现JMS规范中涉及到的所有主题,如订阅模式(BBMS现在的实现中只有PTP模式,及点对点的模式,发送消息和接受消息的实体都必须同时在线)。BBMS主要面向的是轻量级的消息传递,比如GUI,分布式的GUI等。如果有兴趣,可以到BBMS的页面上看一看:http://code.google.com/p/bbms/

 

分享到:
评论

相关推荐

    BBMS功能介绍、业务流程.pptx

    综上所述,BBMS系统是针对中小企业市场推出的一套全面的解决方案,它结合了硬件终端和业务服务,通过高度集成的设备和优化的服务流程,为企业提供便捷、安全、高效的网络和通信服务。同时,系统的可扩展性和定制化...

    C语言数据结构课程设计基于B树为索引的图书管理系统源码.zip

    在这个"C语言数据结构课程设计基于B树为索引的图书管理系统源码"项目中,我们主要探讨了如何利用C语言和B树数据结构来构建一个高效、可靠的图书管理系统。这个系统包括了图书借阅管理子系统API接口文档、项目说明、...

    bbms-ui:基于骨干木偶SASS Browserify的UI组件库

    **bbms-ui:基于骨干木偶SASS Browserify的UI组件库** `bbms-ui` 是一个专为前端开发者设计的UI组件库,它利用了先进的技术和工具链,旨在简化和加速网页应用的开发过程。这个组件库的核心是基于两个强大的技术——`...

    bbms:图书借阅管理系统

    本文将深入探讨一个名为"bbms"的图书借阅管理系统,该系统基于Java语言开发。通过对系统的剖析,我们将了解其核心功能、技术选型以及实现细节。 首先,让我们从系统的基本功能出发。图书借阅管理系统的核心任务是...

    bbms-boilerplate:骨干,木偶,SASS,基于Browserify的样板项目

    【bbms-boilerplate】是一个基于JavaScript的项目模板,它整合了多个强大的前端技术,旨在为开发者提供一个高效、易用的开发起点。这个项目主要采用了Backbone.js(骨干)、Underscore.js(木偶)以及SASS...

    Blood bank management system_(BBMS)_V1.0-开源

    血库管理系统是在Visual Basic 6.0(VB6)中作为前端开发的,而后端数据库是在MS-SQL 2005中开发的,该数据库提供了用于维护血库记录的员工登录信息。 前端– VB6(框架2.0)。 后端– MS-SQL 2005。

    图书管理系统

    图书管理系统是一种基于软件技术实现对图书信息进行高效管理的应用程序。在本项目中,系统主要由Java编程语言构建,利用数据库存储和检索图书数据。Java因其跨平台性和强大的面向对象特性,成为开发此类系统的常用...

    Blood-Bank-Management-System:BBMS(血库管理系统)是献血和血液需求问题的解决方案。 它提供了一个用户友好的界面

    血库管理系统血库管理系统是所有献血问题的解决方案,该系统的访问权限仅授予管理员和用户,它为用户提供了非常友好的用户界面。... 用户的功能是注册,查看他的捐赠详细信息(即他先前何时何地献血)以及查看他的请求...

    Blood Bank Management System in Python using Django

    《Python与Django构建...总之,使用Python和Django构建血液银行管理系统,可以高效地实现血液资源的信息化管理,提升医疗服务水平。通过深入理解和实践Django框架,开发者可以快速搭建出功能强大、安全可靠的Web应用。

    领航者Navigator客户使用手册

    总的来说,《领航者Navigator客户使用手册》是一份全面的指导资料,涵盖了从产品安装到网络配置的所有关键步骤,旨在帮助用户顺利地利用中国电信的领航者产品构建和管理他们的企业网络,实现高效便捷的信息化服务。

    商务领航终端配置方法

    在IT行业中,商务领航是一种综合的业务管理平台,它涉及到网络设备的配置,以便提供稳定、安全的服务。本文将详细解析商务领航终端的配置方法,包括华三、贝尔和思科设备的WAN、TR069、SNMP以及Syslog配置。 **华三...

    BioSCOOP

    它不应与任何特定的编程语言或数据存储紧密结合。 将BioSCOOP功能集成到现有BBMS中应该很容易。 BioSCOOP分为三个部分:数据格式定义,数据操作定义,数据查询格式。 数据格式定义 数据操作定义 词汇表 BBMS-...

    磁力泵维护保养程序.pdf

    磁力泵作为一种特殊的泵类设备,其工作原理依赖于磁场力传递扭矩,从而实现无接触的动力传输,确保液体的无泄漏输送。为了确保磁力泵的稳定运行和延长其使用寿命,进行规范的维护保养至关重要。以下是一些关键的磁力...

    Linux语音通信.zip

    本项目“Linux语音通信.zip”旨在实现基于Linux的语音通信功能,它利用了ALSA(Advanced Linux Sound Architecture)框架来操控音频设备,通过C语言编写,使用UDP(User Datagram Protocol)进行数据传输,实现本地...

    bentley 软件培训内部教程

    一旦设置了工作单位,记得保存设置或通过优选项自动保存,确保所有操作基于统一的单位标准。 ##### 3. 影响定位的因素 - **精确绘图技巧**:掌握使用快捷键、锁定功能等技巧是实现精确绘图的关键。ACS(Absolute ...

Global site tag (gtag.js) - Google Analytics