以下是gateway的配置demo:
spring:
cloud:
gateway:
routes: #配置路由
- id: consumer_low
uri: http://192.168.1.106:8000
predicates:
- Path=/cs/**
- Weight=group1,2
filters: # 网关过滤器
- StripPrefix=1
- id: consumer_high
uri: http://192.168.1.106:8001
predicates:
- name: Path
args:
patterns: /cs/**
- name: Weight
args:
weight.group: group1
weight.weight: 8
filters:
- name: StripPrefix
args:
parts: 1
consumer_low、consumer_high 所以对应的微服务都是同一个,地址各自是http://192.168.1.106:8000,http://192.168.1.106:8001,现在是设置权重的模拟测试,它们分别使用简写和全写。
predicate和filter的全写和简写,原理是一模一样的,看他们的defination就知道。
@Validated
public class PredicateDefinition {
@NotNull
private String name;
private Map<String, String> args = new LinkedHashMap<>();
public PredicateDefinition() {
}
public PredicateDefinition(String text) {
int eqIdx = text.indexOf('=');
if (eqIdx <= 0) {
throw new ValidationException("Unable to parse PredicateDefinition text '"
+ text + "'" + ", must be of the form name=value");
}
setName(text.substring(0, eqIdx));
String[] args = tokenizeToStringArray(text.substring(eqIdx + 1), ",");
for (int i = 0; i < args.length; i++) {
this.args.put(NameUtils.generateName(i), args[i]);
}
}
后续略
@Validated
public class FilterDefinition {
@NotNull
private String name;
private Map<String, String> args = new LinkedHashMap<>();
public FilterDefinition() {
}
public FilterDefinition(String text) {
int eqIdx = text.indexOf('=');
if (eqIdx <= 0) {
setName(text);
return;
}
setName(text.substring(0, eqIdx));
String[] args = tokenizeToStringArray(text.substring(eqIdx + 1), ",");
for (int i = 0; i < args.length; i++) {
this.args.put(NameUtils.generateName(i), args[i]);
}
}
后续略
它们都是name+args。这篇文章已经说了详情,defination和factory的联系https://www.jianshu.com/p/e171a289bbb2
这里主要讲写法的要点,用predicate举例,filter同理。
简写:
predicates:
- Path=/cs/**
- Weight=group1,2
- Path=/cs/** 这样就是一个defination对象,Path就是name,/cs/**就是args
全写:
严格按照定义的写法,
predicates:
- name: Path
args:
patterns: /cs/**
- name: Weight
args:
weight.group: group1
weight.weight: 8
name的话无悬念,关键是args,args我们得严格按照该predicate定义的来写,比如说,权重:
public class WeightRoutePredicateFactory
extends AbstractRoutePredicateFactory<WeightConfig>
implements ApplicationEventPublisherAware {
/**
* Weight config group key.
*/
public static final String GROUP_KEY = WeightConfig.CONFIG_PREFIX + ".group";
/**
* Weight config weight key.
*/
public static final String WEIGHT_KEY = WeightConfig.CONFIG_PREFIX + ".weight";
private static final Log log = LogFactory.getLog(WeightRoutePredicateFactory.class);
private ApplicationEventPublisher publisher;
public WeightRoutePredicateFactory() {
super(WeightConfig.class);
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList(GROUP_KEY, WEIGHT_KEY);
}
@Override
public String shortcutFieldPrefix() {
return WeightConfig.CONFIG_PREFIX;
}
@Override
public void beforeApply(WeightConfig config) {
if (publisher != null) {
publisher.publishEvent(new WeightDefinedEvent(this, config));
}
}
@Override
public Predicate<ServerWebExchange> apply(WeightConfig config) {
return new GatewayPredicate() {
@Override
public boolean test(ServerWebExchange exchange) {
Map<String, String> weights = exchange.getAttributeOrDefault(WEIGHT_ATTR,
Collections.emptyMap());
String routeId = exchange.getAttribute(GATEWAY_PREDICATE_ROUTE_ATTR);
// all calculations and comparison against random num happened in
// WeightCalculatorWebFilter
String group = config.getGroup();
if (weights.containsKey(group)) {
String chosenRoute = weights.get(group);
if (log.isTraceEnabled()) {
log.trace("in group weight: " + group + ", current route: "
+ routeId + ", chosen route: " + chosenRoute);
}
return routeId.equals(chosenRoute);
}
else if (log.isTraceEnabled()) {
log.trace("no weights found for group: " + group + ", current route: "
+ routeId);
}
return false;
}
@Override
public String toString() {
return String.format("Weight: %s %s", config.getGroup(),
config.getWeight());
}
};
}
}
@Validated
public class WeightConfig {
/**
* Configuration prefix for {@link WeightConfig}.
*/
public static final String CONFIG_PREFIX = "weight";
@NotEmpty
private String group;
private String routeId;
@Min(0)
private int weight;
private WeightConfig() {
}
public WeightConfig(String group, String routeId, int weight) {
this.routeId = routeId;
this.group = group;
this.weight = weight;
}
public WeightConfig(String routeId) {
this.routeId = routeId;
}
public String getGroup() {
return group;
}
public WeightConfig setGroup(String group) {
this.group = group;
return this;
}
public String getRouteId() {
return routeId;
}
public WeightConfig setRouteId(String routeId) {
this.routeId = routeId;
return this;
}
public int getWeight() {
return weight;
}
public WeightConfig setWeight(int weight) {
this.weight = weight;
return this;
}
@Override
public String toString() {
return new ToStringCreator(this).append("group", group).append("routeId", routeId)
.append("weight", weight).toString();
}
}
它的GROUP_KEY,WEIGHT_KEY,就是Config里面的group,weight,展示出来的参数要按照shortcutFieldOrder方法里头的字段,有前缀是因为shortcutFieldPrefix,所以它得全写,
args:
weight.group: group1
weight.weight: 8
其实一般的话,predicateFactory和Config基本是一致的,展示出来的参数要按照shortcutFieldOrder方法里头的字段,但是有个别是特殊,比如权重,这是必须是按照predicateFactory的,因为仔细看WeightRoutePredicateFactory,有个方法就是为WebConfig的参数提供前缀的,所以务必注意,有shortcutFieldPrefix方法的必须按照其配置前缀。
@Override
public String shortcutFieldPrefix() {
return WeightConfig.CONFIG_PREFIX;
}
网友评论