이번에는 부하 테스트를 최초로 해보고자 한다 !
부하테스트에는 nGrinder라는 것을 사용해 볼 것이다
부하 테스트에 쓸 주소 - (2) 에서 만든 것들
http://k8s-default-backendi-6566bc7d31-1619657679.ap-northeast-2.elb.amazonaws.com/location
http://k8s-default-backendi-6566bc7d31-1619657679.ap-northeast-2.elb.amazonaws.com/location2
*ngrinder에 관련한 친절한 블로그
https://blog.naver.com/wideeyed/222173944239
nGrinder의 구성요소는?
Controller
웹기반의 GUI 시스템
유저 관리
다른 컴퓨터를 유저로 관리
에이전트 관리
부하 테스트 실시 & 모니터링
부하 시나리오 작성 테스트 저장 / 재활용
Agent
부하를 발생시키는 대상입니다.
Controller의 지휘를 받습니다.
복수의 머신에 설치해서 Controller의 신호에 따라서 일시에 부하를 발생합니다.
*출처 https://nesoy.github.io/articles/2018-10/nGrinder-Start
*윈도우에서 wget 하는 방법.
https://zetawiki.com/wiki/윈도우_wget
(오류 ?) - 까는 데 엄청 헤맴 ...
타 블로그는 엄청 쉽게(?) 되던데 나는 아니었다 . ㅠㅠ
그래서
controller는 docker로 ,
https://danidani-de.tistory.com/40
agent는 이 블로그 참조하여 ,
https://junghyungil.tistory.com/176
겨우 겨우 실행 시킬 수 있었다 !
첫번째 테스트 결과 - vuser1 로 설정.
이 때 현실적인 숫자를 맞출 필요가 있다.
vuser 1000으로 하니 망한 모습 ... (node group = m5.large 3개 , pod 3개 으로 돌렸다 !)
vuser => 동접속자 수 .
tps ==> test per second 초당 몇 번의 테스트가 일어났는지를 뜻함 .
**잠깐!
쿠버네티스 대시보드 !!
https://awskrug.github.io/eks-workshop/dashboard/dashboard/
https://ncoding.tistory.com/69
워크샵 자료와 블로그를 참고하여 잘 접속할 수 있었다 . https://fb53aa248da249aaa0d24e64524c15dd.vfs.cloud9.ap-northeast-2.amazonaws.com/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
============================================================================
실험에는 vuser를 400 정도로 잡았다.
공장 한 빌딩에 400명 정도의 근무자가 있을 것으로 예측했다 .
특이하게 , method는 GET이 많지 않다.
POST 가 많은 서버 .
그리고 헬멧의 post는 20초에 한번씩 일어나므로
400 / 20 = 20
vusers 수를 20 으로 잡았고 (post)
import static net.grinder.script.Grinder.grinder
import static org.junit.Assert.*
import static org.hamcrest.Matchers.*
import net.grinder.script.GTest
import net.grinder.script.Grinder
import net.grinder.scriptengine.groovy.junit.GrinderRunner
import net.grinder.scriptengine.groovy.junit.annotation.BeforeProcess
import net.grinder.scriptengine.groovy.junit.annotation.BeforeThread
// import static net.grinder.util.GrinderUtils.* // You can use this if you're using nGrinder after 3.2.3
import org.junit.Before
import org.junit.BeforeClass
import org.junit.Test
import org.junit.runner.RunWith
import java.util.Date
import java.util.List
import java.util.ArrayList
import net.grinder.plugin.http.HTTPRequest
import net.grinder.plugin.http.HTTPPluginControl
import HTTPClient.Cookie
import HTTPClient.CookieModule
import HTTPClient.HTTPResponse
import HTTPClient.NVPair
// Uncomment this to use new experimental HTTP client.
// import org.ngrinder.http.HTTPRequest
// import org.ngrinder.http.HTTPResponse
// import org.ngrinder.http.cookie.Cookie
// import org.ngrinder.http.cookie.CookieManager
/**
* A simple example using the HTTP plugin that shows the retrieval of a
* single page via HTTP.
*
* This script is automatically generated by ngrinder.
*
* @author admin
*/
@RunWith(GrinderRunner)
class TestRunner {
public static GTest test
public static HTTPRequest request
public static NVPair[] headers = []
public static String body = "{\"employee_id\":1,\n \"name\":\"dong hyeon lee\",\n \"location\":\"4\"\n }"
public static Cookie[] cookies = []
@BeforeProcess
public static void beforeProcess() {
HTTPPluginControl.getConnectionDefaults().timeout = 6000
test = new GTest(1, "http://k8s-default-backendi-6566bc7d31-1619657679.ap-northeast-2.elb.amazonaws.com/")
request = new HTTPRequest()
// Set header datas
List<NVPair> headerList = new ArrayList<>()
headerList.add(new NVPair("Content-Type", "application/json"))
headers = headerList.toArray()
grinder.logger.info("before process.");
}
@BeforeThread
public void beforeThread() {
test.record(this, "test")
grinder.statistics.delayReports=true;
grinder.logger.info("before thread.");
}
@Before
public void before() {
request.setHeaders(headers)
cookies.each { CookieModule.addCookie(it, HTTPPluginControl.getThreadHTTPClientContext()) }
grinder.logger.info("before. init headers and cookies");
}
@Test
public void test(){
HTTPResponse result = request.PUT("http://k8s-default-backendi-6566bc7d31-1619657679.ap-northeast-2.elb.amazonaws.com/location/1/", body.getBytes())
if (result.statusCode == 301 || result.statusCode == 302) {
grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", result.statusCode);
} else {
assertThat(result.statusCode, is(200));
}
}
}
post script를 작성했다 .
(*잠깐 건너가서 , )
private subnet에 db를 구축해보겠다!
기존처럼 docker image 에 db를 넣어버리면
각각 다른 db를 가지게 되서 업데이트가 특정 pod에만 되서
db가 엉터리가 된다.
그래서 rds같이 하나로 만들어서
pod가 그 rds 에 접속하게 해야한다
참고자료
https://ndb796.tistory.com/226
(1) 보안 그룹 생성 - 이번엔 private subnet 2개 묶어서 .
(2) rds 생성
(3) 한국어 지원(설정 변경)
(4) 엔드포인트로 접속 ! (대신 같은 vpc위에서 ! )
mysql -h database-2.czxrv3ygqn3s.ap-northeast-2.rds.amazonaws.com -P 3306 -u admin -p
mysql -h database-3.czxrv3ygqn3s.ap-northeast-2.rds.amazonaws.com -P 3306 -u admin -p
docker 도 settings.py 바꿔야 하는데 이는 구글링 하면 쉽게 나온다.
db 시작할때(rds)
Create Database dbname; 해줘야한다.
(* 다시 돌아와서 )
아까 3개 pod로는 정상적으로 구동이 안된 다는 것을 알았다.
vuser = 50 (근무자 1000 , 20초에 한 번씩 개정된다고 가정. )
*실험1 : m5.large 인스턴스 하나(쿠버x) 로 실험 시
못견디고 중간에 죽는다
*실험2 : pod수 2 (eks사용)
*실험 3: 파드 수 3
*실험 4: 파드 수 5
*실험5 : pod수 10
??? 예상과는 달리 파드를 늘려도 항상 불량(?) 하다.
심지어 갑자기 극단적으로 떨어진다 (???!)
그냥 Ec2에 두고 구동 해본 결과
broken pipe 오류가 미친듯이 나와서 왜그럴까 생각을 해보았는데
잦은 입출력이 하나의 요인이 될 수도 있다고 한다.
그러니까 Request받기전에 또 get,put으로 내놓으라고 하면
broken pipe가 뜬다고 한다.
(=미친듯한 새로고침)
그래서 script에 sleep을 주었더니
오!! 잘된다 !!
자 이제 또 다시 시작해보자 (?)
**setting!
vuser = 1300 ( 이제 sleep(20000)이 붙으므로 , vuser가 65이 아닌 1300 이 되어야 한다. ) - 공장 근무자 가 최고 1300명, 동접(vuser)
65명
(0) ec2 instance 1개(m5.large) 바로 다운
(1) pod = 1
(2) pod =2
(3) pod=3
45분 동안 안정적으로 버틴모습이다.
pod 3개 정도, node_group =3 정도를 maximum으로 잡고 설계하면 될 것 같다.
*vue 백그라운드 무중단 실행 .
(nohup npm run serve&)