使用 Apollo 在 WebSockets 上轻松实现 STOMP 消息传输 已翻译 100%

oschina 投递于 2013/08/06 06:22 (共 4 段, 翻译完成于 08-06)
阅读 7426
收藏 8
1
加载中

在我的上一篇文章中,我已经介绍了两个有趣的用例,通过 Websockects 实现 STOMP 消息发送,使用到了两个著名的中间件 HornetQ 和 ActiveMQ。但是当时我没有介绍 Apollo,因为个人认为它的 API 比较笨重,对 Java 开发者而言它显得表达能力不足。不过,在 Apollo 上花费的时间越多,我越确信它是有着相当大的潜力的。所以本文专门介绍 Apollo

我们尝试解决的问题还是那样:简单的发布/订阅解决方案,来使 JavaScript 编写的 web客户端能够发送消息和监听某个特定主题。任何时候客户端收到任何消息,都会展示一个弹出窗口(请注意我们需要使用支持 Websockets 的现代浏览器,比如 Google Chrome 或者 Mozilla Firefox).

lwei
翻译于 2013/08/06 15:20
1

让我们从 index.html 开始下手 (里面导入了令人生畏的 stomp.js JavaScript 库):

<script src="stomp.js"></script>

<script type="text/javascript">
    var client = Stomp.client( "ws://localhost:61614/stomp", "v11.stomp" );

    client.connect( "", "",
        function() {
            client.subscribe("/topic/test",
                function( message ) {
                    alert( message );
                }, 
                { priority: 9 } 
            );
   
            client.send("/topic/test", { priority: 9 }, "Pub/Sub over STOMP!");
        }
    ); 
</script>

客户端部分没有太多不同,除了主题名称现在变成了 /topic/test。服务器端则变化很大。Apollo 是用 Scala 写的,并且采用了异步,非阻塞式编程模式。我认为,它是个好东西。虽然它带来了一种新的编程范式,但是这并不是一件坏事。下面的 AppConfig 类中配置了内置的 Apollo 中间件:

package com.example.messaging;

import java.io.File;

import org.apache.activemq.apollo.broker.Broker;
import org.apache.activemq.apollo.broker.jmx.dto.JmxDTO;
import org.apache.activemq.apollo.dto.AcceptingConnectorDTO;
import org.apache.activemq.apollo.dto.BrokerDTO;
import org.apache.activemq.apollo.dto.TopicDTO;
import org.apache.activemq.apollo.dto.VirtualHostDTO;
import org.apache.activemq.apollo.dto.WebAdminDTO;
import org.apache.activemq.apollo.stomp.dto.StompDTO;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
    @Bean
    public Broker broker() throws Exception {
        final Broker broker = new Broker();
    
        // Configure STOMP over WebSockects connector
        final AcceptingConnectorDTO ws = new AcceptingConnectorDTO();
        ws.id = "ws";
        ws.bind = "ws://localhost:61614";  
        ws.protocols.add( new StompDTO() );

        // Create a topic with name 'test'
        final TopicDTO topic = new TopicDTO();
        topic.id = "test";
  
        // Create virtual host (based on localhost)
        final VirtualHostDTO host = new VirtualHostDTO();
        host.id = "localhost";  
        host.topics.add( topic );
        host.host_names.add( "localhost" );
        host.host_names.add( "127.0.0.1" );
        host.auto_create_destinations = false;
  
        // Create a web admin UI (REST) accessible at: http://localhost:61680/api/index.html#!/ 
        final WebAdminDTO webadmin = new WebAdminDTO();
        webadmin.bind = "http://localhost:61680";

        // Create JMX instrumentation 
        final JmxDTO jmxService = new JmxDTO();
        jmxService.enabled = true;
  
        // Finally, glue all together inside broker configuration
        final BrokerDTO config = new BrokerDTO();
        config.connectors.add( ws );
        config.virtual_hosts.add( host );
        config.web_admins.add( webadmin );
        config.services.add( jmxService );
  
        broker.setConfig( config );
        broker.setTmp( new File( System.getProperty( "java.io.tmpdir" ) ) );
  
        broker.start( new Runnable() {   
            @Override
            public void run() {  
                System.out.println("The broker has been started started.");
            }
        } );
  
        return broker;
    }
}
lwei
翻译于 2013/08/06 15:47
1
我想,我所说的 笨重且表达能力不足的意思应该已经很清楚了,不过至少它比较容易掌握。首先,我们创建 Websockects链接到 ws://localhost:61614,并且让它支持 STOMP协议。然后我们创建了一个名为 test 的简单的主题(我们在客户端通过 /topic/test 来引用它)。下一个重要的步骤是创建一个 虚拟主机,并且把主题(还有队列,如果有的话) 绑定到它上面。 主机名列表非常重要,因为目的地解析逻辑非常依赖它。在随后的步骤中,我们定义了 web 管理用户界面和 JMX 设施,它给我们提供了查看配置,统计信息和监控的能力。要检查这些效果,请在 Apollo 中间件启动之后在你的浏览器中 打开这个URL。最后,通过应用这些配置和开启中间件,我们就一切就绪了! 正如你所看到的,异步编程模式引入了回调函数和匿名函数 ( Java 8,你在哪儿啊?)。
lwei
翻译于 2013/08/06 17:45
2

现在,配置工作已经完成,是时候看看位于Starter 类中的启动逻辑了(再一次,回调函数和匿名函数被用来实现优雅的关闭逻辑):

package com.example.messaging;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.apache.activemq.apollo.broker.Broker;
import org.springframework.context.annotation.ConfigurableApplicationContext;

public class Starter  {
    public static void main( String[] args ) throws Exception {
        try( ConfigurableApplicationContext context = new AnnotationConfigApplicationContext( AppConfig.class ) ) {
            final Broker broker = context.getBean( Broker.class );  
            System.out.println( "Press any key to terminate ..." );
            System.in.read();    
         
            final CountDownLatch latch = new CountDownLatch( 1 );
            broker.stop( new Runnable() { 
                @Override
                public void run() {  
                    System.out.println("The broker has been stopped.");
                    latch.countDown();
                }
            } );
         
            // Gracefully stop the broker
            if( !latch.await( 1, TimeUnit.SECONDS ) ) {
                System.out.println("The broker hasn't been stopped, exiting anyway ...");
            }
        }
    }
}

之前的例子一样,在运行了 Starter 类之后,在浏览器中打开 index.html,我们应该可以看到类似下图的内容:

棒极了,它工作的很好! 我很确定的说这只是用 Scala 重写了代码而已,这个 Apollo API的使用示例看起来更紧凑更简洁。 如果你在寻找一款杰出的消息架构,我认为任何情形下 Apollo 消息中间件都绝对值得考虑。

所有源代码都可以从 GitHub 获取: Apollo 示例

lwei
翻译于 2013/08/06 16:14
1
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(0)

返回顶部
顶部
返回顶部
顶部