Dubbo
【黑马程序员Dubbo快速入门,Java分布式框架dubbo教程】
4 Dubbo 高级特性
文章目录
- Dubbo
- 4 Dubbo 高级特性
- 4.2 Dubbo 常用高级配置
- 4.2.2 地址缓存
- 4.2.3 超时
4.2 Dubbo 常用高级配置
4.2.2 地址缓存
【一个问题】
如果 注册中心挂了,服务是否可以正常访问?
- 可以,因为dubbo服务消费者在第一次调用时,会将服务提供方地址缓存到本地,以后在调用则不会访问注册中心。
- 当服务提供者地址发生变化时,注册中心会通知服务消费者。
【试试】
上次我们 已经实现了 一次访问,OK,我现在把 zookeeper 停掉
./zkServer.sh stop
OK
再试一次,能否 正常访问
OK,效果很明显, 就算注册中心 挂掉了, 【老的】服务依然可以正常 访问
4.2.3 超时
【一个场景】
现在还是 有一个 消费者 和一个 提供者
而且它俩 分别 部署在了 A B 两台 机器上
现在来了 一个 用户来访问 服务消费者
这时 服务消费者 内部会单独地创建 一个线程 来去访问服务提供者来 调用 服务
服务提供者 把数据处理好 后,把数据返回 给服务消费者
消费者拿到后,再把数据封装一下,就可以返回 给用户了
这样整个请求过程 就算结束了【线程 也就被释放了【或者 归还到线程池】】
这是正常理想情况。
【不正常 的情况】
- 服务消费者在调用服务提供者的时候发生了阻塞、等待的情形,这个时候,服务消费者会一直等待下去。
- 在某个峰值时刻,大量的请求都在同时请求服务消费者,会造成线程的大量堆积,势必会造成雪崩。
这样A 机器可能 就会因为 资源被用光 而就会挂掉了 。
【Dubbo的解决办法】
- dubbo 利用超时机制来解决这个问题,设置一个超时时间,在这个时间段内,无法完成服务访问,则自动断开连接。
- 使用timeout属性配置超时时间,默认值1000,单位毫秒。
比如说这里, 3s 种之内,你B 不给我响应,我当前一定断开 这个请求
这样就 不会 造成 ‘积压’ 了
【试试】
① 在服务提供方,在@Service 注解上配置 :
现在给查 User ,让它睡一会儿
package com.dingjiaxiong.service.impl;
import com.dingjiaxiong.pojo.User;
import com.dingjiaxiong.service.UserService;
import org.apache.dubbo.config.annotation.Service;
/**
* ClassName: UserServiceImpl
* date: 2022/11/13 20:27
*
* @author DingJiaxiong
*/
//@Service
@Service(timeout = 3000,retries = 0) // 将这个类提供的方法【服务】对外发布,将访问的地址ip、端口、路径注册到 注册中心 中
public class UserServiceImpl implements UserService {
public String sayHello() {
return "Hello , Dubbo! DingJiaxiong";
}
public User findUserById(int id) {
// 查询User 对象【这里躲懒了,不走数据库】
User user = new User(1,"zhangsan","123");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return user;
}
}
OK。
为了测试效果 更明显,修改一下控制器
package com.dingjiaxiong.controller;
import com.dingjiaxiong.pojo.User;
import com.dingjiaxiong.service.UserService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* ClassName: UserController
* date: 2022/11/13 20:39
*
* @author DingJiaxiong
*/
@RestController
@RequestMapping("/user")
public class UserController {
//注入 Service
// @Autowired //这个是本地 注入
@Reference
private UserService userService;
@RequestMapping("/sayHello")
public String sayHello(){
return userService.sayHello();
}
int i = 1;
// 根据ID 查询用户信息
@RequestMapping("/find")
public User find(int id){
new Thread(new Runnable() {
public void run() {
while (true){
System.out.println(i ++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}).start();
return userService.findUserById(id);
}
}
OK。重启两个 服务
访问测试测试
OK, 基本一致 ,3 s钟 到了,该超时 了,就开始报错了
大概就是这么 个意思
现在 把timeout 删掉 ,看看默认是多少
OK, 重启 service
嗯,timeout 默认值是 1s
现在 在服务 提供方配个 3s,在服务消费方配 个1s
试试现在会是多少
OK, 是1
以后 定义超时尽量在 服务提供方 定义