环境部署
Zookeeper安装
下载apach-zookeeper压缩包,解压到目标文件夹即可,复制conf中的zoo_sample.cfg为zoo.cfg,在解压的根目录下新建data文件夹和logs文件夹,修改其中配置:
dataDir=E:\Program\apache-zookeeper-3.5.5\data
dataLogDir=E:\Program\apache-zookeeper-3.5.5\logs
zookeepr默认端口为2181,安装完成后双击bin下的zkServer.cmd即可启动服务(若启动闪退,应该是版本的问题,可选择低版本的安装包)
dubbo-admin部署
下载可用的dubbo-admin.war包,或者下载git上的dubbo源码,maven编译打包后将target中的dubbo-admin文件夹复制到tomcat的webapps下,开启tomcat,浏览器输入http://localhost:8080/dubbo-admin/ 用户名密码:root/root登录即可看到zookeeper中管理的dubbo服务发布和消费的情况。
项目结构
首先,我们最基础的分布式架构项目应该由服务提供者、消费者、公用的服务api标准,这三部分组成,所以我们新建三个项目模块,dubbo-provider、dubbo-consumer、service-api;项目结构如下图:
服务接口模块
我们在service-api中定义好通用服务的接口和一些公共操作类(工具类,实体类,传输模型等),然后在pom中将该模块配置安装成本地jar包,供其它两个模块调用;需要注意的是dubbo的对象传输需要实现序列化接口。
服务提供方
provider需要的依赖
dubbo-provider中主要是对刚刚定义的服务接口的实现,提供者由于只需要Spring接管service和repository,不用关注controller层控制视图,所以不需要spring-mvc相关依赖,pom文件中除了spring等相关依赖还需要引入dubbo最新的依赖包、netty-all包、curator-framework包、zookeeper的依赖包和刚刚安装的service-api依赖:
<dependency>
<groupId>com.legolas</groupId>
<artifactId>service-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.6</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.32.Final</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.8</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
provider的业务实现和发布
添加好依赖以后,我们新建dao包完成数据库相关业务,然后新建api包,在api包里完成服务接口的业务实现:
api包里的实现类必须实现service-api中定义好的接口,这样在消费方才能通过service-api中的接口去发现并使用提供者发布的服务,这里因为我使用了多数据源切换服务(似乎自定义的@TargetDataSource与dubbo的注解存在扫描顺序的冲突),所以我新增了serviceImpl包,在serviceImpl包中完成了所有的业务实现,然后在api层直接调用业务实现类。最后在所有需要发布服务的api前添加dubbo的@Service注解,就可以成功发布dubbo服务。
provider的spring和dubbo配置
最后,在provider项目中由spring接管的配置文件application-context中我们先对spring的注解进行扫描,然后扫描dubbo的注解(消费方的扫描顺序相反)
<aop:aspectj-autoproxy/>
<!--spring注解扫描-->
<context:component-scan base-package="com.legolas.provider.config"/>
<context:component-scan base-package="com.legolas.provider.dao"/>
<context:component-scan base-package="com.legolas.provider.serviceImpl"/>
<import resource="spring-mybatis.xml"/>
<!--dubbo注解扫描-->
<dubbo:annotation package="com.legolas.provider.api"/>
<import resource="dubbo.xml"/>
provider的web.xml配置
在配置web.xml时我们将所有业务交给spring容器接管,不需要做spring-mvc的配置,这里我们可以使用com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet类替代spring的DispatcherServlet;(查阅资料了解如果项目使用外部服务器部署,必须将dubbo的BootstrapListener和DispatherServlet添加到web.xml,以完成dubbo的REST功能与外部servlet容器的集成)
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application-context.xml</param-value>
</context-param>
<!-- <listener>
<listener-class>com.alibaba.dubbo.remoting.http.servlet.BootstrapListener</listener-class>
</listener>-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
在dubbo-admin中可以查看发布的服务:
服务消费方
dubbo-consumer需要的相关依赖与provider相同。
consumer调用服务
consumer调用服务非常简单,在controller层使用dubbo的@Reference注解就可以实现对提供者服务的调用:
@Controller
@RequestMapping("/article")
public class ArticleController {
@Reference
ArticleService articleService;
@RequestMapping("/getAllArticle")
@ResponseBody
public List getAllArticle(){
return articleService.getAllArticle();
}
}
对服务进行分组
此外我们可以在服务提供方对发布的服务进行分组指定组名,消费方通过组名区分相同类型接口的服务。
provider:
@Service(group = "group1")
public class TestService1API implements TestService {
@Override
public String test(String name) {
return "(我是group1)test :"+name;
}
}
@Service(group = "group2")
public class TestService2API implements TestService {
@Override
public String test(String name) {
return "(我是group2)test :"+name;
}
}
consumer:
@RequestMapping("/test")
public class TestController {
@Reference(group = "group1")
private TestService testService1;
@Reference(group = "group2")
private TestService testService2;
...
}
consumer的spring和dubbo配置
在消费方,我们需要先完成对dubbo的扫描,然后再进行spring的扫描,否则@Reference注解注入的对象会报空指针异常,所以application-context.xml中需要如下配置:
<dubbo:annotation package="com.legolas.consumer.web.controller" />
<context:component-scan base-package="com.legolas.consumer.web"/>
<import resource="spring-mvc.xml" />
<import resource="dubbo.xml" />
dubbo.xml
<!-- 提供方应用信息,用于计算依赖关系,名称无所谓 -->
<dubbo:application name="dubbo_constumer" />
<!-- 使用zookeeper注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" check="false" file="dubbo-consumer-registry.properties"/>
consumer的web.xml配置
consumer的web.xml配置中spring-mvc也可以架空,控制层的配置可以在java代码中实现。需要注意的是如果要配置静态资源的视图解析,需要开启<mvc:default-servlet-handler/>
,相同效果的配置代码如下:
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
在dubbo-admin中可以查看服务的消费方:
排错问题记录
1.provider与consumer中的dubbo与spring的扫描顺序:provider中先spring后dubbo,consumer中相反。
2.Dubbo消费者在使用@Reference注解时报空指针异常的原因:
由于在web.xml中配置application-context.xml的初始化完controller类之后,同时将dubbo的reference的实例已经交给了controller,而后配置的spring-mvc.xml在进行servlet的初始化的时候再一次对controller进行了初始化,但是它与spring顶级容器不同的是,没有加载dubbo实现的DubboNamespaceHandler,就是说reference实例化的过程都没有进行,因此在mvc容器中的controller是没有注入reference标注的实例的,因此出现NULL的情况。 解决办法是避免在spring-mvc.xml中扫描dubbo的注解。
3.保证dubbo和spring的版本为比较新的版本,在实际使用中各个版本的dubbo所需要的依赖不尽相同(如dubbo2.3.8就不需要netty-all与curator-framework依赖包)对spring的版本也有不同要求,实际运行中出现ClassNotFound等错误时可根据实际情况添加或排除依赖、更换版本等操作进行调整。
4.这点在所有springmvc项目中都需要注意的是,项目需要在controller层实现视图自动匹配控制转向时,需要配置<mvc:default-servlet-handler/>
,该标签作用是 Spring MVC在上下文中定义一个org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler,对进入 DispatcherServlet 的 URL 进行筛查,静态资源由 Web 服务器默认的Servlet处理,非静态资源的请求,由spring的DispatcherServlet处理。
项目示例源码
https://gitee.com/legolaseee/DubboDemo
个站链接:http://www.legolas94.top