赞
踩
(新手笔记,存在错误还请指正)
Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。(rpc的两个核心模块即:通讯,序列化。)
设计架构:
一、打开zookeeper
二、安装dubbo-admin管理控制台
dubbo本身并不是一个服务软件。它其实就是一个jar包能够帮你的java程序连接到zookeeper,并利用zookeeper消费、提供服务。所以不用在Linux上启动什么dubbo服务。
但是为了让用户更好的管理监控众多的dubbo服务,官方提供了一个可视化的监控程序,不过这个监控即使不装也不影响使用。
下载地址:
dubbo-admin
进入目录,修改dubbo-admin配置:
修改 src\main\resources\application.properties 指定zookeeper地址
打包dubbo-admin,cmd中运行:
mvn clean package -Dmaven.test.skip=true
运行dubbo-admin
java -jar dubbo-admin-0.0.1-SNAPSHOT.jar
在浏览器中访问localhost:7001即可访问管理页面(用户名密码均为root)
三、创建工程
需求:
某个电商系统,订单服务需要调用用户服务获取某个用户的所有地址;我们现在需要创建两个服务模块。
订单服务web模块:创建订单等
用户服务web模块:查询用户地址等
实现:两个模块在不同的服务器并且A可以远程调用B的功能。
1、服务提供者
定义一个实体bean,和一个服务提供service
public class UserAddress implements Serializable { private Integer id; private String userAddress; private String userId; private String consignee; private String phoneNum; private String isDefault; public UserAddress() { super(); } public UserAddress(Integer id, String userAddress, String userId, String consignee, String phoneNum, String isDefault) { this.id = id; this.userAddress = userAddress; this.userId = userId; this.consignee = consignee; this.phoneNum = phoneNum; this.isDefault = isDefault; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUserAddress() { return userAddress; } public void setUserAddress(String userAddress) { this.userAddress = userAddress; } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getConsignee() { return consignee; } public void setConsignee(String consignee) { this.consignee = consignee; } public String getPhoneNum() { return phoneNum; } public void setPhoneNum(String phoneNum) { this.phoneNum = phoneNum; } public String getIsDefault() { return isDefault; } public void setIsDefault(String isDefault) { this.isDefault = isDefault; } @Override public String toString() { return "UserAddress{" + "id=" + id + ", userAddress='" + userAddress + '\'' + ", userId='" + userId + '\'' + ", consignee='" + consignee + '\'' + ", phoneNum='" + phoneNum + '\'' + ", isDefault='" + isDefault + '\'' + '}'; } }
public class UserServiceImpl implements UserService {
@Override
public List<UserAddress> getUserAddressList(String userId) {
System.out.println("UserServiceImpl.....old...");
// TODO Auto-generated method stub
UserAddress address1 = new UserAddress(1, "北京市昌平区宏福科技园综合楼3层", "1", "李老师", "010-56253825", "Y");
UserAddress address2 = new UserAddress(2, "深圳市宝安区西部硅谷大厦B座3层(深圳分校)", "1", "王老师", "010-56253825", "N");
return Arrays.asList(address1,address2);
}
}
2、服务消费者
加入同样的bean实体和一个订单service
public class OrderServiceImpl implements OrderService { UserService userService; @Override public List<UserAddress> initOrder(String userId) { // TODO Auto-generated method stub System.out.println("用户id:"+userId); //1、查询用户的收货地址 List<UserAddress> addressList = userService.getUserAddressList(userId); for (UserAddress userAddress : addressList) { System.out.println(userAddress.getUserAddress()); } return addressList; } }
但userservice和订单service在不同的工程中,这时就需要用到dubbo.
工程架构
1、分包
建议将服务接口,服务模型,服务异常等均放在 API 包中,因为服务模型及异常也是 API 的一部分,同时,这样做也符合分包原则:重用发布等价原则(REP),共同重用原则(CRP)。
如果需要,也可以考虑在 API 包中放置一份 spring 的引用配置,这样使用方便,只需在 spring 加载过程中引用此配置即可,配置建议放在模块的包目录下,以免冲突,如:com/alibaba/china/xxx/dubbo-reference.xml。
2、粒度
服务接口尽可能大粒度,每个服务方法应代表一个功能,而不是某功能的一个步骤,否则将面临分布式事务问题,Dubbo 暂未提供分布式事务支持。
服务接口建议以业务场景为单位划分,并对相近业务做抽象,防止接口数量爆炸。
不建议使用过于抽象的通用接口,如:Map query(Map),这样的接口没有明确语义,会给后期维护带来不便。
创建公共接口工程
创建公共接口工程,将上述bean和功能接口复制进去,将服务者和消费者的bean和service接口删掉:
在consumer和provider中引入公共接口依赖:
<dependency>
<groupId>org.example</groupId>
<artifactId>gmall-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
为了使订单service可以成功实现远程调用用户service,需要使用dubbo进行改造。
步骤:
1、将服务提供者注册到注册中心(暴露服务)
1)、导入dubbo依赖(2.6.2)\操作zookeeper的客户端(curator)
2)、配置服务提供者
2、让服务消费者去注册中心订阅服务提供者的服务地址
首先在服务和消费模块引入依赖:
<!--Dubbo的起步依赖,版本2.7之后统一为rg.apache.dubb -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<!--ZooKeeper客户端实现 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
服务端provider.xml配置
<?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 http://code.alibabatech.com/schema/dubbo/dubbo.xsd "> <!-- 配置提供者--> <!--当前应用/服务的名字(同样的服务名字相同,不要和别的服务同名) --> <dubbo:application name="user-service-provider"></dubbo:application> <!--指定注册中心的地址 --> <dubbo:registry address="zookeeper://127.0.0.1:2181" /> <!--使用dubbo协议,将服务暴露在20880端口 --> <dubbo:protocol name="dubbo" port="20880" /> <!-- 指定需要暴露的服务 ref:指向服务的真正实现对象--> <dubbo:service interface="com.atguigu.gmall.service.UserService" ref="userServiceImpl" /> <bean id="userServiceImpl" class="com.atguigu.gmail.service.impl.UserServiceImpl"></bean> </beans>
服务端consumer.xml配置
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.atguigu.gmall.service.impl"></context:component-scan> <!-- 应用名 --> <dubbo:application name="order-service-consumer"></dubbo:application> <!-- 指定注册中心地址 --> <dubbo:registry address="zookeeper://127.0.0.1:2181" ></dubbo:registry> <!-- 声明需要调用的远程服务的接口:生成远程服务代理,可以和本地bean一样使用demoService --> <dubbo:reference id="userService" interface="com.atguigu.gmall.service.UserService"></dubbo:reference> </beans>
在orderServiceImpl中给其加上@Service注解,将给userservice上加@Autowired注解注入容器。
启动服务
//服务端
public class MainApplication {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("classpath:provider.xml");
context.start();
System.in.read();
}
}
//消费端
public class MainApplication {
@SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("classpath:consumer.xml");
OrderService order = context.getBean(OrderService.class);
order.initOrder("1");
System.in.read();
}
}
两个应用启动成功后在dubbo admin管理页面就可以看到相应的信息。
访问initOrder请求,会调用UserService获取用户地址;
调用成功。说明我们order已经可以调用远程的UserService了;
前面安装过的dubbo-admin是图形化的服务管理页面;安装时需要指定注册中心地址,即可从注册中心中获取到所有的提供者/消费者进行配置管理。
dubbo-monitor-simple是一个简单的监控中心;
安装步骤:
安装
1、下载 dubbo-ops
ops
2、修改配置指定注册中心地址
进入 dubbo-monitor-simple\src\main\resources\conf
修改 dubbo.properties文件
3、打包dubbo-monitor-simple
mvn clean package -Dmaven.test.skip=true
4、解压 tar.gz 文件,并运行dubbo-monitor-simple-2.0.0中bin目录下的start.bat
如果缺少servlet-api,自行导入servlet-api再访问监控中心
访问8080端口:
在consumer.xml和provider.xml中配置监控中心
<!-- 所有服务配置连接监控中心,进行监控统计-->
<!-- 监控中心协议,如果为protocol="registry",表示从注册中心发现监控中心地址,否则直连监控中心 -->
<dubbo:monitor protocol="registry"></dubbo:monitor>
新建springboot的provider和consumer项目,将service实现复制进去,同样的将gmall-interface通用接口的依赖导入两个应用中。
引入dubbo和curator的依赖
在两个应用中引入依赖,注意springboot和dubbo的版本要适配。
<!-- 我的是springboot2.6.7--> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.8</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>4.3.0</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>4.3.0</version> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.9</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency>
properties文件配置:
提供者配置: dubbo.application.name=boot-user-service-provider dubbo.registry.protocol=zookeeper dubbo.registry.address=127.0.0.1:2181 dubbo.scan.base-package=com.atguigu.gmall #配置包扫描规则,开启了的话基于不用配置@EnableDubbo了 dubbo.protocol.name=dubbo dubbo.protocol.port=20880 dubbo.monitor.protocol=registry #application.name就是服务名,不能跟别的dubbo提供端重复 #registry.protocol 是指定注册中心协议 #registry.address 是注册中心的地址加端口号 #protocol.name 是分布式固定是dubbo,不要改。 #base-package 注解方式要扫描的包 消费者配置: server.port=8081 #和监控中心端口号重叠,改一下 dubbo.application.name=boot-order-service-consumer dubbo.registry.protocol=zookeeper dubbo.registry.address=127.0.0.1:2181 dubbo.scan.base-package=com.atguigu.gmall dubbo.protocol.name=dubbo dubbo.monitor.protocol=registry
在要暴露的提供者服务上加上dubbo的@service注解
import org.apache.dubbo.config.annotation.DubboService;
@DubboService //暴露服务
@Component
public class UserServiceImpl implements UserService {
@Override
public List<UserAddress> getUserAddressList(String userId) {
......
}
在消费者服务中引入远程调用service注解
@Service
public class OrderServiceImpl implements OrderService {
//@Autowired
@DubboReference
UserService userService;
......
}
在两个应用中要开启dubbo功能
@EnableDubbo //开启基于注解的dubbo功能
@SpringBootApplication
public class BootOrderServiceConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(BootOrderServiceConsumerApplication.class, args);
}
}
在消费者服务中增加controller层
@Controller
public class OrderController {
@Autowired
OrderService orderService;
@ResponseBody
@RequestMapping("/initOrder")
public List<UserAddress> initOrder(@RequestParam("uid")String userId) {
return orderService.initOrder(userId);
}
}
访问如下地址
//随便带上一个uid
http://localhost:8081/initOrder?uid=1
访问成功:
可以看我整理的另一篇文章:
dubbo配置
文章地址:
dubbo高可用
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。