Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Y
yudao-cloud
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
hblj
yudao-cloud
Commits
d0ce24a2
提交
d0ce24a2
authored
6月 25, 2022
作者:
YunaiV
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
完善 yudao-spring-boot-starter-env 组件,完成 feign 组件
上级
f879c4aa
隐藏空白字符变更
内嵌
并排
正在显示
9 个修改的文件
包含
239 行增加
和
8 行删除
+239
-8
pom.xml
yudao-framework/yudao-spring-boot-starter-env/pom.xml
+15
-0
YudaoEnvRpcAutoConfiguration.java
...ao/framework/env/config/YudaoEnvRpcAutoConfiguration.java
+59
-0
YudaoEnvWebAutoConfiguration.java
...ao/framework/env/config/YudaoEnvWebAutoConfiguration.java
+5
-0
EnvLoadBalancerClient.java
...yudao/framework/env/core/fegin/EnvLoadBalancerClient.java
+81
-0
EnvLoadBalancerClientFactory.java
...ramework/env/core/fegin/EnvLoadBalancerClientFactory.java
+30
-0
EnvRequestInterceptor.java
...yudao/framework/env/core/fegin/EnvRequestInterceptor.java
+24
-0
EnvUtils.java
...va/cn/iocoder/yudao/framework/env/core/util/EnvUtils.java
+12
-2
spring.factories
...-starter-env/src/main/resources/META-INF/spring.factories
+2
-1
GrayLoadBalancer.java
...n/iocoder/yudao/gateway/filter/grey/GrayLoadBalancer.java
+11
-5
没有找到文件。
yudao-framework/yudao-spring-boot-starter-env/pom.xml
浏览文件 @
d0ce24a2
...
...
@@ -46,6 +46,21 @@
<artifactId>
jakarta.servlet-api
</artifactId>
</dependency>
<!-- RPC 相关 -->
<dependency>
<groupId>
org.springframework.cloud
</groupId>
<artifactId>
spring-cloud-loadbalancer
</artifactId>
</dependency>
<dependency>
<groupId>
io.github.openfeign
</groupId>
<artifactId>
feign-core
</artifactId>
</dependency>
<!-- Registry 注册中心相关 -->
<dependency>
<groupId>
com.alibaba.cloud
</groupId>
<artifactId>
spring-cloud-starter-alibaba-nacos-discovery
</artifactId>
</dependency>
</dependencies>
</project>
yudao-framework/yudao-spring-boot-starter-env/src/main/java/cn/iocoder/yudao/framework/env/config/YudaoEnvRpcAutoConfiguration.java
0 → 100644
浏览文件 @
d0ce24a2
package
cn
.
iocoder
.
yudao
.
framework
.
env
.
config
;
import
cn.iocoder.yudao.framework.env.core.fegin.EnvLoadBalancerClientFactory
;
import
cn.iocoder.yudao.framework.env.core.fegin.EnvRequestInterceptor
;
import
org.springframework.beans.factory.ObjectProvider
;
import
org.springframework.cloud.client.loadbalancer.LoadBalancerClientsProperties
;
import
org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientSpecification
;
import
org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
java.util.Collections
;
import
java.util.List
;
/**
* 多环境的 RPC 组件的自动配置
*
* @author 芋道源码
*/
@Configuration
public
class
YudaoEnvRpcAutoConfiguration
{
// ========== Feign 相关 ==========
// TODO @芋艿:由于 loadBalancerClientFactoryBeanPostProcessor 拦截不到 LoadBalancerClientFactory,所以采用 loadBalancerClientFactory 实现
// @Bean
// public BeanPostProcessor loadBalancerClientFactoryBeanPostProcessor(LoadBalancerClientsProperties properties) {
// return new BeanPostProcessor() {
// @Override
// public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// if (!(bean instanceof LoadBalancerClientFactory)) {
// return bean;
// }
// return bean;
// }
// };
// }
/**
* 创建 {@link EnvLoadBalancerClientFactory} Bean
*
* 参考 {@link org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration#loadBalancerClientFactory(LoadBalancerClientsProperties)} 方法
*/
@Bean
public
LoadBalancerClientFactory
loadBalancerClientFactory
(
LoadBalancerClientsProperties
properties
,
ObjectProvider
<
List
<
LoadBalancerClientSpecification
>>
configurations
)
{
EnvLoadBalancerClientFactory
clientFactory
=
new
EnvLoadBalancerClientFactory
(
properties
);
clientFactory
.
setConfigurations
(
configurations
.
getIfAvailable
(
Collections:
:
emptyList
));
return
clientFactory
;
}
@Bean
public
EnvRequestInterceptor
envRequestInterceptor
()
{
return
new
EnvRequestInterceptor
();
}
// ========== Dubbo 相关 ==========
}
yudao-framework/yudao-spring-boot-starter-env/src/main/java/cn/iocoder/yudao/framework/env/config/YudaoEnvWebAutoConfiguration.java
浏览文件 @
d0ce24a2
...
...
@@ -7,6 +7,11 @@ import org.springframework.boot.web.servlet.FilterRegistrationBean;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
/**
* 多环境的 Web 组件的自动配置
*
* @author 芋道源码
*/
@Configuration
@ConditionalOnWebApplication
(
type
=
ConditionalOnWebApplication
.
Type
.
SERVLET
)
public
class
YudaoEnvWebAutoConfiguration
{
...
...
yudao-framework/yudao-spring-boot-starter-env/src/main/java/cn/iocoder/yudao/framework/env/core/fegin/EnvLoadBalancerClient.java
0 → 100644
浏览文件 @
d0ce24a2
package
cn
.
iocoder
.
yudao
.
framework
.
env
.
core
.
fegin
;
import
cn.hutool.core.collection.CollUtil
;
import
cn.hutool.core.util.StrUtil
;
import
cn.iocoder.yudao.framework.common.util.collection.CollectionUtils
;
import
cn.iocoder.yudao.framework.env.core.context.EnvContextHolder
;
import
cn.iocoder.yudao.framework.env.core.util.EnvUtils
;
import
com.alibaba.cloud.nacos.balancer.NacosBalancer
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.ObjectProvider
;
import
org.springframework.cloud.client.ServiceInstance
;
import
org.springframework.cloud.client.loadbalancer.DefaultResponse
;
import
org.springframework.cloud.client.loadbalancer.EmptyResponse
;
import
org.springframework.cloud.client.loadbalancer.Request
;
import
org.springframework.cloud.client.loadbalancer.Response
;
import
org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer
;
import
org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier
;
import
org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer
;
import
org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier
;
import
reactor.core.publisher.Mono
;
import
java.util.List
;
/**
* 多环境的 {@link org.springframework.cloud.client.loadbalancer.LoadBalancerClient} 实现类
* 在从服务实例列表选择时,优先选择 tag 匹配的服务实例
*
* @author 芋道源码
*/
@RequiredArgsConstructor
@Slf4j
public
class
EnvLoadBalancerClient
implements
ReactorServiceInstanceLoadBalancer
{
/**
* 用于获取 serviceId 对应的服务实例的列表
*/
private
final
ObjectProvider
<
ServiceInstanceListSupplier
>
serviceInstanceListSupplierProvider
;
/**
* 需要获取的服务实例名
*
* 暂时用于打印 logger 日志
*/
private
final
String
serviceId
;
/**
* 被代理的 ReactiveLoadBalancer 对象
*/
private
final
ReactiveLoadBalancer
<
ServiceInstance
>
reactiveLoadBalancer
;
@Override
public
Mono
<
Response
<
ServiceInstance
>>
choose
(
Request
request
)
{
String
tag
=
EnvContextHolder
.
getTag
();
if
(
StrUtil
.
isEmpty
(
tag
))
{
return
Mono
.
from
(
reactiveLoadBalancer
.
choose
(
request
));
}
// 选择实例
ServiceInstanceListSupplier
supplier
=
serviceInstanceListSupplierProvider
.
getIfAvailable
(
NoopServiceInstanceListSupplier:
:
new
);
return
supplier
.
get
(
request
).
next
().
map
(
list
->
getInstanceResponse
(
list
,
tag
));
}
private
Response
<
ServiceInstance
>
getInstanceResponse
(
List
<
ServiceInstance
>
instances
,
String
tag
)
{
// 如果服务实例为空,则直接返回
if
(
CollUtil
.
isEmpty
(
instances
))
{
log
.
warn
(
"[getInstanceResponse][serviceId({}) 服务实例列表为空]"
,
serviceId
);
return
new
EmptyResponse
();
}
// 筛选满足条件的实例列表
List
<
ServiceInstance
>
chooseInstances
=
CollectionUtils
.
filterList
(
instances
,
instance
->
tag
.
equals
(
EnvUtils
.
getTag
(
instance
)));
if
(
CollUtil
.
isEmpty
(
chooseInstances
))
{
log
.
warn
(
"[getInstanceResponse][serviceId({}) 没有满足 tag({}) 的服务实例列表,直接使用所有服务实例列表]"
,
serviceId
,
tag
);
chooseInstances
=
instances
;
}
// TODO 芋艿:https://juejin.cn/post/7056770721858469896 想通网段
// 随机 + 权重获取实例列表 TODO 芋艿:目前直接使用 Nacos 提供的方法,如果替换注册中心,需要重新失败该方法
return
new
DefaultResponse
(
NacosBalancer
.
getHostByRandomWeight3
(
chooseInstances
));
}
}
yudao-framework/yudao-spring-boot-starter-env/src/main/java/cn/iocoder/yudao/framework/env/core/fegin/EnvLoadBalancerClientFactory.java
0 → 100644
浏览文件 @
d0ce24a2
package
cn
.
iocoder
.
yudao
.
framework
.
env
.
core
.
fegin
;
import
org.springframework.cloud.client.ServiceInstance
;
import
org.springframework.cloud.client.loadbalancer.LoadBalancerClientsProperties
;
import
org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer
;
import
org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier
;
import
org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory
;
/**
* 多环境的 {@link LoadBalancerClientFactory} 实现类
* 目的:在创建 {@link ReactiveLoadBalancer} 时,会额外增加 {@link EnvLoadBalancerClient} 代理,用于 tag 过滤服务实例
*
* @author 芋道源码
*/
public
class
EnvLoadBalancerClientFactory
extends
LoadBalancerClientFactory
{
public
EnvLoadBalancerClientFactory
(
LoadBalancerClientsProperties
properties
)
{
super
(
properties
);
}
@Override
public
ReactiveLoadBalancer
<
ServiceInstance
>
getInstance
(
String
serviceId
)
{
ReactiveLoadBalancer
<
ServiceInstance
>
reactiveLoadBalancer
=
super
.
getInstance
(
serviceId
);
// 参考 {@link com.alibaba.cloud.nacos.loadbalancer.NacosLoadBalancerClientConfiguration#nacosLoadBalancer(Environment, LoadBalancerClientFactory, NacosDiscoveryProperties)} 方法
return
new
EnvLoadBalancerClient
(
super
.
getLazyProvider
(
serviceId
,
ServiceInstanceListSupplier
.
class
),
serviceId
,
reactiveLoadBalancer
);
}
}
yudao-framework/yudao-spring-boot-starter-env/src/main/java/cn/iocoder/yudao/framework/env/core/fegin/EnvRequestInterceptor.java
0 → 100644
浏览文件 @
d0ce24a2
package
cn
.
iocoder
.
yudao
.
framework
.
env
.
core
.
fegin
;
import
cn.hutool.core.util.StrUtil
;
import
cn.iocoder.yudao.framework.env.core.context.EnvContextHolder
;
import
cn.iocoder.yudao.framework.env.core.util.EnvUtils
;
import
feign.RequestInterceptor
;
import
feign.RequestTemplate
;
/**
* 多环境的 {@link RequestInterceptor} 实现类:Feign 请求时,将 tag 设置到 header 中,继续透传给被调用的服务
*
* @author 芋道源码
*/
public
class
EnvRequestInterceptor
implements
RequestInterceptor
{
@Override
public
void
apply
(
RequestTemplate
requestTemplate
)
{
String
tag
=
EnvContextHolder
.
getTag
();
if
(
StrUtil
.
isNotEmpty
(
tag
))
{
EnvUtils
.
setTag
(
requestTemplate
,
tag
);
}
}
}
yudao-framework/yudao-spring-boot-starter-env/src/main/java/cn/iocoder/yudao/framework/env/core/util/EnvUtils.java
浏览文件 @
d0ce24a2
package
cn
.
iocoder
.
yudao
.
framework
.
env
.
core
.
util
;
import
cn.hutool.core.net.NetUtil
;
import
feign.RequestTemplate
;
import
org.springframework.cloud.client.ServiceInstance
;
import
javax.servlet.http.HttpServletRequest
;
import
java.util.Objects
;
...
...
@@ -12,15 +14,23 @@ import java.util.Objects;
*/
public
class
EnvUtils
{
private
static
final
String
HEADER_
DUBBO_
TAG
=
"tag"
;
private
static
final
String
HEADER_TAG
=
"tag"
;
private
static
final
String
HOST_NAME_VALUE
=
"${HOSTNAME}"
;
public
static
String
getTag
(
HttpServletRequest
request
)
{
String
tag
=
request
.
getHeader
(
HEADER_
DUBBO_
TAG
);
String
tag
=
request
.
getHeader
(
HEADER_TAG
);
// 如果请求的是 "${HOSTNAME}",则解析成对应的本地主机名
// 目的:特殊逻辑,解决 IDEA Rest Client 不支持环境变量的读取,所以就服务器来做
return
Objects
.
equals
(
tag
,
HOST_NAME_VALUE
)
?
NetUtil
.
getLocalHostName
()
:
tag
;
}
public
static
String
getTag
(
ServiceInstance
instance
)
{
return
instance
.
getMetadata
().
get
(
HEADER_TAG
);
}
public
static
void
setTag
(
RequestTemplate
requestTemplate
,
String
tag
)
{
requestTemplate
.
header
(
HEADER_TAG
,
tag
);
}
}
yudao-framework/yudao-spring-boot-starter-env/src/main/resources/META-INF/spring.factories
浏览文件 @
d0ce24a2
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.iocoder.yudao.framework.env.config.YudaoEnvWebAutoConfiguration
cn.iocoder.yudao.framework.env.config.YudaoEnvWebAutoConfiguration,\
cn.iocoder.yudao.framework.env.config.YudaoEnvRpcAutoConfiguration
yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/filter/grey/GrayLoadBalancer.java
浏览文件 @
d0ce24a2
...
...
@@ -35,8 +35,16 @@ public class GrayLoadBalancer implements ReactorServiceInstanceLoadBalancer {
private
static
final
String
VERSION
=
"version"
;
private
final
ObjectProvider
<
ServiceInstanceListSupplier
>
serviceInstanceListSupplierProvider
;
// 用于获取 serviceId 对应的服务实例的列表
private
final
String
serviceId
;
// 服务名,暂时用于打印 logger 日志
/**
* 用于获取 serviceId 对应的服务实例的列表
*/
private
final
ObjectProvider
<
ServiceInstanceListSupplier
>
serviceInstanceListSupplierProvider
;
/**
* 需要获取的服务实例名
*
* 暂时用于打印 logger 日志
*/
private
final
String
serviceId
;
@Override
public
Mono
<
Response
<
ServiceInstance
>>
choose
(
Request
request
)
{
...
...
@@ -50,9 +58,7 @@ public class GrayLoadBalancer implements ReactorServiceInstanceLoadBalancer {
private
Response
<
ServiceInstance
>
getInstanceResponse
(
List
<
ServiceInstance
>
instances
,
HttpHeaders
headers
)
{
// 如果服务实例为空,则直接返回
if
(
CollUtil
.
isEmpty
(
instances
))
{
if
(
log
.
isWarnEnabled
())
{
log
.
warn
(
"[getInstanceResponse][serviceId({}) 服务实例列表为空]"
,
serviceId
);
}
log
.
warn
(
"[getInstanceResponse][serviceId({}) 服务实例列表为空]"
,
serviceId
);
return
new
EmptyResponse
();
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论