ip端口探活
admin中的探活主要使用UpstreamCheckService这个类
- 关键代码解析
/**
* Setup selectors of divide plugin.
*/
// 初始化
@PostConstruct
public void setup() {
// 获取DIVIDE插件信息
PluginDO pluginDO = pluginMapper.selectByName(PluginEnum.DIVIDE.getName());
if (pluginDO != null) {
// 获取divide插件的选择器列表
List<SelectorDO> selectorDOList = selectorMapper.findByPluginId(pluginDO.getId());
for (SelectorDO selectorDO : selectorDOList) {
// 获取数据库保存的divide代理服务列表
List<DivideUpstream> divideUpstreams = GsonUtils.getInstance().fromList(selectorDO.getHandle(), DivideUpstream.class);
if (CollectionUtils.isNotEmpty(divideUpstreams)) {
// 被代理的服务信息缓存
UPSTREAM_MAP.put(selectorDO.getName(), divideUpstreams);
}
}
}
// 根据ip端口进行服务探活
if (check) {
new ScheduledThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), SoulThreadFactory.create("scheduled-upstream-task", false))
.scheduleWithFixedDelay(this::scheduled, 10, scheduledTime, TimeUnit.SECONDS);
}
}
// 具体的探活操作
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) {
// 长度大于0,更新配置
UPSTREAM_MAP.put(selectorName, successList);
updateSelectorHandler(selectorName, successList);
} else {
// 长度等于0,移除配置
UPSTREAM_MAP.remove(selectorName);
updateSelectorHandler(selectorName, null);
}
}
一开始的时候,会从数据库查询divide插件信息和代理的服务列表,如果探活检查标记为true,则进行探活检测
探活检测即对代理的服务列表进行socket连接测试,连接上则为存活,并通过eventPublisher通知其他bootstrap
springcloud集成查看 Soul源码阅读 体验SpringCloud代理【第五天】
Bootstrap 集成springcloud,pom需要添加如下的依赖
<!-- springCloud if you config register center is eureka please dependency end-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
配置初始化 SoulSpringCloudClientConfiguration
/**
* Spring cloud client bean post processor.
*
* @param soulSpringCloudConfig the soul spring cloud config
* @param env the env
* @return the spring cloud client bean post processor
*/
// 注册配置
@Bean
public SpringCloudClientBeanPostProcessor springCloudClientBeanPostProcessor(final SoulSpringCloudConfig soulSpringCloudConfig, final Environment env) {
return new SpringCloudClientBeanPostProcessor(soulSpringCloudConfig, env);
}
# 这个是干嘛用的?
/**
* Context register listener.
*
* @param soulSpringCloudConfig the soul spring cloud config
* @param env the env
* @return the context register listener
*/
@Bean
public ContextRegisterListener contextRegisterListener(final SoulSpringCloudConfig soulSpringCloudConfig, final Environment env) {
return new ContextRegisterListener(soulSpringCloudConfig, env);
}
使用SpringCloudClientBeanPostProcessor注册到eureka
// 注册
@Override
public Object postProcessAfterInitialization(@NonNull final Object bean, @NonNull final String beanName) throws BeansException {
// 如果是全部代理
if (config.isFull()) {
return bean;
}
// 请求的controller注解获取
Controller controller = AnnotationUtils.findAnnotation(bean.getClass(), Controller.class);
RestController restController = AnnotationUtils.findAnnotation(bean.getClass(), RestController.class);
RequestMapping requestMapping = AnnotationUtils.findAnnotation(bean.getClass(), RequestMapping.class);
// 有一个就获取一个
if (controller != null || restController != null || requestMapping != null) {
String prePath = "";
// 找到controller上的注解
SoulSpringCloudClient clazzAnnotation = AnnotationUtils.findAnnotation(bean.getClass(), SoulSpringCloudClient.class);
// 如果存在注解则代理
if (Objects.nonNull(clazzAnnotation)) {
// 如果是全部都代理
if (clazzAnnotation.path().indexOf("*") > 1) {
// 路径都进行注册
String finalPrePath = prePath;
executorService.execute(() -> RegisterUtils.doRegister(buildJsonParams(clazzAnnotation, finalPrePath), url,
RpcTypeEnum.SPRING_CLOUD));
return bean;
}
// 不然就注册注解的路径
prePath = clazzAnnotation.path();
}
// 需要代理的方法数组
final Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(bean.getClass());
for (Method method : methods) {
// 找到方法代理
SoulSpringCloudClient soulSpringCloudClient = AnnotationUtils.findAnnotation(method, SoulSpringCloudClient.class);
// 存在方法代理
if (Objects.nonNull(soulSpringCloudClient)) {
String finalPrePath = prePath;
// 进行注册
executorService.execute(() -> RegisterUtils.doRegister(buildJsonParams(soulSpringCloudClient, finalPrePath), url,
RpcTypeEnum.SPRING_CLOUD));
}
}
}
return bean;
}
网友评论