提交 b060d8ee 编写于 作者: zlt2000's avatar zlt2000

增加自定义负载均衡规则,实现服务实例版本号隔离

上级 1c17de32
......@@ -16,4 +16,6 @@ spring:
shared-dataids: common.yml
refreshable-dataids: common.yml
discovery:
server-addr: ${zlt.nacos.server-addr}
\ No newline at end of file
server-addr: ${zlt.nacos.server-addr}
# metadata:
# version: zlt
\ No newline at end of file
package com.central.common.config;
import com.central.common.constant.ConfigConstants;
import com.central.common.feign.UserService;
import com.central.common.interceptor.LbIsolationInterceptor;
import com.central.common.interceptor.TenantInterceptor;
import com.central.common.interceptor.TraceInterceptor;
import com.central.common.resolver.ClientArgumentResolver;
import com.central.common.resolver.TokenArgumentResolver;
import com.central.log.properties.TraceProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
......@@ -23,6 +27,12 @@ public class DefaultWebMvcConfig extends WebMvcConfigurationSupport {
@Autowired
private UserService userService;
@Autowired
private TraceProperties traceProperties;
@Value("${" + ConfigConstants.CONFIG_RIBBON_ISOLATION_ENABLED + ":false}")
private boolean enableIsolation;
/**
* 配置SpringMVC拦截器,添加租户拦截器
*/
......@@ -31,8 +41,15 @@ public class DefaultWebMvcConfig extends WebMvcConfigurationSupport {
//租户拦截器
registry.addInterceptor(new TenantInterceptor()).addPathPatterns("/**");
//日志链路追踪拦截器
registry.addInterceptor(new TraceInterceptor()).addPathPatterns("/**");
if (traceProperties.getEnable()) {
//日志链路追踪拦截器
registry.addInterceptor(new TraceInterceptor()).addPathPatterns("/**");
}
if (enableIsolation) {
//负债均衡隔离规则拦截器
registry.addInterceptor(new LbIsolationInterceptor()).addPathPatterns("/**");
}
super.addInterceptors(registry);
}
......
......@@ -117,4 +117,12 @@ public interface CommonConstant {
* 日志链路追踪id日志标志
*/
String LOG_TRACE_ID = "traceId";
/**
* 负载均衡策略-版本号 信息头
*/
String Z_L_T_VERSION = "z-l-t-version";
/**
* 注册中心元数据 版本号
*/
String METADATA_VERSION = "version";
}
package com.central.common.constant;
/**
* 配置项常量
*
* @author zlt
* @date 2019/9/3
*/
public interface ConfigConstants {
/**
* 是否开启自定义隔离规则
*/
String CONFIG_RIBBON_ISOLATION_ENABLED = "zlt.ribbon.isolation.enabled";
}
package com.central.common.context;
import com.alibaba.ttl.TransmittableThreadLocal;
/**
* 负载均衡策略Holder
*
* @author zlt
* @date 2019/9/2
*/
public class LbIsolationContextHolder {
private static final ThreadLocal<String> VERSION_CONTEXT = new TransmittableThreadLocal<>();
public static void setVersion(String version) {
VERSION_CONTEXT.set(version);
}
public static String getVersion() {
return VERSION_CONTEXT.get();
}
public static void clear() {
VERSION_CONTEXT.remove();
}
}
package com.central.common.interceptor;
import cn.hutool.core.util.StrUtil;
import com.central.common.constant.CommonConstant;
import com.central.common.context.LbIsolationContextHolder;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 负载均衡隔离规则截器
*
* @author zlt
* @date 2019/8/5
*/
public class LbIsolationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String version = request.getHeader(CommonConstant.Z_L_T_VERSION);
if(StrUtil.isNotEmpty(version)){
LbIsolationContextHolder.setVersion(version);
}
return true;
}
}
......@@ -24,6 +24,11 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
......
package com.central.common.ribbon;
import com.central.common.constant.ConfigConstants;
import com.central.common.ribbon.config.RestTemplateProperties;
import com.central.common.ribbon.config.RuleConfigure;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.netflix.ribbon.DefaultPropertiesFactory;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Ribbon扩展配置类
......@@ -12,9 +17,15 @@ import org.springframework.context.annotation.Bean;
* @date 2018/11/17 9:24
*/
@EnableConfigurationProperties(RestTemplateProperties.class)
public class RibbonAutoConfigure {
public class RibbonAutoConfigure {
@Bean
public DefaultPropertiesFactory defaultPropertiesFactory() {
return new DefaultPropertiesFactory();
}
@Configuration
@ConditionalOnProperty(value = ConfigConstants.CONFIG_RIBBON_ISOLATION_ENABLED, havingValue = "true")
@RibbonClients(defaultConfiguration = {RuleConfigure.class})
public class LbIsolationConfig {
}
}
......@@ -29,6 +29,7 @@ public class FeignInterceptorConfig {
requestHeaders.add(SecurityConstants.USER_ID_HEADER);
requestHeaders.add(SecurityConstants.USER_HEADER);
requestHeaders.add(SecurityConstants.ROLE_HEADER);
requestHeaders.add(CommonConstant.Z_L_T_VERSION);
}
/**
......
package com.central.common.ribbon.config;
import com.central.common.ribbon.rule.CustomIsolationRule;
import com.netflix.loadbalancer.IRule;
import org.springframework.context.annotation.Bean;
/**
* @author zlt
* @date 2019/9/3
*/
public class RuleConfigure {
@Bean
public IRule isolationRule() {
return new CustomIsolationRule();
}
}
package com.central.common.ribbon.rule;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.central.common.constant.CommonConstant;
import com.central.common.context.LbIsolationContextHolder;
import com.netflix.loadbalancer.*;
import java.util.List;
import java.util.stream.Collectors;
/**
* 自定义隔离随机规则
*
* @author zlt
* @date 2019/9/3
*/
public class CustomIsolationRule extends RoundRobinRule {
/**
* 优先根据版本号取实例
*/
@Override
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
}
String version = LbIsolationContextHolder.getVersion();
List<Server> targetList = null;
List<Server> upList = lb.getReachableServers();
if (StrUtil.isNotEmpty(version)) {
//取指定版本号的实例
targetList = upList.stream().filter(
server -> version.equals(
((NacosServer) server).getMetadata().get(CommonConstant.METADATA_VERSION)
)
).collect(Collectors.toList());
}
if (CollUtil.isEmpty(targetList)) {
//只取无版本号的实例
targetList = upList.stream().filter(
server -> {
String metadataVersion = ((NacosServer) server).getMetadata().get(CommonConstant.METADATA_VERSION);
return StrUtil.isEmpty(metadataVersion);
}
).collect(Collectors.toList());
}
if (CollUtil.isNotEmpty(targetList)) {
return getServer(targetList);
}
return super.choose(lb, key);
}
/**
* 随机取一个实例
*/
private Server getServer(List<Server> upList) {
int nextInt = RandomUtil.randomInt(upList.size());
return upList.get(nextInt);
}
}
......@@ -21,4 +21,7 @@ zlt.fdfs.web-url=192.168.28.130
zlt.fdfs.trackerList=${zlt.fdfs.web-url}:22122
##### 日志链路追踪
zlt.trace.enable=true
\ No newline at end of file
zlt.trace.enable=true
##### 负载均衡隔离(version隔离,只适用于开发环境)
zlt.ribbon.isolation.enabled=true
\ No newline at end of file
package com.central.gateway.filter.pre;
import cn.hutool.core.util.StrUtil;
import com.central.common.constant.CommonConstant;
import com.central.common.constant.ConfigConstants;
import com.central.common.context.LbIsolationContextHolder;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
/**
* 保存负载均衡隔离值
*
* @author zlt
* @date 2019/8/13
*/
@Component
public class LbIsolationFilter extends ZuulFilter {
@Value("${" + ConfigConstants.CONFIG_RIBBON_ISOLATION_ENABLED + ":false}")
private boolean enableIsolation;
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
//根据配置控制是否开启过滤器
return enableIsolation;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
String version = ctx.getRequest().getHeader(CommonConstant.Z_L_T_VERSION);
if (StrUtil.isNotEmpty(version)) {
LbIsolationContextHolder.setVersion(version);
} else {
LbIsolationContextHolder.clear();
}
return null;
}
}
......@@ -105,6 +105,10 @@ layui.define(['config', 'layer'], function (exports) {
xhr.setRequestHeader('Authorization', 'bearer ' + token.access_token);
}
}
let isolationVersion = config.isolationVersion;
if (isolationVersion) {
xhr.setRequestHeader('z-l-t-version', isolationVersion);
}
}
});
},
......
......@@ -19,6 +19,7 @@ layui.define(function (exports) {
base_server: apiUrl,
tableName: 'easyweb', // 存储表名
clientId: 'webApp', // 应用id
isolationVersion: '', // 隔离版本
clientSecret: 'webApp', // 应用秘钥
autoRender: false, // 窗口大小改变后是否自动重新渲染表格,解决layui数据表格非响应式的问题,目前实现的还不是很好,暂时关闭该功能
pageTabs: true, // 是否开启多标签
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册