前言
随着现在技术的不断深入,服务的不断增多,不仅仅是海量数据、用户数量多,而且很容易出现高并发。所以分布式的系统就慢慢出现了。这种分布式系统主要就是将一个完整的系统进行拆分,拆分成一个个微服务,做到每一个服务是小而专的特点。也就是各司其职。所以大家可能会说:“那它们之间怎么交流呢?这分开了,还怎么形成一个完整的系统。这个时候,dubbo就出来了。他就是用来解决每个微服务之间的交互的,也就是RPC(远程调用)。
Dubbo具有的功能:远程调用、服务的注册与发现、支持负载均衡、容灾和集群功能。
正文
下面就直接上干货吧!!!
- 前期准备:
1)我们在使用dubbo的时候,首先我们的环境中要有jdk。
2)因为我们dubbo是要进行服务的注册与发现。所以它要有一个注册中心。其实所谓的注册中心就是用来存储我们拥有哪些服务。所以能做注册中心就是哪些可以存储的东西。比如zookeeper、redis。一般我们都使用zk的。所以这里我们使用zk作为注册中心。
3)安装zookeeper:
先去下载zookeepr
解压后,执行下方的命令
# 在zookeeper文件夹中创建data文件夹 里面存放一些临时数据
mkdir data
# 进入conf中修改配置文件的名字
mv zoo_sample.cfg zoo.cfg
# 进入zoo.cfg这个文件,修改里面的dataDir,路径改成刚才创建的data的文件夹的位置
dataDir=/usr/local/tangyuan/zookeeper/zookeeper-3.6.3/data
# 然后启动zookeeper
./zkServer.sh start 启动
./zkServer.sh stop 停止
./zkServer.sh status 状态
#不报错 就说明你上面的操作都是正常的。
- 创建项目 写代码 引入dubbo的jar 然后就没了 是不是很简单
我们这里就以一个服务方和消费方作为例子。用消费方远程调用服务方。
服务方:
- 引入jar
<!--dubbo的springboot支持-->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<!--dubbo框架-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<!--zk依赖-->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
</dependency>
- 配置文件
# 服务方
server:
port: 8081
servlet:
context-path: /tangyuan
dubbo:
application:
name: dubbo-provider-qishen
protocol:
name: dubbo
port: 20880
host: 192.168.23.1
registry:
address: zookeeper://192.168.23.129:2181
client: zkclient
timeout: 60000
consumer:
timeout: 60000
scan:
basePackages: com.qishen.dubbo_provider
#消费方
dubbo:
application:
name: dubbo-consum-qishen
registry:
address: zookeeper://192.168.23.129:2181
client: zkclient
timeout: 60000
consumer:
timeout: 60000
scan:
basePackages: com.qishen.dubbo_consum
#注意 上面是两个配置 文件 不要写在一个里面了
- dubbo中比较重要的两个注解
服务方使用注解@Service
消费方注入服务使用注解@Reference
- dubbo的高级特性
- 序列化
dubbo内部已经进行了序列化与反序列化的封装了,所以我们只需要实现serializable接口就可以了。这样我们的对象就可以进行远程传输了,不然在传输对象的时候就会出现报错的情况了 - 地址缓存
所谓的地址缓存是指:当我们的服务第一次调用的时候就会把服务的提供方地址缓存到本地,当地址发生变化后,注册中心就会通知消费者,重新获取服务提供方的地址并进行缓存 - 超时
当服务的消费者调用服务的提供者的时候出现阻塞、等待的情况,服务的消费方会一直处于等待的状态,当大量的请求处于这个阶段,就会造成雪崩。所以dubbo提供了超时的机制。
做法:在@Service注解种加入timeout
@Service(timeout=3000,retries=0) //timeoout 超时时间 retries 重试次数
- 重试
当我们链接不上的时候,可能是网络抖动引起的,所以我们不能出现这种问题,也让我们程序跑不下去啊,所以我们要进行重试,果断时间,再发一次请求。用法就不说了 超时里面写的有 - 多版本
多版本就很好理解了,我们在发布新的功能的时候,如果改动原来的dubbo内容,之前的功能也要用,是让不同的用户来试试,就跟你打王者荣耀,人家是不死也有一个体验服,让别人体验好了,在放在正式服上面。 这个就是这个道理,所以这里我们也是通过一个属性实现的
@Sercice(version="1.1.0")
- 负载均衡
负载均衡的概念,我就不做过多解释了。比如一个服务消费者发送了多个请求到一个服务提供者上面进行处理,是不是要排队等着处理,你想想你排队买饭,是不是很着急。万一前面想吃的被别人买完了怎么办!!!
这个时候,有多个队伍都可以买这个饭,相对来说 你是不是排的靠前了。这就是负载均衡。
均衡一点嘛 你品 你细品 晓得了吧
负载均衡策略:
Random: 按权重随机,默认值。按权重设置随机概率。
RoundRobin: 按权重轮询。
LeastActive: 最少活跃调用数,相同活跃数的随机。
ConsistentHash: 一致性Hash,相同参数的请求总是发到同一提供者。
服务者配置:
@Service(weight = 100)
消费者配置:
//@Reference(loadbalance = "roundrobin")
//@Reference(loadbalance = "leastactive")
//@Reference(loadbalance = "consistenthash")
@Reference(loadbalance = "random")//默认 按权重随机
- 集群容错
上面的负载均衡都理解了 那集群不就更简单了嘛,所谓集群就是那本来就一个队伍买饭,现在有多个队伍可以买饭了,这就是集群。
集群模式:
Failover Cluster:失败重试。默认值。当出现失败,重试其它服务器,默认重试2次,使用retries配置。一般用于读操作
Failfast Cluster :快速失败,发起-次调用,失败立即报错。通常用于写操作。
Failsafe Cluster:失败安全,出现异常时,直接忽略。返回一个空结果。
Failback Cluster:失败自动恢复,后台记录失败请求,定时重发。
Forking Cluster :并行调用多个服务器,只要一个成功即返回。
Broadcast Cluster: 广播调用所有提供者,逐个调用,任意一台报错则报错。
这个只需要消费者配置一下就行了 队伍都已经在那放着了,现在就是看你怎么用这几个队伍了。 以那种集群的方式使用了。
消费者配置:
@Reference(cluster = "failover")//远程注入
private UserService userService;
- 服务降级
最后一个了,服务降级,这个可能从字面上难以理解,我就解释一下:
大家都在双11在淘宝、京东这些地方买过东西吧。他们那段时间销售量那么大,为啥服务器还没有崩掉呢,当然不是完全因为使用服务降级了,首先人家也不一定了dubbo嘛,而且解决这种的方案很多,可能都用了,也可能用了一部分,我这里就是假设用了,举个例子而已。
所谓服务降级就是当服务器压力巨大的情况,我们可以设置一些服务的页面不处理或者换简单的方法处理,比如,你在双11买东西,你主要是买东西呢,还是在当前该账户密码、注册账号啊。答案很明显,对于这些不重要的服务,我们可以采用降级的方式处理,以保证释放足够的资源去处理核心的业务——卖东西。
服务降级的方式:
-
mock= force:return null:表示消费方对该服务的方法调用都直接返回null值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响
-
mock=fail:return null:表示消费方对该服务的方法调用在失败后,再返回null值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响
概念都说的差不多,给你们看点代码吧(此处只有核心代码)
- 实体类
package com.qishen.dubbo_inter.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author 岐神~汤圆FengJY
* @version 1.0
* @description
* @date 2021/10/20 17:17
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
private String id;
private String name;
private String phone;
}
#注意 :写实体类得时候一定实现这个接口
- 消费方代码
package com.qishen.dubbo_consum.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.qishen.dubbo_inter.inter.UserService;
import com.qishen.dubbo_inter.pojo.User;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author 岐神~汤圆FengJY
* @version 1.0
* @description
* @date 2021/10/20 18:52
*/
@RestController
public class UserController {
@Reference(version = "1.1")
private UserService userService;
@RequestMapping ("/a/{id}")
public User getUserId(@PathVariable String id){
return userService.getUser(id);
}
}
- 服务方代码
package com.qishen.dubbo_provider.service.impl;
import com.alibaba.dubbo.config.annotation.Service;
import com.qishen.dubbo_inter.inter.UserService;
import com.qishen.dubbo_inter.pojo.User;
/**
* @author 岐神~汤圆FengJY
* @version 1.0
* @description
* @date 2021/10/20 18:50
*/
@Service(version = "1.1")
public class UserServiceImpl implements UserService {
@Override
public User getUser(String id) {
return new User(id,"张三","1234");
}
}
配置文件最前面说过了,代码不多 !!!
源码:https://gitee.com/fengjiyuan/dubbo_demo.git
福利:平时 我们想要看我们dubbo得服务运行状态怎么办呢,还好,有一个工具叫做dubbo-admin,
大概样子就是这个,他其实就是一个springboot+vue的项目,大家可自行下载https://github.com/apache/dubbo-admin/
我们只需要修改配置文件就行了
这个是我上面的,然后启动就行了。我就不过多介绍了,这个比较简单。
最后:我觉得现在有好多使用nacos作为注册中心的(后面面有机会再介绍这个),所以zookeeper大家知道是干嘛的就行,也不用特别的去学习。