使用dubbo分布式服务框架发布服务及消费服务
什么是DUBBO
DUBBO是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案。
准备工作
安装zookeeper
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务。
具体安装步骤:略,请参考网上资源,很简单。
安装完后,配置一下zoo.cfg配置文件,里面有个端口的配置,我配置的是2181端口,客户端将使用该端口连接该服务。
我的zookeeper配置的服务器ip为10.0.10.51。
安装dubbo-admin
dubbo-admin是dubbo管理控制台。
具体安装步骤:略,请参考网上资源,其实就是一个war包,部署到tomcat即可。
部署完后,修改下dubbo.properties配置文件内容,将dubbo.registry.address的注册地址配置为zookeeper服务的地址,同时可以配置控制台的访问密码,如下是我的配置。
dubbo.registry.address=zookeeper://10.0.10.51:2181?backup=127.0.0.1:2182,127.0.0.1:2183 dubbo.admin.root.password=root dubbo.admin.guest.password=guest
访问http://10.0.10.51/dubbo-admin-2.5.3/,效果如下:
工程结构
我们将使用maven管理构建工程,工程结构如下:
首先,新建一个maven工程,包括四个模块:
<modules> <module>dubbo-demo-common</module> <module>dubbo-demo-api</module> <module>dubbo-demo-service</module> <module>dubbo-demo-web</module> </modules>
其中dubbo-demo-service即为我们的服务模块;其它的common模块主要放一些model、log、基类等;api模块放service的接口;service的实现放在service模块。web模块为我们的服务消费模块,是一个spring mvc工程,调用我们发布的服务;
服务提供
在dubbo-demo-service模块里,我们将使用spring+mybatis框架;
关于spring、mybatis的相关配置就不说了。
这里主要关注service服务,跟平常一样写一个service,在service里使用spring的注解@Autowired注入dao bean,然后使用dubbo的注解@Service将该service标记为dubbo服务,如下是一个UserServiceImpl例子:
package org.dubbo.demo.service.user.impl; import java.util.List; import java.util.Map; import org.dubbo.demo.api.service.IUserService; import org.dubbo.demo.common.model.User; import org.dubbo.demo.dao.IUserDao; import org.springframework.beans.factory.annotation.Autowired; import com.alibaba.dubbo.config.annotation.Service; @Service(interfaceClass = IUserService.class) public class UserServiceImpl implements IUserService { @Autowired private IUserDao userDao; @Override public List<User> queryAll(Map<String, Object> param) throws Exception { return userDao.queryAll(param); } @Override public void saveUser(Map<String, Object> param) throws Exception { userDao.saveUser(param); } @Override public void deleteUser(Map<String, Object> param) throws Exception { userDao.deleteUser(param); } }
这样我们的service服务就写好了,是不是发现很简单,接下来配置一下dubbo即可,如下:
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo https://git.oschina.net/pi.chen/wendang/raw/master/dubbo.xsd"> <!-- 应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 --> <dubbo:application name="dubbo-demo-service" /> <!-- 使用zookeeper广播注册中心暴露发现服务地址 --> <dubbo:registry protocol="zookeeper" address="10.0.10.51:2181" /> <!-- 用dubbo协议在20880端口暴露服务 --> <dubbo:protocol name="dubbo" port="20880" /> <!-- 扫描包 --> <dubbo:annotation package="org.dubbo.demo.service" /> </beans>
最后,写一个启动类,启动spring容器即可,如下示例:
package org.dubbo.demo; import org.dubbo.demo.common.log.Logger; import org.springframework.context.support.ClassPathXmlApplicationContext; public class StartDubboService { private static Logger logger = Logger.getLogger(StartDubboService.class); public static void main(String[] args) { try { @SuppressWarnings("resource") ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring.xml"); context.start(); logger.info("context start success."); } catch (Exception e) { logger.error("context start error.", e); } synchronized (StartDubboService.class) { while (true) { try { StartDubboService.class.wait(); } catch (InterruptedException e) { logger.error("synchronized error.", e); } } } } }
将该main方法绑定到maven的test阶段,
然后我们执行clean test -f service-pom.xml命令即可启动服务(这里指定了service-pom.xml,表示只构建该文件里定义的模块);
发布完服务后,可以在dubbo控制台中看到我们的服务提供者,如下图:
服务消费
提供者发布完服务后,消费者就可以开始调用服务了,消费者这边将用一个Java web工程模拟,使用spring-mvc框架,也就是之前提到的dubbo-demo-web模块,这个模块很简单,就配置一下spring-mvc和dubbo,然后controller中使用的service用“com.alibaba.dubbo.config.annotation.Reference”注解注入即可,如下是一个UserController:
package org.dubbo.demo.controller.user; import java.util.HashMap; import java.util.List; import java.util.Map; import org.dubbo.demo.api.service.IUserService; import org.dubbo.demo.common.base.BaseController; import org.dubbo.demo.common.model.User; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.alibaba.dubbo.config.annotation.Reference; import com.google.gson.Gson; @Controller @RequestMapping(value = "/user") public class UserController extends BaseController { @Reference private IUserService userService; @RequestMapping(value = "/getUserList", produces = "application/json; charset=utf-8") @ResponseBody public String getUserList(int pageNo, int pageSize) { Gson gson = new Gson(); Map<String, Object> map = new HashMap<String, Object>(); try { Map<String, Object> param = new HashMap<String, Object>(); param.put("pageNo", pageNo); param.put("pageSize", pageSize); List<User> userList = userService.queryAll(param); map.put("userList", userList); return gson.toJson(map); } catch (Exception e) { logger.error(e.toString(), e); } return gson.toJson("faild"); } @RequestMapping(value = "/deleteUser", produces = "application/json; charset=utf-8") @ResponseBody public String deleteUser(int userId) { Gson gson = new Gson(); try { Map<String, Object> param = new HashMap<String, Object>(); param.put("userId", userId); userService.deleteUser(param); return gson.toJson("success"); } catch (Exception e) { logger.error(e.toString(), e); } return gson.toJson("faild"); } @RequestMapping(value = "/saveUserTest", produces = "application/json; charset=utf-8") @ResponseBody public String saveUserTest(String userName, String address) { Gson gson = new Gson(); try { Map<String, Object> param = new HashMap<String, Object>(); param.put("name", userName); param.put("address", address); userService.saveUser(param); } catch (Exception e) { logger.error(e.toString(), e); return gson.toJson("fail"); } return gson.toJson("success"); } }
工程配置完后,启动我们的web工程,输入”clean tomcat:run -f web-pom.xml“命令,
然后,开始尝试调用controller,浏览器输入http://localhost:8080/dubbo-demo-web/user/getUserList.do?pageNo=0&pageSize=5
成功调用服务,并得到正确结果:
同样,可以在dubbo的管理页面,看到消费者应用:
工程源码
https://github.com/peterchenhdu/Demos/tree/master/dubbo-demo