美文网首页spring cloud gateway
spring cloud gateway中predicate、f

spring cloud gateway中predicate、f

作者: virtual灬zzZ | 来源:发表于2021-10-28 15:01 被阅读0次

以下是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;
    }

还有一点需要注意的就是,PredicateDefinition里面的Map<String, String> args,所以就是说一对key-value,代表每个属性只能配置单次,比如weight.group: group1,如果需要多次用到某一个predicate,就需要定义多次,当然这里的weight不需要多次,但是query可能要多次,如果有这方面的需求,这时候只能配置多次了。

相关文章

网友评论

    本文标题:spring cloud gateway中predicate、f

    本文链接:https://www.haomeiwen.com/subject/kphvaltx.html