基于JMS消息中间件的分布式系统初探究(一) - 通过JMS实现Web服务器与服务框架的通讯

50 篇文章 0 订阅
22 篇文章 1 订阅

在一个大型网站中,如果要把整个业务拆分成N个子业务,每个业务单独部署到一台服务器上,那么需要解决的问题有:

  1. 自身的部署。是部署到JavaEE容器中随容器启动,还是做为一个standalone程序单独启动?
  2. 子系统如何暴露服务接口(如何与其它系统进行通讯)。服务请求者直接通过Socket直连,还是通过Web Service, RMI等技术?

这里我们尝试通过standalone方式部署,通过JMS中间件实现通讯。如图所示:
这里写图片描述

在客户端(运行Web服务)和服务端,我们使用Spring, Spring JMS框架简化消息收发过程,JMS Provider使用ActiveMQ。

在服务端,需要手动创建Spring的ApplicationContext:

@Component
public class Bootstrap {
    private static ApplicationContext ctx;

    public static void main(String[] args) {
        initSpring("spring-config.xml");
    }

    public static void initSpring(String configPath) {
        ctx = new ClassPathXmlApplicationContext(configPath);
    }

}

然后编写一个组件作为JMS消息处理器:

@Component
public class SayHelloHandler {
    public String onSaveMember(String username) {
        return "OK";
    }
}

我们希望Spring能在从taolijie.member.request.queue消息队列收到一条消息时调用上述方法,则需在spring-config.xml中做如下配置:

<jms:listener-container connection-factory="connectionFactory">
        <jms:listener destination="taolijie.member.request.queue"
                      ref="sayHelloHandler" method="onSaveMember" />
    </jms:listener-container>

同时,我们还要配置ConnectionFactoryJmsTemplate:

<!-- 配置ActiveMQ -->
    <amq:connectionFactory id="connectionFactory" brokerURL="tcp://localhost:61616" />
    <amq:queue id="member-request-queue" physicalName="taolijie.member.request.queue" />

    <bean id="jmsTemplate"
          class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="connectionFactory" />
    </bean>

到这里我们再一次看到了Spring低侵入式框架的优点,即上面的消息处理组件没有任何JMS的痕迹,完全是一个普通的POJO。

做好上面的工作后,当Spring收到ActiveMQ来自taolijie.member.request.queue队列的一条消息时就会调用onSaveMember方法,将消息中的payload转换成String类型传入到方法中。如果该方法有返回值,Spring JMS会自动将返回值封装成Message对象并设置JMSReplayTo消息头,ActiveMQ则会按照该消息头将返回的消息投递给发送端。

在客户端的配置与上面相同,只是需要使用Spring JMS提供的JmsTemplate编写发送一个发送消息组件:

@Component
public class DefaultHelloService implements HelloService {
    @Autowired
    private JmsTemplate jmsTemplate;

    @Override
    public void sayHello(String name) {
        System.out.println("sending persistence request");
        Message msg = jmsTemplate.sendAndReceive("taolijie.member.request.queue",
                (Session session) -> {
                    return session.createObjectMessage(new String("hello"));
                });

        TextMessage txt = (TextMessage) msg;
        try {
            System.out.println("done. " + txt.getText());
        } catch (JMSException e) {
            // ... ...
        }

    }
}

当我们调用JmsTemplatesendAndReceive()方法时,Spring会帮我们创建一个临时的队列用于接收返回消息,并时同该方法阻塞,等待返回消息。如果不想发送同步消息,可以改为调用send(),该方法会立即返回。

以上只是一个模型,我们可以在服务端消息处理方法(如onSaveMember())中添加我们需要的业务逻辑方法,处理完成后返回信息给客户端。所有服务端应用都可以单独部署在一台服务器中,这样就简单实现了一个分布式系统。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值