dubbo+zookeper实现分布式服务部署实例

环境部署

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值