Skip to content

[Bug] MeshRuleRouter applies AND semantics to VirtualService match alternatives #16376

Description

@yin-bo-Final

Pre-check

  • I am sure that all the content I provide is in English.

Search before asking

  • I had searched in the issues and found no similar issues.

Apache Dubbo Component

Java SDK (apache/dubbo)

Dubbo Version

Apache Dubbo Java 3.3.7-SNAPSHOT (3.3 branch, commit c91027d), OpenJDK 17, Ubuntu 22.04

Steps to reproduce this issue

While reviewing the mesh routing logic, I noticed that MeshRuleRouter uses allMatch when evaluating the match list of a DubboRouteDetail.

Add the following regression test to MeshRuleRouterTest:

@Test
void routeDetailShouldMatchWhenAnyRequestMatches()
        throws ReflectiveOperationException {
    StandardMeshRuleRouter<Object> router =
            new StandardMeshRuleRouter<>(
                    url.addParameter("trafficLabel", "gray"));

    Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
    Map<String, Object> rule = yaml.load(
            "routedetail:\n"
                    + "  - match:\n"
                    + "      - sourceLabels: {trafficLabel: blue}\n"
                    + "      - sourceLabels: {trafficLabel: gray}\n"
                    + "    route:\n"
                    + "      - destination: {host: demo, subset: gray}\n");

    DubboRoute dubboRoute =
            PojoUtils.mapToPojo(rule, DubboRoute.class);

    assertNotNull(
            router.getDubboRouteDestination(
                    dubboRoute, new RpcInvocation()));
}

The required additional imports are:

import org.apache.dubbo.common.utils.PojoUtils;
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.DubboRoute;

import static org.junit.jupiter.api.Assertions.assertNotNull;

Run the test:

./mvnw -pl dubbo-cluster \
  -Dtest=MeshRuleRouterTest#routeDetailShouldMatchWhenAnyRequestMatches \
  test

The test currently fails because getDubboRouteDestination returns null.

What you expected to happen

The route detail should match when any entry in the match list matches the request.

In this example, the first alternative (trafficLabel=blue) does not match, but the second alternative (trafficLabel=gray) does. Therefore, the configured route destination should be returned.

Conditions inside a single match entry should use AND semantics, while multiple entries in the match list should use OR semantics.

However, the current implementation uses allMatch, so it requires both mutually exclusive alternatives to match at the same time.

Anything else

The current implementation is:

if (matchRequestList.stream()
        .allMatch(request ->
                request.isMatch(
                        invocation,
                        sourcesLabels,
                        tracingContextProviders))) {
    return dubboRouteDetail.getRoute();
}

Dubbo's mesh routing documentation states that its VirtualService semantics are based on and almost identical to Istio VirtualService. Istio defines conditions inside one match block as AND, while the list of match blocks uses OR semantics.

Do you have a (mini) reproduction demo?

  • Yes, I have a minimal reproduction demo to help resolve this issue more effectively!

Are you willing to submit a pull request to fix on your own?

  • Yes I am willing to submit a pull request on my own!

Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    type/bugBugs to being fixed

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions