单元化部署(开发指南)
最近更新时间: 2024-10-17 17:10:00
操作场景
TSF 支持使用单元化功能以达到让不同的业务流量根据一定的单元化规则分发到指定的单元里,不同单元之间通过微服务网关实现跨单元调用,当某个单元内的服务器实例出现问题时也不会影响到其他单元业务的使用,使得业务受影响粒度达到最小,同时单元化也为业务容灾高可用提供了强有力的保障。
注意:
单元化网关支持跨命名空间调用,单元化配置仅支持部署在全局命名空间下的网关。
从1.28.0版本开始,TSF 微服务网关 SDK 支持提供基于 Zuul 的单元化功能。
微服务网关要么是单元化网关,要么是非单元化网关,开启了单元化的功能,该网关就是单元化网关,否则就是非单元化网关。
前提条件
开始实践单元化功能前,请确保已完成了【SDK 下载】,同时请确保 SDK 版本高于1.28。
操作步骤
先暴露 Provider 服务接口,然后将单元化规则配置在调用方 Consumer 工程或微服务网关工程里面。
一、配置Consumer 工程或者微服务网关工程
Consumer 工程
1. 向 Consumer 工程中添加依赖
在 pom.xml
中添加以下代码:
<dependency>
<groupId>com.tencent.tsf</groupId>
<artifactId>spring-cloud-tsf-starter</artifactId>
<version><!-- 调整为 SDK 最新版本号 --></version>
</dependency>
2. 向 Application 类中添加注解 @EnableTsf
和@ComponentScan
// 下面省略了无关的代码
@SpringBootApplication
@EnableTsf
@EnableFeignClients // 使用Feign微服务调用时请启用
@ComponentScan(basePackages="com.tsf.demo.consumer.*") // 需要扫描单元化@TsfUnitRule注解所在的包
public class ConsumerApplication {
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(ConsumerApplication.class, args);
}
}
3. 配置单元化规则
Feign调用
- 使用
@TsfUnitRule
配置单元化规则。
@FeignClient(name = "provider-demo")
public interface ProviderDemoService {
@TsfUnitRule(ruleGenerator = "com.tsf.demo.consumer.util.UserIdGenerator")
@RequestMapping(value = "/echo/unit/{str}", method = RequestMethod.GET)
String echoUnit(@PathVariable("str") String str);
}
- 在代码中编写单元化规则。
需要编写一个类实现接口TsfUnitRuleGenerator的方法generateRule,计算出单元化规则的tag标签值,该类就是步骤3中
@TsfUnitRule
的ruleGenerator属性指定的类。
// 下面省略了无关的代码
public class UserIdGenerator implements TsfUnitRuleGenerator {
@Override
public Map<String, String> generateRule(Method method, Object[] args) {
String userId = (String)args[0];
Map<String, String> ruleMap = new HashMap<>();
// 添加单元化规则的tag key
ruleMap.put("userId", userId);
return ruleMap;
}
}
可以看到,TSF 的单元化功能针对Feign调用只需在需要单元化的类或方法上增加一个注解并添加对应的单元化规则即可(需要该 Bean 类被 Spring 所管理)。
注意:
注解
@TsfUnitRule
支持配置在类上,也支持配置在方法上。如果是配置在类上,则单元化规则对该类所有的方法都生效。
RestTemplate调用
在 Consumer 中设置 tag ,使用com.tencent.tsf.unit包中的TsfUnitContext类,设置单元化 Tag 的方法
@RequestMapping(value = "/echo-rest-unit/{str}", method = RequestMethod.GET)
public String restUnit(@PathVariable String str,
@RequestParam(required = false) String tagName,
@RequestParam(required = false) String tagValue) {
if (!StringUtils.isEmpty(tagName)) {
// 添加单元化规则tag key和value
TsfUnitContext.putTag(tagName, tagValue);
}
return restTemplate.getForObject("http://provider-demo/echo/unit/" + str, String.class);
}
注意:
设置单元化规则的tag类是com.tencent.tsf.unit.TsfUnitContext,不是org.springframework.tsf.core.TsfContext。
微服务网关工程
开始实践微服务网关单元化功能之前,请确保您已完成 [微服务网关 SDK 使用指南]。
向自定义网关过滤器 Filter 类中添加 tag 标签:
// 下面省略了无关的代码
import com.tencent.tsf.gateway.core.annotation.TsfGatewayFilter;
import com.tencent.tsf.unit.TsfUnitContext;
@TsfGatewayFilter
public class TestFilter extends TsfGatewayZuulFilter {
private Logger logger = LoggerFactory.getLogger(TestFilter.class);
@Override
public String filterType() {
return PRE_TYPE;
}
@Override
public int filterOrder() {
// 注:设置 putTag 的filter的order必须在ZUUL_UNIT_ORDER之前
return TsfGatewayFilterOrderConstants.ZUUL_UNIT_ORDER - 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
// 单元化场景的putTag操作
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String userId = request.getHeader("userId");
if(StringUtils.isNotBlank(userId)) {
logger.info("put unit tag userId:{}", userId);
TsfUnitContext.putTag("userId", userId);
}
System.out.println("hello world");
logger.info("hello world");
return null;
}
}
使用包 com.tencent.tsf.unit 下的类 TsfUnitContext 的方法 putTag 来设置单元化标签
自定义设置 putTag 的 Filter 的顺序必须在 TsfGatewayFilterOrderConstants.ZUUL_UNIT_ORDER 之前
开启单元化功能并创建单元化规则
在TSF控制台开启单元化功能并创建单元化规则,详细操作参考【单元化部署】。