概述
soul网关源码学习03-dubbo应用示例运行
目标:
- 运行dubbo-example
- 走一遍熔断、限流插件
一、启动项目
启动soul-admin,发现有个报错。
根据报错信息,找到相应的代码,发现程序会去检查已配置的这些选择器是否连接有效,把已失去连接的从内存移除。
private void check(final String selectorName, final List<DivideUpstream> upstreamList) {
List<DivideUpstream> successList = Lists.newArrayListWithCapacity(upstreamList.size());
for (DivideUpstream divideUpstream : upstreamList) {
final boolean pass = UpstreamCheckUtils.checkUrl(divideUpstream.getUpstreamUrl());
if (pass) {
if (!divideUpstream.isStatus()) {
divideUpstream.setTimestamp(System.currentTimeMillis());
divideUpstream.setStatus(true);
log.info("UpstreamCacheManager check success the url: {}, host: {} ", divideUpstream.getUpstreamUrl(), divideUpstream.getUpstreamHost());
}
successList.add(divideUpstream);
} else {
divideUpstream.setStatus(false);
log.error("check the url={} is fail ", divideUpstream.getUpstreamUrl());
}
}
if (successList.size() == upstreamList.size()) {
return;
}
if (successList.size() > 0) {
UPSTREAM_MAP.put(selectorName, successList);
updateSelectorHandler(selectorName, successList);
} else {
UPSTREAM_MAP.remove(selectorName);
updateSelectorHandler(selectorName, null);
}
}
什么时候会执行这个check?找到有个定时10秒钟的线程,在定期检查已配置的信息是否连接有效。
if (check) {
new ScheduledThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), SoulThreadFactory.create("scheduled-upstream-task", false))
.scheduleWithFixedDelay(this::scheduled, 10, scheduledTime, TimeUnit.SECONDS);
}
private void scheduled() {
if (UPSTREAM_MAP.size() > 0) {
UPSTREAM_MAP.forEach(this::check);
}
}
根据这行代码“UPSTREAM_MAP.forEach(this::check); ”,找到UPSTREAM_MAP的来源,在submit方法中。这里的配置用了一个Map来存,查找的时候用containsKey方法,O(1)的时间复杂度,避免循环遍历。
public void submit(final String selectorName, final DivideUpstream divideUpstream) {
if (UPSTREAM_MAP.containsKey(selectorName)) {
UPSTREAM_MAP.get(selectorName).add(divideUpstream);
} else {
UPSTREAM_MAP.put(selectorName, Lists.newArrayList(divideUpstream));
}
}
然后,这个submit方法什么时候调用?是SoulClientController里面的一个方法调用的。
@RestController
@RequestMapping("/soul-client")
public class SoulClientController {
@PostMapping("/springmvc-register")
public String registerSpringMvc(@RequestBody final SpringMvcRegisterDTO springMvcRegisterDTO) {
return soulClientRegisterService.registerSpringMvc(springMvcRegisterDTO);
}
}
这里的接口又是什么时候调用的?就是上一讲讲到的注册接口的时候发起的http请求。
public static void doRegister(final String json, final String url, final RpcTypeEnum rpcTypeEnum) {
try {
String result = OkHttpTools.getInstance().post(url, json);
if (AdminConstants.SUCCESS.equals(result)) {
log.info("{} client register success: {} ", rpcTypeEnum.getName(), json);
} else {
log.error("{} client register error: {} ", rpcTypeEnum.getName(), json);
}
} catch (IOException e) {
log.error("cannot register soul admin param, url: {}, request body: {}", url, json, e);
}
}
所以,那个error,其实是正常的,把http服务启动了就能正常使用了。
。。。好的,启动dubbo项目。
启动报错,没起zk,起个zk再重启dubbo就OK了。
二、运行dubbo-example
打开http://localhost:9095,admin/123456 进入系统,点击插件管理,开启dubbo插件。
用http请求调用dubbo服务,感觉跟http服务类似。
三、熔断插件
首先,在插件管理中开启熔断插件
新增熔断选择器
新增熔断规则
先调用一下刚才的dubbo服务,返回正常,然后把dubbo服务停掉,再次调用接口,说明熔断插件生效,dubbo服务已被熔断。
把熔断插件关闭,再次调用接口,返回500找不到服务。
四、限流插件
启动一个redis服务,然后开启限流插件。
新增一个选择器
新增一个规则
capacity:是你允许用户每秒执行多少请求,而丢弃任何请求。这是令牌桶的填充速率。
rate:是允许用户在一秒钟内执行的最大请求数。这是令牌桶可以保存的令牌数。
快速的点击send调用接口会发现被限流的情况
五、总结
- 根据一个error了解了一下接口注册的流程,接下来需要把整个流程以及四种数据同步的方式完整的debug走一遍。
- 走了一遍dubbo的转发,熔断、限流插件,大概了解了功能和流程,后续了还需要深入的研究源码。
- 感觉每次看代码都有不同的收获,看的过程总会遇到一些自己不懂的东西,根据这些问题去查资料,能学到很多新的知识,也巩固了之前很多学过的知识。
最后
以上就是顺利飞鸟为你收集整理的soul网关源码学习03-dubbo应用示例运行soul网关源码学习03-dubbo应用示例运行的全部内容,希望文章能够帮你解决soul网关源码学习03-dubbo应用示例运行soul网关源码学习03-dubbo应用示例运行所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复