北京尚学堂2020java_Dubbo
第一节 Dubbo简介
对RPC一个具体实现,高可用,基于Java的开源RPC框架。不仅仅具备RPC访问功能,还包含服务治理功能。
不用再像之前那样,还需要你去手写操作zookeeper的相关代码。
服务治理:哪个服务多,让他强一点,否则弱一点。
第二节 Dubbo架构讲解

Registry:注册中心
先写Provider,启动Container,注册到Registry,然后启动Consumer,订阅代理信息,创建代理对象,通过代理对象调用远程对象。monitor会做一些统计。
实线代表同步,虚线代表异步。
Dubbo完全基于Spring实现
Registry放置所有对外提供的信息,包括ip 端口 访问遵守的协议 对外提供的接口,接口中有哪些方法等等。
Consumer消费者,RPC调用者,SOA(面向服务编程)开发中也是一个项目,编写service和controller。调用远程服务实现XXXXServiceImpl中的方法
第三节 Dubbo支持的协议
1.Dubbo协议(官方推荐协议)
优点:采用NIO单一长连接,并使用线程池做并发处理请求,减少握手和加大并发效率,性能较好。长连接,会做池化处理
缺点:大文件上传时,可能出现问题(不使用Dubbo实现文件传输)
2.RMI协议
优点:JDK自带的能力
缺点:偶尔连接失败
3.Hessian协议
优点:可与原生Hessian互操作,基于HTTP协议
缺点:需要hession.jar支持 http短链接的开销大
第四节 Dubbo支持的注册中心
注册中心:保存发布的服务
- Zookeeper
有点:支持分布式,周边产品多
缺点:受限于zk软件的稳定性,zk专门分布式辅助软件 - Multicast
优点:去中心化,不需要单独安装软件
缺点:Provider、Consumer和Registry不能跨机房(路由)必须处于同一个内网中。这个不太行,有的时候可能要北京调广州的代码。 - redis
优点:支持集群,性能高 所有数据都在内存里
缺点:要求服务器时间同步,否则可能出现集群失败问题 - Simple
优点:标准RPC服务,没有兼容问题
缺点:不支持集群
第五节 第一个Dubbo的Provider
首先在项目pom中引入需要的包 19_dubbo/rpc_dubbo/pom.xml:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>2.2.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter -->
<!-- dubbo和SpringBoot整合使用的启动器-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes -->
<!-- dubbo使用zk作为注册时,必须依赖的资源-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.3.0</version>
</dependency>
</dependencies>
</dependencyManagement>
在接口中定义好接口19_dubbo/rpc_dubbo/dubbo_serviceapi/src/main/java/com/bjsxt/dubbo/service/UserService.java:
public interface UserService {
// 保存一个User对象
int saveUser(User user);
// 根据姓名找User对象
User getUserByName(String name);
}
接着在server中写好实现类19_dubbo/rpc_dubbo/dubbo_provider/src/main/java/com/bjsxt/dubbo/service/provider/UserServiceImpl.java:
这里的@Service注解是dubbo包中的,这是这个将该服务通过dubbo发布到了zookeeper上
import org.apache.dubbo.config.annotation.Service;
/**
* 开始使用dubbo注解,做服务发布注册
* Service - 可以实现Component注解的功能,创建当前类型的bean对象,让spring容器管理
* 并且,可以将当前类型实现的接口作为服务,注册到注册中心中。
*/
@Service
public class UserServiceImpl implements UserService {
@Override
public int saveUser(User user) {
// 模拟将user对象保存到数据库
System.out.println("保存用户对象[" + user + "]");
// 保存了一条数据
return 1;
}
@Override
public User getUserByName(String name) {
// 模拟从数据库中做条件查询
User user = new User();
user.setName(name);
user.setAge(24);
user.setHobbies(Arrays.asList("开发", "睡觉", "吃"));
return null;
}
}
然后在spring配置中配置好zookeeper的地址19_dubbo/rpc_dubbo/dubbo_provider/src/main/resources/application.yml:
dubbo:
application: #dubbo应用配置
name: dubbo-first-provider # 为当前的dubbo起一个名字
registry: #dubbo注册中心
address: zookeeper://192.168.2.128:2181 #注册中心的访问地址
即可向zookepper自动配置服务信息。
至于zk中记录的内容:
/dubbo # dubbo框架记录的节点
/com.bjsxt.service.UserService # 使用dubbo发布的服务的接口名称
/providers # 发布的服务是什么,服务提供者信息
# 具体的服务内容,下述内容是一个协议信息,只要又良好的数据转换,所有人都可以自我解读。
# 和自定义RPC框架记录rmi协议信息类似。用来描述一个服务的
# %3A -> : %2F -> / %3F -> ? %3D -> = %26 -> & %2C -> ,
/dubbo://
此外在主启动类上需要加上@EnableDubbo注解,这是启动dubbo服务的必由之路19_dubbo/rpc_dubbo/dubbo_provider/src/main/java/com/bjsxt/DubboProviderApp.java:
/**
* EnableDubbo:会扫描当前类型所在包及所有子孙包,识别Dubbo定义的
*/
@SpringBootApplication
@EnableDubbo
public class DubboProviderApp {
public static void main(String[] args) {
SpringApplication.run(DubboProviderApp.class, args);
}
}
第七节 完成Dubbo的Consumer
引入依赖,包括serviceapi、springboot和dubbo的:19_dubbo/rpc_dubbo/dubbo_consumer/pom.xml
<dependencies>
<dependency>
<groupId>com.bjsxt</groupId>
<artifactId>dubbo_serviceapi</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- springboot的核心启动器,可以通过这个资源库实现springboot环境的初始化-->
<dependency>
<groupId>org.springframework.boot</groupId>
<!-- 就是一套核心启动器,没有tomcat还要维护端口之类乱七八糟的-->
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
</dependencies>
在consumser中写控制器类19_dubbo/rpc_dubbo/dubbo_consumer/src/main/java/com/bjsxt/controller/UserController.java:
@Controller
public class UserController {
@Autowired
private UserService userService;
// 新增用户
@RequestMapping("/saveUser")
@ResponseBody
public Object saveUser(User user) {
// save方法返回map,内部存储code和msg,code=200 成功 其他为失败
Map<String,Object> result = userService.save(user);
return result;
}
// 根据姓名查询用户
@RequestMapping("/getUser")
@ResponseBody
public User getUserByName(String name) {
// 服务直接返回查询到的用户对象
return userService.getUserByName(name);
}
}
consumer也需要服务的接口,不过这里的接口不是公共的接口,而是SpringMVC中的接口19_dubbo/rpc_dubbo/dubbo_consumer/src/main/java/com/bjsxt/service/UserService.java:
public interface UserService {
// 保存用户数据
Map<String, Object> save(User user);
// 根据用户姓名查询用户对象
User getUserByName(String name);
}
然后该服务的实现需要用到远程提供的服务19_dubbo/rpc_dubbo/dubbo_consumer/src/main/java/com/bjsxt/service/impl/UserServiceImpl.java:
其中最重要的就是@Reference注解,它代表了项目和dubbo的链接,它表示需要通过dubbo在远程拿到代理对象才能使用。不得不说,太方便了!amazing!
/**
* 当前类型是consumer消费者的本地服务实现
* 使用spring提供的service注解,保证当前类型被spring容器管理即可
* 它不需要去注册服务
*/
@Service
public class UserServiceImpl implements UserService {
// 服务标准接口,duboo-spring-boot-starter会访问zk,查询远程服务信息,并创建一个proxy代理对象。
// 说明当前的属性需要dubbo来初始化,代表需要根据当前类型访问zk,查询可使用的服务信息,并创建代理对象,注入。
@Reference
private com.bjsxt.dubbo.service.UserService userService;
/**
* 调用远程dubbo provider提供的服务,实现用户的保存
* @param user
* @return
*/
@Override
public Map<String, Object> save(User user) {
// 调用远程服务逻辑
int i = userService.saveUser(user);
Map<String, Object> result = new HashMap<>();
result.put("code", i > 0 ? 200:500);
result.put("msg", i > 0 ? "新增用户成功": "新增用户失败");
return result;
}
/**
* 调用远程dubbo provider提供的服务,实现用户的查询
* @param name
* @return
*/
@Override
public User getUserByName(String name) {
return userService.getUserByName(name);
}
}
然后就是用19_dubbo/rpc_dubbo/dubbo_consumer/src/main/java/com/bjsxt/DubboConsumerApp.java来启动它,千万别忘了@EnableDubbo注解
@SpringBootApplication
@EnableDubbo
public class DubboConsumerApp {
public static void main(String[] args) {
SpringApplication.run(DubboConsumerApp.class, args);
}
}
第八节 负载均衡
8.1 开启两个项目
dubbo:
application: # dubbo应用的配置
name: dubbo-first-provider # 为当前的dubbo应用起一个名字
registry: # dubbo注册中心
address: zookeeper://192.168.2.129:2181 # 注册中心的方式地址
timeout: 50000
protocol: # dubbo服务发布的时候,协议配置
port: 20881 # 服务端口, 默认20880,现在新开一个端口叫20881
name: dubbo # 使用的协议名称, 默认dubbo协议。
provider:
loadbalance: roundrobin
然后新建一个类来启动它19_dubbo/rpc_dubbo/dubbo_consumer/src/main/java/com/bjsxt/DubboConsumerApp20881.java:
@SpringBootApplication
@EnableDubbo
public class DubboConsumerApp20881 {
public static void main(String[] args) {
SpringApplication.run(DubboConsumerApp20881.class, args);
}
}
8.2 负载均衡
所谓负载均衡就是设置集群的访问规则
集群:一模一样的内容部署多次形成的整体称为集群。
roundrobin:轮询
leastActive:一开始全部设置为1,活跃数相同的随机,不同的活跃数高的放前面
consistentHash:一致性hash,相同的参数总是发到一个提供者。
直接在server的service的实现类的注解上加即可:
@Service(loadbalance = "roundrobin", weight = 3)
public class UserServiceImpl implements UserService {
@Override
public int saveUser(User user) {
同样的,消费者的Reference注解也可以19_dubbo/rpc_dubbo/dubbo_consumer/src/main/java/com/bjsxt/service/impl/UserServiceImpl.java:
@Service
public class UserServiceImpl implements UserService {
// 服务标准接口,duboo-spring-boot-starter会访问zk,查询远程服务信息,并创建一个proxy代理对象。
// 说明当前的属性需要dubbo来初始化,代表需要根据当前类型访问zk,查询可使用的服务信息,并创建代理对象,注入。
@Reference(loadbalance = "roundrobin")
private com.bjsxt.dubbo.service.UserService userService;
然后也可以在配置文件上改:
dubbo
provider:
loadbalance: roundrobin

浙公网安备 33010602011771号