原文及更多文章請見我的博客: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()); } }