一、Dubbox 框架
Dubbox 是一个分布式服务框架,其前身是阿里巴巴开源项目 Dubbo ,被国内电商及互联网项目中使用,后期阿里巴巴停止了该项目的维护,当当网便在 Dubbo 基础上进行优化,并继续维护,为了与原有的 Dubbo 区分,故将其命名为 Dubbox。
Dubbox 致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案。简单的说,dubbox 就是个服务框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时候,才有 dubbox 这样的分布式服务框架的需求,并且本质上是个服务调用的东东,说白了就是个远程服务调用的分布式框架。
节点角色说明:
Provider: 暴露服务的服务提供方。
Consumer: 调用远程服务的服务消费方。
Registry: 服务注册与发现的注册中心。
Monitor: 统计服务的调用次调和调用时间的监控中心。
Container: 服务运行容器。
调用关系说明:
0. 服务容器负责启动,加载,运行服务提供者。
1. 服务提供者在启动时,向注册中心注册自己提供的服务。
2. 服务消费者在启动时,向注册中心订阅自己所需的服务。
3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
二、注册中心 Zookeeper的安装与启动
官方推荐使用 zookeeper 注册中心。注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小。
Zookeeper 是 Apacahe Hadoop 的子项目,是一个树型的目录服务,支持变更推送,适合作为 Dubbox 服务的注册中心,工业强度较高,可用于生产环境。
windows安装zookeeper
第一步:下载安装包
官网地址:https://zookeeper.apache.org/releases.html
下载的文件如下:
第二步:开始安装
解压后:
1)、将conf目录下的zoo_sample.cfg文件,复制一份,重命名为zoo.cfg
2)、在安装目录下面新建一个空的data文件夹和log文件夹
3)、修改zoo.cfg配置文件,将dataDir=/tmp/zookeeper修改成zookeeper安装目录所在的data文件夹,再添加一条添加数据日志的配置。
tickTime=2000 initLimit=10 syncLimit=5 dataDir=F:/work/apache-zookeeper-3.7.0-bin/data dataLogDir=F:/work/apache-zookeeper-3.7.0-bin/log clientPort=2181
注意:dataDir和dataLogDir这两个路径中是/而不是\,因为windows的文件分隔符是/,而不是\.
tickTime:这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
initLimit:这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 10 个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 5*2000=10 秒
syncLimit:这个配置项标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 2*2000=4 秒
dataDir:顾名思义就是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。
clientPort:这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
第三步:启动程序
三、服务提供者
<!--dubbo--> <dependency> <groupId>com.alibaba.boot</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>0.2.0</version> </dependency> <!--zookeeper--> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.6</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> <exclusion> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </exclusion> </exclusions> </dependency>
2、dubbo的配置
#dubbo dubbo.application.name=pts-server #应用名 dubbo.protocol.name=dubbo #协议名 dubbo.protocol.port=20880 #dubbo服务暴露的端口 dubbo.provider.timeout=20000 dubbo.registry.address=zookeeper://127.0.0.1:2181 #zookeeper地址
注意:zookeeper的ip地址12.0.0.1,如果该ip的地址改为其他电脑的ip地址,那么你访问的服务就不是本地的服务了,而是其他电脑上的服务。
3、服务提供方接口和实现类
创建service接口
创建service接口实现类UserServiceImpl2
import com.alibaba.dubbo.config.annotation.Service; import com.ljxx.service.IUserService; @Service public class UserServiceImpl2 implements IUserService { @Override public String getName() { return "itcast"; } }
注意:Service 注解与原来不同,需要引入 com.alibaba 包下的。
四、服务消费者
<!--dubbo--> <dependency> <groupId>com.alibaba.boot</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>0.2.0</version> </dependency> <!--zookeeper--> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.6</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> <exclusion> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </exclusion> </exclusions> </dependency>
2、dubbo配置
#dubbo dubbo.application.name=pts-interface dubbo.registry.address=zookeeper://127.0.0.1:2181
3、将服务提供方的接口拷贝到服务消费方
public interface IUserService { public String getName(); }
4、编写controller
import com.alibaba.dubbo.config.annotation.Reference; @Controller @RequestMapping("/user") public class UserController { @Reference private IUserService userService; @RequestMapping("/showName") @ResponseBody public JSONObject showName(){ JSONObject jsonObject = new JSONObject(); String name = userService.getName(); jsonObject.put("msg",name); return jsonObject; } }
五、启动类加@EnableDubbo注解
服务提供方的启动类
@SpringBootApplication @MapperScan("com.ljxx.dao") @EnableAsync @EnableDubbo public class PtsServerApplication extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(PtsServerApplication.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(PtsServerApplication.class); } }
服务器消费方的启动类
@SpringBootApplication @EnableDubbo public class PtsInterfaceApplication extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(PtsInterfaceApplication.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(PtsInterfaceApplication.class); } }
@EnableDubbo:开启基于注解的dubbo功能(主要是包扫描@DubboComponentScan)
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented @EnableDubboConfig @DubboComponentScan public @interface EnableDubbo { @AliasFor( annotation = DubboComponentScan.class, attribute = "basePackages" ) String[] scanBasePackages() default {}; @AliasFor( annotation = DubboComponentScan.class, attribute = "basePackageClasses" ) Class<?>[] scanBasePackageClasses() default {}; @AliasFor( annotation = EnableDubboConfig.class, attribute = "multiple" ) boolean multipleConfig() default false; }
也可以在配置文件中使用dubbo.scan.base-package来替代 @EnableDubbo
六、管理中心dubbo-admin部署
我们在开发时,需要知道注册中心都注册了哪些服务,以便我们开发和测试。我们可以通过部署一个管理中心来实现。其实管理中心就是一个 web 应用,部署到 tomcat 即可。
1、下载安装包
官网下载地址:https://github.com/apache/dubbo/releases?after=dubbo-2.6.3
注意:下载2.6.0版本的才有dubbo-admin文件夹。
下载后的目录结构如下:
2、通过命令行的方式使用maven构建jar包
“Ctrl+R”输入“cmd”。进入dubbo-admin安装目录,然后输入下面代码
mvn clean package
打包后如下所示:
3、将jar放到tomcat中并改名字为dubbo-admin
4、浏览器中输入http://localhost:8088/dubbo-admin/打开界面。
登录账户和密码均为root。
service为服务名,application为应用名,address为机器IP
点击application,再点击箭头进入下一个页面
七、启动服务提供者和消费者
启动服务提供者和服务消费者后:
点击governence,点击applications,点击application,最后点击箭头,就可以看到服务的提供者和服务的消费者
查看所有的服务提供者
点击governance,再点击services,就可以看到所有服务,其中status为OK的服务表示已经被消费者调用,no.consumer表示没有消费者。
八、测试服务调用
使用postman访问服务消费者,看能不能获取服务提供者返回的数据。
注意:
1、dubbo服务消费方不能传递Date或DateTime类型的数据给服务提供方,可以通过String.valueOf转成字符串传递。
2、dubbo服务提供方抛出的自定义异常会变成RuntimeExceptionm,而且关于自定义异常的细节已经完全丢失,只会剩下一个类名的描述。
先了解Dubbo在遇到异常时的处理方法:
1)、非RuntimeException不处理,直接返回
2)、抛出的是方法上注明的异常,直接返回
3)、如果异常类和接口类在同一jar包,直接返回
4)、java或者javax目录下的异常类,直接返回
5)、Dubbo自带的RpcException,直接返回
6)、其他的异常,会被封装为RuntimeException返回
我的解决办法是在服务提供方抛出自定义的异常,在服务器消费方抛出Dubbo自带的RpcException。
3、服务提供方和服务消费方service接口的包结构要完全一样,否则,服务消费方找不到服务提供方的服务。controller的包接口可以不一样。