public static <T> MeshRuleCache<T> build(
            String protocolServiceKey,
            BitList<Invoker<T>> invokers,
            Map<String, VsDestinationGroup> vsDestinationGroupMap) {
        if (CollectionUtils.isNotEmptyMap(vsDestinationGroupMap)) {
            BitList<Invoker<T>> unmatchedInvokers = new BitList<>(invokers.getOriginList(), true);
            Map<String, Map<String, BitList<Invoker<T>>>> totalSubsetMap = new HashMap<>();

            for (Invoker<T> invoker : invokers) {
                String remoteApplication = invoker.getUrl().getRemoteApplication();
                if (StringUtils.isEmpty(remoteApplication) || INVALID_APP_NAME.equals(remoteApplication)) {
                    unmatchedInvokers.add(invoker);
                    continue;
                }
                VsDestinationGroup vsDestinationGroup = vsDestinationGroupMap.get(remoteApplication);
                if (vsDestinationGroup == null) {
                    unmatchedInvokers.add(invoker);
                    continue;
                }
                Map<String, BitList<Invoker<T>>> subsetMap =
                        totalSubsetMap.computeIfAbsent(remoteApplication, (k) -> new HashMap<>());

                boolean matched = false;
                for (DestinationRule destinationRule : vsDestinationGroup.getDestinationRuleList()) {
                    DestinationRuleSpec destinationRuleSpec = destinationRule.getSpec();
                    List<Subset> subsetList = destinationRuleSpec.getSubsets();
                    for (Subset subset : subsetList) {
                        String subsetName = subset.getName();
                        List<Invoker<T>> subsetInvokers = subsetMap.computeIfAbsent(
                                subsetName, (k) -> new BitList<>(invokers.getOriginList(), true));

                        Map<String, String> labels = subset.getLabels();
                        if (isLabelMatch(invoker.getUrl(), protocolServiceKey, labels)) {
                            subsetInvokers.add(invoker);
                            matched = true;
                        }
                    }
                }
                if (!matched) {
                    unmatchedInvokers.add(invoker);
                }
            }

            return new MeshRuleCache<>(
                    new LinkedList<>(vsDestinationGroupMap.keySet()),
                    Collections.unmodifiableMap(vsDestinationGroupMap),
                    Collections.unmodifiableMap(totalSubsetMap),
                    unmatchedInvokers);
        } else {
            return new MeshRuleCache<>(
                    Collections.emptyList(), Collections.emptyMap(), Collections.emptyMap(), invokers);
        }
    }
@Test
    void testBuild() {
        BitList<Invoker<Object>> invokers =
                new BitList<>(Arrays.asList(createInvoker(""), createInvoker("unknown"), createInvoker("app1")));

        Subset subset = new Subset();
        subset.setName("TestSubset");
        DestinationRule destinationRule = new DestinationRule();
        DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec();
        destinationRuleSpec.setSubsets(Collections.singletonList(subset));
        destinationRule.setSpec(destinationRuleSpec);
        VsDestinationGroup vsDestinationGroup = new VsDestinationGroup();
        vsDestinationGroup.getDestinationRuleList().add(destinationRule);
        Map<String, VsDestinationGroup> vsDestinationGroupMap = new HashMap<>();
        vsDestinationGroupMap.put("app1", vsDestinationGroup);

        MeshRuleCache<Object> cache = MeshRuleCache.build("test", invokers, vsDestinationGroupMap);
        assertEquals(2, cache.getUnmatchedInvokers().size());
        assertEquals(1, cache.getSubsetInvokers("app1", "TestSubset").size());

        subset.setLabels(Collections.singletonMap("test", "test"));
        cache = MeshRuleCache.build("test", invokers, vsDestinationGroupMap);
        assertEquals(3, cache.getUnmatchedInvokers().size());
        assertEquals(0, cache.getSubsetInvokers("app1", "TestSubset").size());

        invokers = new BitList<>(Arrays.asList(
                createInvoker(""), createInvoker("unknown"), createInvoker("app1"), createInvoker("app2")));
        subset.setLabels(null);
        cache = MeshRuleCache.build("test", invokers, vsDestinationGroupMap);
        assertEquals(3, cache.getUnmatchedInvokers().size());
        assertEquals(1, cache.getSubsetInvokers("app1", "TestSubset").size());
        assertEquals(0, cache.getSubsetInvokers("app2", "TestSubset").size());
    }