Sync from bytedesk-private: update

This commit is contained in:
jack ning
2024-12-24 10:32:23 +08:00
parent 062d024743
commit 1155490db3
3 changed files with 104 additions and 93 deletions

View File

@@ -22,7 +22,7 @@ import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import com.bytedesk.core.message.MessageProtobuf;
import com.bytedesk.core.utils.JsonResult;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
@@ -41,103 +41,97 @@ public class VisitorAnonymousControllerTest {
@MockBean
private VisitorRestService visitorRestService;
// orgUid=df_org_uid
// type=0 or 1
// sid=df_ag_uid or df_wg_uid
private List<String> visitorUids;
private static final String ORG_UID = "df_org_uid";
private static final String AGENT_UID = "df_ag_uid"; // df_ag_uid or df_wg_uid
private static final String TYPE = "0";// 0: agent, 1: workgroup
private static final int VISITOR_COUNT = 100;
private static final int REQUEST_PER_VISITOR = 100;
private List<VisitorResponse> visitors;
@BeforeEach
void setUp() {
// 初始化访客ID列表
visitorUids = new ArrayList<>();
// 初始化访客列表
visitors = new ArrayList<>();
for (int i = 0; i < VISITOR_COUNT; i++) {
visitorUids.add("visitor_" + i);
VisitorResponse visitor = VisitorResponse.builder()
.nickname("Visitor " + i)
.avatar("https://example.com/avatar/" + i + ".jpg")
.build();
visitor.setUid("visitor_" + i);
visitors.add(visitor);
}
// Mock visitorService的响应
when(visitorRestService.create(any())).thenReturn(VisitorResponse.builder().build());
when(visitorRestService.requestThread(any())).thenReturn(MessageProtobuf.builder().build());
when(visitorRestService.create(any())).thenAnswer(invocation -> {
int index = (int)(Math.random() * VISITOR_COUNT);
return visitors.get(index);
});
}
@Test
void testMassVisitorRequests() throws Exception {
// 1. 首先创建100个访客
log.info("开始创建{}个访客", VISITOR_COUNT);
createVisitors();
// 2. 每个访客发起100次请求
log.info("开始模拟每个访客发起{}次请求", REQUEST_PER_VISITOR);
simulateVisitorRequests();
// 3. 验证调用次数
verify(visitorRestService, times(VISITOR_COUNT)).create(any());
verify(visitorRestService, times(VISITOR_COUNT * REQUEST_PER_VISITOR)).requestThread(any());
}
private void createVisitors() throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(10);
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (String visitorUid : visitorUids) {
// 创建访客
for (int i = 0; i < VISITOR_COUNT; i++) {
final int visitorIndex = i;
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
VisitorRequest request = new VisitorRequest();
request.setUid(visitorUid);
request.setNickname("Visitor " + visitorUid);
request.setAvatar("https://example.com/avatar.png");
// 1. 初始化访客
VisitorRequest initRequest = VisitorRequest.builder()
.sid(AGENT_UID)
.build();
initRequest.setType(TYPE);
initRequest.setOrgUid(ORG_UID);
mockMvc.perform(post("/visitor/anonymous/init")
String initResult = mockMvc.perform(post("/visitor/api/v1/init")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)))
.andExpect(status().isOk());
.content(objectMapper.writeValueAsString(initRequest)))
.andExpect(status().isOk())
.andReturn()
.getResponse()
.getContentAsString();
// 解析返回的访客信息
JsonResult<?> initResponse = objectMapper.readValue(initResult, JsonResult.class);
VisitorResponse visitor = objectMapper.convertValue(initResponse.getData(), VisitorResponse.class);
// 2. 请求会话
for (int j = 0; j < REQUEST_PER_VISITOR; j++) {
VisitorRequest threadRequest = VisitorRequest.builder()
.sid(AGENT_UID)
.nickname(visitor.getNickname())
.avatar(visitor.getAvatar())
.build();
threadRequest.setOrgUid(ORG_UID);
threadRequest.setType(TYPE);
threadRequest.setUid(visitor.getUid());
mockMvc.perform(post("/visitor/api/v1/request")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(threadRequest)))
.andExpect(status().isOk());
}
} catch (Exception e) {
log.error("创建访客失败: {}", visitorUid, e);
log.error("访客请求失败: {}", visitorIndex, e);
}
}, executor);
futures.add(future);
}
// 等待所有访客创建完成
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
executor.shutdown();
}
private void simulateVisitorRequests() throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(20);
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (String visitorUid : visitorUids) {
for (int i = 0; i < REQUEST_PER_VISITOR; i++) {
final int requestNum = i;
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
VisitorRequest request = new VisitorRequest();
request.setUid(visitorUid);
// request.setWorkGroupWid("workgroup_1");
// request.setRequestNo("request_" + visitorUid + "_" + requestNum);
mockMvc.perform(post("/visitor/anonymous/requestThread")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)))
.andExpect(status().isOk());
} catch (Exception e) {
log.error("访客请求失败: {} - 请求 {}", visitorUid, requestNum, e);
}
}, executor);
futures.add(future);
}
}
// 等待所有请求完成
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
executor.shutdown();
// 验证调用次数
verify(visitorRestService, times(VISITOR_COUNT)).create(any());
verify(visitorRestService, times(VISITOR_COUNT * REQUEST_PER_VISITOR)).requestThread(any());
}
@Test
void testConcurrentVisitorRequests() throws Exception {
// 创建10个访客同时发起10次请求的并发测试
int concurrentVisitors = 10;
int concurrentRequests = 10;
@@ -145,38 +139,46 @@ public class VisitorAnonymousControllerTest {
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (int i = 0; i < concurrentVisitors; i++) {
final String visitorUid = "concurrent_visitor_" + i;
// 先创建访客
VisitorRequest initRequest = new VisitorRequest();
initRequest.setUid(visitorUid);
initRequest.setNickname("Concurrent Visitor " + i);
mockMvc.perform(post("/visitor/anonymous/init")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(initRequest)))
.andExpect(status().isOk());
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
// 1. 初始化访客
VisitorRequest initRequest = new VisitorRequest();
initRequest.setOrgUid(ORG_UID);
initRequest.setType(TYPE);
initRequest.setSid(AGENT_UID);
// 然后并发发起请求
for (int j = 0; j < concurrentRequests; j++) {
final int requestNum = j;
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
VisitorRequest request = new VisitorRequest();
request.setUid(visitorUid);
// request.setWorkGroupWid("workgroup_1");
// request.setRequestNo("concurrent_request_" + visitorUid + "_" + requestNum);
String initResult = mockMvc.perform(post("/visitor/anonymous/init")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(initRequest)))
.andExpect(status().isOk())
.andReturn()
.getResponse()
.getContentAsString();
// 解析返回的访客信息
JsonResult initResponse = objectMapper.readValue(initResult, JsonResult.class);
VisitorResponse visitor = objectMapper.convertValue(initResponse.getData(), VisitorResponse.class);
// 2. 并发请求会话
for (int j = 0; j < concurrentRequests; j++) {
VisitorRequest threadRequest = new VisitorRequest();
threadRequest.setOrgUid(ORG_UID);
threadRequest.setType(TYPE);
threadRequest.setSid(AGENT_UID);
threadRequest.setUid(visitor.getUid());
threadRequest.setNickname(visitor.getNickname());
threadRequest.setAvatar(visitor.getAvatar());
mockMvc.perform(post("/visitor/anonymous/requestThread")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)))
.content(objectMapper.writeValueAsString(threadRequest)))
.andExpect(status().isOk());
} catch (Exception e) {
log.error("并发请求失败: {} - 请求 {}", visitorUid, requestNum, e);
}
}, executor);
futures.add(future);
}
} catch (Exception e) {
log.error("并发请求失败", e);
}
}, executor);
futures.add(future);
}
// 等待所有并发请求完成