250x250
Notice
Recent Posts
Recent Comments
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- myBatis
- JDBC
- IntelliJ
- STS
- PostgreSQL
- Source
- MSSQL
- Exception
- JavaScript
- oracle
- Python
- maven
- SpringBoot
- 오픈소스
- 설정
- MySQL
- error
- AJAX
- spring
- Spring Boot
- git
- 문서
- Eclipse
- Open Source
- Tomcat
- jpa
- Docker
- Thymeleaf
- ubuntu
- Core Java
Archives
- Today
- Total
헤르메스 LIFE
[Spring Boot] Multi FileUpload Test 본문
728x90
테스트 환경
https://hermeslog.tistory.com/577?category=1078420
동시 업로드를 어디까지 받을 수 있는지 확인하고 싶었습니다.
로컬테스트에서 이정도 성능이면, 서버에서는 더더욱 좋지.. 싶습니다.
HttpClient 를 Thread 로 이용했습니다.
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
</dependency>
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.3</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.study</groupId>
<artifactId>springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>springboot</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>11</java.version>
</properties>
<dependencies>
<!-- <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mustache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
FileUploadControllerTest.java
package com.study.springboot.system.controller;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
public class FileUploadControllerTest {
@Autowired(required = true)
FileUploadController fileUpload;
@Test
public void upload() throws Exception {
System.out.println("main start .......");
for (int i = 0; i < 10; i++) {
Runnable task = new Task1();
Thread thread = new Thread(task);
thread.setName("thread-A" + i);
thread.start();
}
for (int i = 0; i < 10; i++) {
Runnable task = new Task2();
Thread thread = new Thread(task);
thread.setName("thread-B" + i);
thread.start();
}
for (int i = 0; i < 10; i++) {
Runnable task = new Task3();
Thread thread = new Thread(task);
thread.setName("thread-C" + i);
thread.start();
}
for (int i = 0; i < 10; i++) {
Runnable task = new Task4();
Thread thread = new Thread(task);
thread.setName("thread-D" + i);
thread.start();
}
for (int i = 0; i < 10; i++) {
Runnable task = new Task5();
Thread thread = new Thread(task);
thread.setName("thread-E" + i);
thread.start();
}
for (int i = 0; i < 10; i++) {
Runnable task = new Task6();
Thread thread = new Thread(task);
thread.setName("thread-F" + i);
thread.start();
}
for (int i = 0; i < 10; i++) {
Runnable task = new Task7();
Thread thread = new Thread(task);
thread.setName("thread-G" + i);
thread.start();
}
for (int i = 0; i < 10; i++) {
Runnable task = new Task8();
Thread thread = new Thread(task);
thread.setName("thread-H" + i);
thread.start();
}
for (int i = 0; i < 10; i++) {
Runnable task = new Task9();
Thread thread = new Thread(task);
thread.setName("thread-I" + i);
thread.start();
}
for (int i = 0; i < 10; i++) {
Runnable task = new Task10();
Thread thread = new Thread(task);
thread.setName("thread-J" + i);
thread.start();
}
Thread.sleep(120000); // 재우지 않으면 Connection 이 Close 되어버림. ( 1000: 1초 )
System.out.println("main exit .......");
}
class Task1 implements Runnable {
@Override
public void run() {
File imgFile = new File("c:/Temp/pickpick/이미지 004.jpg");
excuteClient(Thread.currentThread(), imgFile);
}
}
class Task2 implements Runnable {
@Override
public void run() {
File imgFile = new File("c:/Temp/pickpick/이미지 005.jpg");
excuteClient(Thread.currentThread(), imgFile);
}
}
class Task3 implements Runnable {
@Override
public void run() {
File imgFile = new File("c:/Temp/pickpick/이미지 006.jpg");
excuteClient(Thread.currentThread(), imgFile);
}
}
class Task4 implements Runnable {
@Override
public void run() {
File imgFile = new File("c:/Temp/pickpick/이미지 007.jpg");
excuteClient(Thread.currentThread(), imgFile);
}
}
class Task5 implements Runnable {
@Override
public void run() {
File imgFile = new File("c:/Temp/pickpick/이미지 008.jpg");
excuteClient(Thread.currentThread(), imgFile);
}
}
class Task6 implements Runnable {
@Override
public void run() {
File imgFile = new File("c:/Temp/pickpick/이미지 009.jpg");
excuteClient(Thread.currentThread(), imgFile);
}
}
class Task7 implements Runnable {
@Override
public void run() {
File imgFile = new File("c:/Temp/pickpick/이미지 010.jpg");
excuteClient(Thread.currentThread(), imgFile);
}
}
class Task8 implements Runnable {
@Override
public void run() {
File imgFile = new File("c:/Temp/pickpick/이미지 001.jpg");
excuteClient(Thread.currentThread(), imgFile);
}
}
class Task9 implements Runnable {
@Override
public void run() {
File imgFile = new File("c:/Temp/pickpick/이미지 002.jpg");
excuteClient(Thread.currentThread(), imgFile);
}
}
class Task10 implements Runnable {
@Override
public void run() {
File imgFile = new File("c:/Temp/pickpick/이미지 003.jpg");
excuteClient(Thread.currentThread(), imgFile);
}
}
private void excuteClient(Thread threadId, File imgFile) {
MultipartEntityBuilder params = MultipartEntityBuilder.create();
CloseableHttpClient http = HttpClients.createDefault();
StringBuffer result = new StringBuffer();
try {
params.addPart("files",
new FileBody(imgFile, ContentType.create("application/octet-stream"), imgFile.getName()));
HttpPost post = new HttpPost("http://localhost:9090/upload");
post.setHeader("Connection", "Keep-Alive");
post.setHeader("Accept-Charset", "UTF-8");
post.setEntity(params.build());
CloseableHttpResponse response = http.execute(post);
try {
HttpEntity res = response.getEntity();
BufferedReader br = new BufferedReader(
new InputStreamReader(res.getContent(), Charset.forName("UTF-8")));
String buffer = null;
while ((buffer = br.readLine()) != null) {
result.append(buffer).append("\r\n");
}
} finally {
response.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
http.close();
} catch (Exception e) {
}
}
// Printing the status and the contents of the response
System.out.println("threadId >> " + threadId + " >> " + result.toString());
}
}
결과
300개 파일이 저장된 모습입니다.
여러번 테스트 한 중에...
아래의 설정을 추가하고, 좀 더 빨라졌음을 느꼈습니다.
아래 참고 Site를 참조하였습니다.
server:
port: 9090
servlet:
context-path: /
encoding:
charset: UTF-8
enabled: true
force: true
tomcat:
accept-count: 100 # Spring Default : 100
max-connections: 100 # Spring Default : 8192
connection-timeout: 20000 # Spring Default : 60000 (i.e. 60 seconds)
threads:
max: 200 # Spring Default : 200
min-spare: 10 # Spring Default : 10
keep-alive-timeout: 15 # Spring Default : 15
max-keep-alive-requests: 100 # Spring Default : 100
max-http-form-post-size: 100
uri-encoding: UTF-8 # Spring Default : UTF-8
application.xml
server:
port: 9090
servlet:
context-path: /
encoding:
charset: UTF-8
enabled: true
force: true
tomcat:
accept-count: 100 # Spring Default : 100
max-connections: 100 # Spring Default : 8192
connection-timeout: 20000 # Spring Default : 60000 (i.e. 60 seconds)
threads:
max: 200 # Spring Default : 200
min-spare: 10 # Spring Default : 10
keep-alive-timeout: 15 # Spring Default : 15
max-keep-alive-requests: 100 # Spring Default : 100
max-http-form-post-size: 100
uri-encoding: UTF-8 # Spring Default : UTF-8
spring:
mvc:
view:
prefix: /WEB-INF/jsp/
suffix: .jsp
h2:
console:
enabled: true
path: /h2-console
datasource:
url: jdbc:postgresql://localhost:5432/springboot
username: hermeswing
password: pass
hikari:
idle-timeout: 10000
maximum-pool-size: 10
minimum-idle: 5
pool-name: BaseHikariPool
jpa:
generate-ddl: true
hibernate:
ddl-auto: update # Hibernate ddl auto (create, create-drop, validate, update)
show-sql: false
properties:
hibernatte:
format_sql: true
profiles:
active: local
logging:
level:
org:
hibernate:
SQL: debug
type:
descriptor:
SQL: trace
https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html
https://www.codetd.com/en/article/12548952
728x90
'Spring Boot Framework' 카테고리의 다른 글
[Spring Boot] Spring Security #01 (0) | 2022.03.01 |
---|---|
[Spring Boot] 정적 페이지 로딩 (0) | 2022.02.27 |
[Spring Boot] JPA 동시 입력 테스트 (0) | 2022.02.27 |
Common Application Properties (0) | 2022.02.27 |
[Spring Boot] Multi FileUpload (0) | 2022.02.27 |