Skip to content

Commit 5fdc88d

Browse files
authored
Fix tri convert upper header (#11075)
1 parent b1ae0de commit 5fdc88d

File tree

3 files changed

+106
-18
lines changed

3 files changed

+106
-18
lines changed

dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHeaderEnum.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
import org.apache.dubbo.common.constants.CommonConstants;
2121

22+
import io.netty.handler.codec.http2.Http2Headers;
23+
2224
import java.util.HashMap;
2325
import java.util.HashSet;
2426
import java.util.Map;
@@ -61,6 +63,11 @@ public enum TripleHeaderEnum {
6163
excludeAttachmentsSet.add(CommonConstants.APPLICATION_KEY);
6264
excludeAttachmentsSet.add(TripleConstant.SERIALIZATION_KEY);
6365
excludeAttachmentsSet.add(TripleConstant.TE_KEY);
66+
67+
for (Http2Headers.PseudoHeaderName value : Http2Headers.PseudoHeaderName.values()) {
68+
excludeAttachmentsSet.add(value.value().toString());
69+
}
70+
6471
}
6572

6673
private final String header;

dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/stream/StreamUtils.java

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,19 @@
2020
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
2121
import org.apache.dubbo.common.logger.LoggerFactory;
2222
import org.apache.dubbo.common.utils.JsonUtils;
23+
import org.apache.dubbo.common.utils.LRU2Cache;
2324
import org.apache.dubbo.rpc.TriRpcStatus;
2425
import org.apache.dubbo.rpc.protocol.tri.TripleConstant;
2526
import org.apache.dubbo.rpc.protocol.tri.TripleHeaderEnum;
2627

2728
import io.netty.handler.codec.http2.DefaultHttp2Headers;
28-
import io.netty.handler.codec.http2.Http2Headers;
2929

3030
import java.nio.charset.StandardCharsets;
3131
import java.util.Base64;
3232
import java.util.Collections;
3333
import java.util.HashMap;
3434
import java.util.Locale;
3535
import java.util.Map;
36-
import java.util.stream.Collectors;
3736

3837
import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_UNSUPPORTED;
3938

@@ -44,6 +43,11 @@ public class StreamUtils {
4443
private static final Base64.Decoder BASE64_DECODER = Base64.getDecoder();
4544
private static final Base64.Encoder BASE64_ENCODER = Base64.getEncoder().withoutPadding();
4645

46+
47+
private static final int MAX_LRU_HEADER_MAP_SIZE = 10000;
48+
49+
private static final Map<String, String> lruHeaderMap = new LRU2Cache<>(MAX_LRU_HEADER_MAP_SIZE);
50+
4751
public static String encodeBase64ASCII(byte[] in) {
4852
byte[] bytes = encodeBase64(in);
4953
return new String(bytes, StandardCharsets.US_ASCII);
@@ -63,9 +67,6 @@ public static Map<String, Object> toAttachments(Map<String, Object> origin) {
6367
}
6468
Map<String, Object> res = new HashMap<>(origin.size());
6569
origin.forEach((k, v) -> {
66-
if (Http2Headers.PseudoHeaderName.isPseudoHeader(k)) {
67-
return;
68-
}
6970
if (TripleHeaderEnum.containsExcludeAttachments(k)) {
7071
return;
7172
}
@@ -88,27 +89,26 @@ public static void convertAttachment(DefaultHttp2Headers headers,
8889
if (attachments == null) {
8990
return;
9091
}
91-
92+
Map<String, String> needConvertKey = new HashMap<>();
9293
for (Map.Entry<String, Object> entry : attachments.entrySet()) {
93-
final String key = entry.getKey().toLowerCase(Locale.ROOT);
94-
if (Http2Headers.PseudoHeaderName.isPseudoHeader(key)) {
95-
continue;
94+
String key = lruHeaderMap.get(entry.getKey());
95+
if (key == null) {
96+
final String lowerCaseKey = entry.getKey().toLowerCase(Locale.ROOT);
97+
lruHeaderMap.put(entry.getKey(), lowerCaseKey);
98+
key = lowerCaseKey;
9699
}
97100
if (TripleHeaderEnum.containsExcludeAttachments(key)) {
98101
continue;
99102
}
103+
if (needConvertHeaderKey && !key.equals(entry.getKey())) {
104+
needConvertKey.put(key, entry.getKey());
105+
}
100106
final Object v = entry.getValue();
101107
convertSingleAttachment(headers, key, v);
102108
}
103-
if (needConvertHeaderKey) {
104-
Map<String, String> needConvertKey = attachments.entrySet()
105-
.stream()
106-
.filter(it -> !headers.contains(it.getKey()))
107-
.collect(Collectors.toMap(Map.Entry::getKey, it -> it.getKey().toLowerCase(Locale.ROOT)));
108-
if (!needConvertKey.isEmpty()) {
109-
String needConvertJson = JsonUtils.getJson().toJson(needConvertKey);
110-
headers.add(TripleHeaderEnum.TRI_HEADER_CONVERT.getHeader(), TriRpcStatus.encodeMessage(needConvertJson));
111-
}
109+
if (!needConvertKey.isEmpty()) {
110+
String needConvertJson = JsonUtils.getJson().toJson(needConvertKey);
111+
headers.add(TripleHeaderEnum.TRI_HEADER_CONVERT.getHeader(), TriRpcStatus.encodeMessage(needConvertJson));
112112
}
113113
}
114114

dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/stream/StreamUtilsTest.java

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,99 @@
1717

1818
package org.apache.dubbo.rpc.protocol.tri.stream;
1919

20+
import org.apache.dubbo.common.utils.JsonUtils;
21+
import org.apache.dubbo.rpc.TriRpcStatus;
22+
import org.apache.dubbo.rpc.protocol.tri.TripleHeaderEnum;
23+
24+
import io.netty.handler.codec.http2.DefaultHttp2Headers;
2025
import org.junit.jupiter.api.Assertions;
2126
import org.junit.jupiter.api.Test;
2227

2328
import java.nio.charset.StandardCharsets;
29+
import java.util.HashMap;
30+
import java.util.Map;
31+
import java.util.concurrent.CountDownLatch;
32+
import java.util.concurrent.ExecutorService;
33+
import java.util.concurrent.Executors;
34+
import java.util.concurrent.TimeUnit;
2435

2536
class StreamUtilsTest {
2637

38+
2739
@Test
2840
void encodeBase64ASCII() {
2941
String content = "😯";
3042
Assertions.assertArrayEquals(content.getBytes(StandardCharsets.UTF_8),
3143
StreamUtils.decodeASCIIByte(StreamUtils.encodeBase64ASCII(content.getBytes(
3244
StandardCharsets.UTF_8))));
3345
}
46+
47+
@Test
48+
void testConvertAttachment() throws InterruptedException {
49+
ExecutorService executorService = Executors.newFixedThreadPool(10);
50+
51+
DefaultHttp2Headers headers = new DefaultHttp2Headers();
52+
headers.add("key", "value");
53+
54+
Map<String, Object> attachments = new HashMap<>();
55+
attachments.put(TripleHeaderEnum.PATH_KEY.getHeader(), "value");
56+
attachments.put("key1111", "value");
57+
attachments.put("Upper", "Upper");
58+
attachments.put("obj", new Object());
59+
60+
StreamUtils.convertAttachment(headers, attachments, false);
61+
Assertions.assertNull(headers.get(TripleHeaderEnum.PATH_KEY.getHeader()));
62+
Assertions.assertNull(headers.get("Upper"));
63+
Assertions.assertNull(headers.get("obj"));
64+
65+
headers = new DefaultHttp2Headers();
66+
headers.add("key", "value");
67+
68+
StreamUtils.convertAttachment(headers, attachments, true);
69+
Assertions.assertNull(headers.get(TripleHeaderEnum.PATH_KEY.getHeader()));
70+
Assertions.assertNull(headers.get("Upper"));
71+
Assertions.assertNull(headers.get("obj"));
72+
String jsonRaw = headers.get(TripleHeaderEnum.TRI_HEADER_CONVERT.getHeader()).toString();
73+
String json = TriRpcStatus.decodeMessage(jsonRaw);
74+
System.out.println(jsonRaw + "---" + json);
75+
Map<String, String> upperMap = JsonUtils.getJson().toJavaObject(json, Map.class);
76+
Assertions.assertArrayEquals("Upper".getBytes(StandardCharsets.UTF_8), upperMap.get("upper").getBytes(StandardCharsets.UTF_8));
77+
78+
int count = 10000;
79+
CountDownLatch latch = new CountDownLatch(count);
80+
for (int i = 0; i < count; i++) {
81+
String randomKey = "key" + i;
82+
String randomValue = "value" + i;
83+
Map<String, Object> attachments2 = new HashMap<>();
84+
attachments2.put(TripleHeaderEnum.PATH_KEY.getHeader(), "value");
85+
attachments2.put("key1111", "value");
86+
attachments2.put("Upper", "Upper");
87+
attachments2.put("obj", new Object());
88+
attachments2.put(randomKey, randomValue);
89+
executorService.execute(() -> {
90+
DefaultHttp2Headers headers2 = new DefaultHttp2Headers();
91+
headers2.add("key", "value");
92+
StreamUtils.convertAttachment(headers2, attachments2, true);
93+
94+
if (headers2.get(TripleHeaderEnum.PATH_KEY.getHeader()) != null) {
95+
return;
96+
}
97+
if (headers2.get("Upper") != null) {
98+
return;
99+
}
100+
if (headers2.get("obj") != null) {
101+
return;
102+
}
103+
if (!headers2.get(randomKey).toString().equals(randomValue)) {
104+
return;
105+
}
106+
latch.countDown();
107+
});
108+
}
109+
latch.await(10, TimeUnit.SECONDS);
110+
Assertions.assertEquals(0, latch.getCount());
111+
executorService.shutdown();
112+
}
113+
114+
34115
}

0 commit comments

Comments
 (0)