|
18 | 18 | */ |
19 | 19 | package org.apache.pulsar.broker.loadbalance.extensions.models; |
20 | 20 |
|
| 21 | +import static org.mockito.ArgumentMatchers.eq; |
| 22 | +import static org.mockito.ArgumentMatchers.any; |
| 23 | +import static org.mockito.Mockito.doReturn; |
| 24 | +import static org.mockito.Mockito.mock; |
21 | 25 | import static org.testng.Assert.assertEquals; |
22 | 26 | import static org.testng.Assert.assertNull; |
23 | | -import static org.testng.Assert.assertTrue; |
24 | 27 | import java.util.ArrayList; |
25 | 28 | import java.util.Collections; |
26 | 29 | import java.util.HashMap; |
27 | 30 | import java.util.List; |
28 | 31 | import java.util.Map; |
| 32 | +import java.util.Optional; |
29 | 33 | import java.util.Random; |
| 34 | +import org.apache.pulsar.broker.PulsarService; |
| 35 | +import org.apache.pulsar.broker.ServiceConfiguration; |
| 36 | +import org.apache.pulsar.broker.loadbalance.impl.LoadManagerShared; |
| 37 | +import org.apache.pulsar.broker.resources.LocalPoliciesResources; |
| 38 | +import org.apache.pulsar.broker.resources.NamespaceResources; |
| 39 | +import org.apache.pulsar.broker.resources.PulsarResources; |
| 40 | +import org.apache.pulsar.common.naming.NamespaceName; |
| 41 | +import org.apache.pulsar.common.policies.data.AutoFailoverPolicyData; |
| 42 | +import org.apache.pulsar.common.policies.data.AutoFailoverPolicyType; |
| 43 | +import org.apache.pulsar.common.policies.data.LocalPolicies; |
| 44 | +import org.apache.pulsar.common.policies.data.NamespaceIsolationData; |
| 45 | +import org.apache.pulsar.common.policies.data.NamespaceIsolationDataImpl; |
| 46 | +import org.apache.pulsar.common.policies.impl.NamespaceIsolationPolicies; |
| 47 | +import org.apache.pulsar.metadata.api.MetadataStoreException; |
30 | 48 | import org.apache.pulsar.policies.data.loadbalancer.NamespaceBundleStats; |
| 49 | +import org.testng.annotations.BeforeMethod; |
31 | 50 | import org.testng.annotations.Test; |
32 | 51 |
|
33 | 52 | @Test(groups = "broker") |
34 | 53 | public class TopKBundlesTest { |
| 54 | + private PulsarService pulsar; |
| 55 | + private ServiceConfiguration configuration; |
| 56 | + private NamespaceResources.IsolationPolicyResources isolationPolicyResources; |
| 57 | + private PulsarResources pulsarResources; |
| 58 | + private LocalPoliciesResources localPoliciesResources; |
35 | 59 |
|
| 60 | + String bundle1 = "my-tenant/my-namespace1/0x00000000_0x0FFFFFFF"; |
| 61 | + String bundle2 = "my-tenant/my-namespace2/0x00000000_0x0FFFFFFF"; |
| 62 | + String bundle3 = "my-tenant/my-namespace3/0x00000000_0x0FFFFFFF"; |
| 63 | + String bundle4 = "my-tenant/my-namespace4/0x00000000_0x0FFFFFFF"; |
| 64 | + |
| 65 | + @BeforeMethod |
| 66 | + public void init() throws MetadataStoreException { |
| 67 | + pulsar = mock(PulsarService.class); |
| 68 | + configuration = new ServiceConfiguration(); |
| 69 | + doReturn(configuration).when(pulsar).getConfiguration(); |
| 70 | + configuration.setLoadBalancerSheddingBundlesWithPoliciesEnabled(false); |
| 71 | + pulsarResources = mock(PulsarResources.class); |
| 72 | + var namespaceResources = mock(NamespaceResources.class); |
| 73 | + |
| 74 | + isolationPolicyResources = mock(NamespaceResources.IsolationPolicyResources.class); |
| 75 | + doReturn(pulsarResources).when(pulsar).getPulsarResources(); |
| 76 | + doReturn(namespaceResources).when(pulsarResources).getNamespaceResources(); |
| 77 | + doReturn(isolationPolicyResources).when(namespaceResources).getIsolationPolicies(); |
| 78 | + doReturn(Optional.empty()).when(isolationPolicyResources).getIsolationDataPolicies(any()); |
| 79 | + |
| 80 | + localPoliciesResources = mock(LocalPoliciesResources.class); |
| 81 | + doReturn(localPoliciesResources).when(pulsarResources).getLocalPolicies(); |
| 82 | + doReturn(Optional.empty()).when(localPoliciesResources).getLocalPolicies(any()); |
| 83 | + |
| 84 | + } |
36 | 85 | @Test |
37 | 86 | public void testTopBundlesLoadData() { |
38 | 87 | Map<String, NamespaceBundleStats> bundleStats = new HashMap<>(); |
39 | | - var topKBundles = new TopKBundles(); |
| 88 | + var topKBundles = new TopKBundles(pulsar); |
40 | 89 | NamespaceBundleStats stats1 = new NamespaceBundleStats(); |
41 | 90 | stats1.msgRateIn = 500; |
42 | | - bundleStats.put("bundle-1", stats1); |
| 91 | + bundleStats.put(bundle1, stats1); |
43 | 92 |
|
44 | 93 | NamespaceBundleStats stats2 = new NamespaceBundleStats(); |
45 | 94 | stats2.msgRateIn = 10000; |
46 | | - bundleStats.put("bundle-2", stats2); |
| 95 | + bundleStats.put(bundle2, stats2); |
47 | 96 |
|
48 | 97 | NamespaceBundleStats stats3 = new NamespaceBundleStats(); |
49 | 98 | stats3.msgRateIn = 100000; |
50 | | - bundleStats.put("bundle-3", stats3); |
| 99 | + bundleStats.put(bundle3, stats3); |
51 | 100 |
|
52 | 101 | NamespaceBundleStats stats4 = new NamespaceBundleStats(); |
53 | 102 | stats4.msgRateIn = 0; |
54 | | - bundleStats.put("bundle-4", stats4); |
| 103 | + bundleStats.put(bundle4, stats4); |
55 | 104 |
|
56 | 105 | topKBundles.update(bundleStats, 3); |
57 | 106 | var top0 = topKBundles.getLoadData().getTopBundlesLoadData().get(0); |
58 | 107 | var top1 = topKBundles.getLoadData().getTopBundlesLoadData().get(1); |
59 | 108 | var top2 = topKBundles.getLoadData().getTopBundlesLoadData().get(2); |
60 | 109 |
|
61 | | - assertEquals(top0.bundleName(), "bundle-3"); |
62 | | - assertEquals(top1.bundleName(), "bundle-2"); |
63 | | - assertEquals(top2.bundleName(), "bundle-1"); |
| 110 | + assertEquals(top0.bundleName(), bundle3); |
| 111 | + assertEquals(top1.bundleName(), bundle2); |
| 112 | + assertEquals(top2.bundleName(), bundle1); |
64 | 113 | } |
65 | 114 |
|
66 | 115 | @Test |
67 | 116 | public void testSystemNamespace() { |
68 | 117 | Map<String, NamespaceBundleStats> bundleStats = new HashMap<>(); |
69 | | - var topKBundles = new TopKBundles(); |
| 118 | + var topKBundles = new TopKBundles(pulsar); |
70 | 119 | NamespaceBundleStats stats1 = new NamespaceBundleStats(); |
71 | 120 | stats1.msgRateIn = 500; |
72 | | - bundleStats.put("pulsar/system/bundle-1", stats1); |
| 121 | + bundleStats.put("pulsar/system/0x00000000_0x0FFFFFFF", stats1); |
73 | 122 |
|
74 | 123 | NamespaceBundleStats stats2 = new NamespaceBundleStats(); |
75 | 124 | stats2.msgRateIn = 10000; |
76 | | - bundleStats.put("pulsar/system/bundle-2", stats2); |
| 125 | + bundleStats.put(bundle1, stats2); |
77 | 126 |
|
78 | 127 | topKBundles.update(bundleStats, 2); |
79 | | - assertTrue(topKBundles.getLoadData().getTopBundlesLoadData().isEmpty()); |
| 128 | + |
| 129 | + assertEquals(topKBundles.getLoadData().getTopBundlesLoadData().size(), 1); |
| 130 | + var top0 = topKBundles.getLoadData().getTopBundlesLoadData().get(0); |
| 131 | + assertEquals(top0.bundleName(), bundle1); |
| 132 | + } |
| 133 | + |
| 134 | + |
| 135 | + private void setAntiAffinityGroup() throws MetadataStoreException { |
| 136 | + LocalPolicies localPolicies = new LocalPolicies(null, null, "namespaceAntiAffinityGroup"); |
| 137 | + NamespaceName namespace = NamespaceName.get(LoadManagerShared.getNamespaceNameFromBundleName(bundle2)); |
| 138 | + doReturn(Optional.of(localPolicies)).when(localPoliciesResources).getLocalPolicies(eq(namespace)); |
| 139 | + } |
| 140 | + |
| 141 | + private void setIsolationPolicy() throws MetadataStoreException { |
| 142 | + Map<String, String> parameters = new HashMap<>(); |
| 143 | + parameters.put("min_limit", "3"); |
| 144 | + parameters.put("usage_threshold", "90"); |
| 145 | + var policyData = Map.of("policy", (NamespaceIsolationDataImpl) |
| 146 | + NamespaceIsolationData.builder() |
| 147 | + .namespaces(Collections.singletonList("my-tenant/my-namespace1.*")) |
| 148 | + .primary(Collections.singletonList("prod1-broker[1-3].messaging.use.example.com")) |
| 149 | + .secondary(Collections.singletonList("prod1-broker.*.use.example.com")) |
| 150 | + .autoFailoverPolicy(AutoFailoverPolicyData.builder() |
| 151 | + .policyType(AutoFailoverPolicyType.min_available) |
| 152 | + .parameters(parameters) |
| 153 | + .build() |
| 154 | + ).build()); |
| 155 | + |
| 156 | + NamespaceIsolationPolicies policies = new NamespaceIsolationPolicies(policyData); |
| 157 | + doReturn(Optional.of(policies)).when(isolationPolicyResources).getIsolationDataPolicies(any()); |
| 158 | + } |
| 159 | + |
| 160 | + @Test |
| 161 | + public void testIsolationPolicy() throws MetadataStoreException { |
| 162 | + |
| 163 | + setIsolationPolicy(); |
| 164 | + |
| 165 | + Map<String, NamespaceBundleStats> bundleStats = new HashMap<>(); |
| 166 | + var topKBundles = new TopKBundles(pulsar); |
| 167 | + NamespaceBundleStats stats1 = new NamespaceBundleStats(); |
| 168 | + stats1.msgRateIn = 500; |
| 169 | + bundleStats.put(bundle1, stats1); |
| 170 | + |
| 171 | + NamespaceBundleStats stats2 = new NamespaceBundleStats(); |
| 172 | + stats2.msgRateIn = 10000; |
| 173 | + bundleStats.put(bundle2, stats2); |
| 174 | + |
| 175 | + topKBundles.update(bundleStats, 2); |
| 176 | + assertEquals(topKBundles.getLoadData().getTopBundlesLoadData().size(), 1); |
| 177 | + var top0 = topKBundles.getLoadData().getTopBundlesLoadData().get(0); |
| 178 | + assertEquals(top0.bundleName(), bundle2); |
| 179 | + } |
| 180 | + |
| 181 | + |
| 182 | + @Test |
| 183 | + public void testAntiAffinityGroupPolicy() throws MetadataStoreException { |
| 184 | + |
| 185 | + setAntiAffinityGroup(); |
| 186 | + |
| 187 | + Map<String, NamespaceBundleStats> bundleStats = new HashMap<>(); |
| 188 | + var topKBundles = new TopKBundles(pulsar); |
| 189 | + NamespaceBundleStats stats1 = new NamespaceBundleStats(); |
| 190 | + stats1.msgRateIn = 500; |
| 191 | + bundleStats.put(bundle1, stats1); |
| 192 | + |
| 193 | + NamespaceBundleStats stats2 = new NamespaceBundleStats(); |
| 194 | + stats2.msgRateIn = 10000; |
| 195 | + bundleStats.put(bundle2, stats2); |
| 196 | + |
| 197 | + topKBundles.update(bundleStats, 2); |
| 198 | + assertEquals(topKBundles.getLoadData().getTopBundlesLoadData().size(), 1); |
| 199 | + var top0 = topKBundles.getLoadData().getTopBundlesLoadData().get(0); |
| 200 | + assertEquals(top0.bundleName(), bundle1); |
| 201 | + |
| 202 | + } |
| 203 | + |
| 204 | + @Test |
| 205 | + public void testLoadBalancerSheddingBundlesWithPoliciesEnabledConfig() throws MetadataStoreException { |
| 206 | + |
| 207 | + setIsolationPolicy(); |
| 208 | + setAntiAffinityGroup(); |
| 209 | + |
| 210 | + configuration.setLoadBalancerSheddingBundlesWithPoliciesEnabled(true); |
| 211 | + |
| 212 | + Map<String, NamespaceBundleStats> bundleStats = new HashMap<>(); |
| 213 | + var topKBundles = new TopKBundles(pulsar); |
| 214 | + NamespaceBundleStats stats1 = new NamespaceBundleStats(); |
| 215 | + stats1.msgRateIn = 500; |
| 216 | + bundleStats.put(bundle1, stats1); |
| 217 | + |
| 218 | + NamespaceBundleStats stats2 = new NamespaceBundleStats(); |
| 219 | + stats2.msgRateIn = 10000; |
| 220 | + bundleStats.put(bundle2, stats2); |
| 221 | + |
| 222 | + topKBundles.update(bundleStats, 2); |
| 223 | + |
| 224 | + assertEquals(topKBundles.getLoadData().getTopBundlesLoadData().size(), 2); |
| 225 | + var top0 = topKBundles.getLoadData().getTopBundlesLoadData().get(0); |
| 226 | + var top1 = topKBundles.getLoadData().getTopBundlesLoadData().get(1); |
| 227 | + |
| 228 | + assertEquals(top0.bundleName(), bundle2); |
| 229 | + assertEquals(top1.bundleName(), bundle1); |
80 | 230 | } |
81 | 231 |
|
82 | 232 |
|
|
0 commit comments