原文及更多文章请见我的博客:http://heartlifes.comjava
vert.xgit
dubbo是阿里巴巴内部的rpc远程调用框架,和spring无缝对接,自带loadbalance,是用来搭建soa服务架构的利器,惋惜据说在阿里内部斗争中,已经被hsf干掉了。可是,对于咱们这种小企业来讲,dubbo仍是搭建高可用服务的不二选择。dubbo官方地址:http://dubbo.iogithub
vert.x+dubbo能够搭建一个逼格很高的微服务架构,即vert.x用于发布服务,经过事件总线,调用后端的dubbo业务处理服务。从而完成rest服务与业务代码的完美解耦。web
本章基用到前序章节的全部知识,而且这里将不会介绍dubbo服务的开发,默认你会玩dubbo服务。spring
<dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>${dubbo.version}</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.3.6</version> <exclusions> <exclusion> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.1.41</version> </dependency> <dependency> <groupId>org.jboss.netty</groupId> <artifactId>netty</artifactId> <version>3.2.5.Final</version> </dependency>
所谓集成dubbo,从本质来说就是配置dubbo服务,而且以xml形式集成spring。
咱们假设后台有这么一个dubbo服务,如今要在vert.x中调用,那么咱们的作法和普通的dubbo consumer同样,申明一个spring配置文件,并引用该服务。配置文件以下:数据库
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd "> <!-- 使用Annotation自动注册Bean,解决事物失效问题:在主容器中不扫描@Controller注解,在SpringMvc中只扫描@Controller注解。 --> <context:component-scan base-package="com"/> <dubbo:application name="demo-consumer" /> <dubbo:registry address="multicast://224.5.6.7:1234" /> <dubbo:protocol name="dubbo" host="127.0.0.1" port="20802" serialization="hessian2" threadpool="cached" threads="1000" /> <!-- dubbo引用的服务 --> <dubbo:reference id="dubboService" interface="com.heartlifes.dubbo.DubboService" /> </beans>
package com.heartlifes.vertx.demo.dubbo; import io.vertx.core.AbstractVerticle; import io.vertx.core.Handler; import io.vertx.core.eventbus.Message; import org.springframework.context.ApplicationContext; public class SpringVerticle extends AbstractVerticle { private DubboService service; public static final String PRINT_MSG_SERVICE_ADDRESS = "print_msg_service_address"; public static final String GET_MSG_SERVICE_ADDRESS = "get_msg_service_address"; public SpringVerticle(ApplicationContext ctx) { // 从spring上下文获取service this.service = (DubboService) ctx.getBean("dubboService"); } @Override public void start() throws Exception { // 唤起事件总线,注册一个事件处理者,或者直译叫事件消费者 vertx.eventBus().<String> consumer(PRINT_MSG_SERVICE_ADDRESS) .handler(msg -> { // 获取事件内容后,调用service服务 // 这里是非阻塞式调用 service.printMsg("Asynchronous call dubbo service!!!"); msg.reply("success"); }); vertx.eventBus().<String> consumer(GET_MSG_SERVICE_ADDRESS, printMsg()); } // 模拟dubbo服务要从后台数据库获取数据,因此这里就是vert.x中的阻塞式调用 // vert.x中规定,全部调用不能够阻塞其eventloop,因此当有数据库调用、thread.sleep等可能会阻塞线程的服务调动时 // 须要使用vertx接口中的阻塞式调用接口 private Handler<Message<String>> printMsg() { return msg -> { System.out.println("bus msg body is:" + msg.body()); // 阻塞式接口调用 vertx.<String> executeBlocking(future -> { // 经过future等待调用返回结果 String dubboMsg = ""; try { dubboMsg = this.service.getMsg(); } catch (Exception e) { e.printStackTrace(); future.fail(e); } // 把结果放到result中 future.complete(dubboMsg); }, result -> { // 判断接口调用结果,成功的话讲结果放到事件总线的msg中传递给server端展现 if (result.succeeded()) { System.out.println("msg from dubbo service is: " + result.result()); msg.reply(result.result()); } if (result.failed()) { msg.fail(400, result.cause().getMessage()); } }); }; } }
package com.heartlifes.vertx.demo.dubbo; import io.vertx.core.AbstractVerticle; import io.vertx.ext.web.Router; import io.vertx.ext.web.handler.BodyHandler; /** * 基本代码注释,请参见vert.x笔记:3.使用vert.x发布restful接口 * * @author john * */ public class ServerVerticle extends AbstractVerticle { @Override public void start() throws Exception { Router router = Router.router(vertx); router.route().handler(BodyHandler.create()); router.route("/dubbo/get").handler( // 唤起vert.x的事件总线,并发送一个简单消息 ctx -> vertx.eventBus().<String> send( SpringVerticle.GET_MSG_SERVICE_ADDRESS,// 消息地址 "event bus calls dubbo service",// 消息内容 result -> {// 异步结果处理 if (result.succeeded()) { // 成功的话,返回处理结果给前台,这里的处理结果就是service返回的一段字符串 ctx.response() .putHeader("content-type", "application/json") .end(result.result().body()); } else { ctx.response().setStatusCode(400) .end(result.cause().toString()); } })); router.route("/dubbo/print").handler( // 唤起vert.x的事件总线,并发送一个简单消息 ctx -> vertx.eventBus().<String> send( SpringVerticle.PRINT_MSG_SERVICE_ADDRESS,// 消息地址 "event bus calls dubbo service",// 消息内容 result -> {// 异步结果处理 if (result.succeeded()) { // 成功的话,返回处理结果给前台 ctx.response() .putHeader("content-type", "application/json") .end("success"); } else { ctx.response().setStatusCode(400) .end(result.cause().toString()); } })); vertx.createHttpServer().requestHandler(router::accept).listen(8080); } }
package com.heartlifes.vertx.demo.dubbo; import io.vertx.core.Vertx; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringMain { public static void main(String[] args) { // 配置文件方式 ApplicationContext ctx = new ClassPathXmlApplicationContext( "dubbo-consumer.xml"); Vertx vertx = Vertx.vertx(); // 部署spring模块 vertx.deployVerticle(new SpringVerticle(ctx)); // 部署服务器模块 vertx.deployVerticle(new ServerVerticle()); } }