用jmeter测试SpringBoot异步controller

下面的示例是在 springboot 的 controller 中整合异步service调用的示例。

我们需要完成:

  1. 做一个提供测试测试数据的 controller。
  2. 创建一个异步的 service,远程调用上面的测试数据 controller。
  3. 创建一个 controller,调用多个异步 service,并等待异步调用全部完成,输出结果。

示例

1. 测试数据 controller

package com.example.demoasync;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class EmployeeDataController {
    private static Logger log = LoggerFactory.getLogger(EmployeeDataController.class);

    @RequestMapping(value = "/addresses", method = RequestMethod.GET)
    public List<String> getAddresses() {
        log.info("get addresses Start");

        ArrayList<String> employeeAddresses = new ArrayList<String>();
        employeeAddresses.add("addr1");
        employeeAddresses.add("addr2");
        employeeAddresses.add("addr3");

        return employeeAddresses;
    }

    @RequestMapping(value = "/phones", method = RequestMethod.GET)
    public List<String> getPhoneNumbers() {
        log.info("get phones Start");

        ArrayList<String> phoneNumberList = new ArrayList<String>();

        phoneNumberList.add("100000");
        phoneNumberList.add("200000");

        return phoneNumberList;
    }

    @RequestMapping(value = "/names", method = RequestMethod.GET)
    public List<String> getEmployeeName() {
        log.info("get names Start");

        List<String> employeeList = new ArrayList<String>();

        employeeList.add("Santa");
        employeeList.add("Banta");

        return employeeList;
    }
}

 

2. 异步 service

import java.util.List;
import java.util.concurrent.CompletableFuture;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class AsyncService {

    private static Logger log = LoggerFactory.getLogger(AsyncService.class);

    @Autowired
    private RestTemplate restTemplate;

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @Async("asyncExecutor")
    public CompletableFuture<List<String>> getEmployeeName() throws InterruptedException {
        log.info("getEmployeeName starts");

        List<String> employeeNameData = restTemplate.getForObject("http://localhost:8080/names", List.class);

        log.info("employeeNameData, {}", employeeNameData);
        Thread.sleep(1000L); // Intentional delay
        log.info("employeeNameData completed");
        return CompletableFuture.completedFuture(employeeNameData);
    }

    @Async("asyncExecutor")
    public CompletableFuture<List<String>> getEmployeeAddress() throws InterruptedException {
        log.info("getEmployeeAddress starts");

        List<String> employeeAddressData = restTemplate.getForObject("http://localhost:8080/addresses", List.class);

        log.info("employeeAddressData, {}", employeeAddressData);
        Thread.sleep(1000L); // Intentional delay
        log.info("employeeAddressData completed");
        return CompletableFuture.completedFuture(employeeAddressData);
    }

    @Async("asyncExecutor")
    public CompletableFuture<List<String>> getEmployeePhone() throws InterruptedException {
        log.info("getEmployeePhone starts");

        List<String> employeePhoneData = restTemplate.getForObject("http://localhost:8080/phones", List.class);

        log.info("employeePhoneData, {}", employeePhoneData);
        Thread.sleep(1000L); // Intentional delay
        log.info("employeePhoneData completed");
        return CompletableFuture.completedFuture(employeePhoneData);
    }
}

或者:

@Async
    public CompletableFuture<List<RouteSelfCureDetailDTO>> getRouteSelfCureDetailList() {
        List<RouteSelfCureDetailDTO> list = routeMapper.getSelfCureDetailList();
        if (CollectionUtils.isEmpty(list)) {
            logger.info("There is no data, please adding first.");
            return CompletableFuture.completedFuture(new ArrayList<>());
        }
        list.stream().forEach(t -> {
            if (StringUtils.isEmpty(t.getSelfCureStatus())) {
                t.setSelfCureStatus(Constants.ROUTE_UP_STATUS);
            }
        });
        return CompletableFuture.completedFuture(list);
    }

 

3. controller

package com.example.demoasync;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AsyncController {
 
    private static Logger log = LoggerFactory.getLogger(AsyncController.class);
 
    @Autowired
    private AsyncService service;
 
    @RequestMapping(value = "/testAsynch", method = RequestMethod.GET)
    public void testAsynch() throws InterruptedException, ExecutionException
    {
        log.info("testAsynch Start");
 
        CompletableFuture<List<String>> employeeAddress = service.getEmployeeAddress();
        CompletableFuture<List<String>> employeeName = service.getEmployeeName();
        CompletableFuture<List<String>> employeePhone = service.getEmployeePhone();
 
        // 等待每个异步调用都完成
        CompletableFuture.allOf(employeeAddress, employeeName, employeePhone).join();
         
        log.info("EmployeeAddress--> " + employeeAddress.get());
        log.info("EmployeeName--> " + employeeName.get());
        log.info("EmployeePhone--> " + employeePhone.get());
    }
}

或者:

@RequestMapping(value = "/get_route_selfcure_list", method = RequestMethod.GET)
    public CompletableFuture<RetMsg> getRouteSelfCureDetailList() {
        if (logger.isDebugEnabled()) {
            logger.debug("getRouteSelfCureDetailList method begins");
        }
        CompletableFuture<List<RouteSelfCureDetailDTO>> future = detailApi.getRouteSelfCureDetailList();
        return future.thenApplyAsync(routeSelfCureDetailDTOS -> {
            if (CollectionUtils.isEmpty(routeSelfCureDetailDTOS)) {
                return new FailMsg(SelfCureExecuting.RetMsg.ROUTE_SELFCURE_DETAIL_ERROR_CODE, SelfCureExecuting.RetMsg.ROUTE_SELFCURE_DETAIL_ERROR_MSG);
            }
            return new SucMsg(routeSelfCureDetailDTOS);
        });
    }

4.在启动类上添加@EnableAsync注解:

@EnableAsync
public class Application {
.......
}

 5.在过滤器上添加异步支持:

@WebFilter(urlPatterns = "/*", filterName = "corsFilter", asyncSupported = true)
public class CorsFilter implements Filter {
........
}

6.最后把内置的Tomcat替换成jetty:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>

 7.设置jetty启动参数:

server.jetty.connection-idle-timeout=60000
server.jetty.threads.max-queue-capacity=2000
server.jetty.threads.max=4500
server.jetty.threads.min=4000

使用jmeter测试,需要添加cookie

使用Jmeter性能测试遇到的问题:java.net.SocketException: Connection reset by peer: socket write error at java.net.SocketOutputStream.socketWrite0(Native Method) at java.net.SocketOutputStream.socketWrite(Unknown Source) at java.net.SocketOutputStream.write(Unknown Source) at sun.security.ssl.OutputRecord.writeBuffer(Unknown Source) at sun.security.ssl.OutputRecord.write(Unknown Source) at

解决方法:

Make sure that your HTTP Requests "Implementation" is HTTPClient4
Add the following lines to user.properties file (located in /bin folder of your JMeter home)

httpclient4.retrycount=1
hc.parameters.file=hc.parameters
In the hc.parameters file (same location - JMeter's /bin folder) uncomment the next line:

http.connection.stalecheck$Boolean=true

 

链接:https://www.jianshu.com/p/be3b9cfbf495

https://blog.csdn.net/lanse_huanxiang/article/details/126558792

posted @ 2023-06-21 16:00  ppjj  阅读(272)  评论(0编辑  收藏  举报