Open skarltjr opened 3 years ago
// cpu-test.yaml
config:
target: "http://34.64.70.44"
phases:
- duration: 60
arrivalRate: 1
name: Warm up
scenarios:
# We define one scenario:
- name: "just get hash"
flow:
- get:
url: "/hash/123"
gcp 워커인스턴스를 3개 다 만드는게 아니라 gcp가 제공해주는 기능 . 복사
머신 이미지 -> 머신이미지 만들기
이 후 인스턴스를 만들어준다
주의 : 이렇게 만들어진 인스턴스는 모두 기존 워커인스턴스와 동일한 환경을 갖는다. 여기서 동일하다는 것은 파일에 대한내용. 설치해준 패키지나 다운로드한것들이 동일한것이지 젠킨스 배포관련설정,8080 포트띄워준 도커 애플리케이션은 해당 x
인스턴스 ip 8080으로 확인해보기
nohup docker run -p 8080:80 skarltjr/spring-boot-cpu-bound > nohup.out 2>&1 &
으로 명령어 변경tail -f nohup.out
으로 찍어보면sudo systemctl start docker
sudo chmod 666 /var/run/docker.sock
sudo yum install nginx
로 다운로드sudo systemctl start
nginx 로 시작sudo vi /etc/nginx/nginx.conf
upstream cpu-bound-app {
server {instance_1번의_내부ip}:8080 weight=100 max_fails=3 fail_timeout=3s;
server {instance_2번의_ip}:8080 weight=100 max_fails=3 fail_timeout=3s;
server {instance_3번의_ip}:8080 weight=100 max_fails=3 fail_timeout=3s;
}
location / {
proxy_pass http://cpu-bound-app;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
sudo systemctl reload nginx
이 때 restart reload의 차이는
restart : 서비스를 종료 후 재시작 - PID변경
reload : 프로세스를 종료하지않고 해당 서비스의 설정파일을 다시로딩
sudo tail -f /var/log/nginx/error.log
connect() to 10.178.0.15:8080 failed (13: Permission denied) while connecting to upstream, client: 112.151.220.190, server: _, request: "GET /hello HTTP/1.1", upstream: "http://10.178.0.15:8080/hello", host: "35.229.133.12"
setsebool -P httpd_can_network_connect on
을 입력해주면된다를 찾음sudo setsebool -P httpd_can_network_connect on
500에러는 성능상 더 이상 cpu bound애플리케이션이 요청을 처리할 수 없다
502는 500에러 조차 낼 수 없을정도. 애플리케이션이 종료되어서 나타난다. 이때부터 nginx는 이 인스턴스가 더이상 요청을 처리할 수 없다고 판단해서 연결을 끊는다.
300초동안 매 초3명의 유저를 투입시킬 때 : 부분부분 튀지만 어느정도 안정적
300초동안 매 초 8명의 유저를 투입시킬 떄 : 튀는 부분이 있지만 어느정도
이 때 동일한 조건에서 워커인스턴스2,3번을 내리고 단일 인스턴스로 측정해보고 비교해보기
그러기위해 2,3번 종료시키기 위해
docker ps // 동작중인 도커정보 출력
docker ps | grep spring-boot-cpu-bound // 이 후 맨 앞 컨테이너 아이디필요없이 찾아낼 수 있다
docker container kill -s 15 {컨테이너 id} // 이를통해 애플리케이션이 스스로 모든 로직을 처리한 후에 잘 종료하도록해준다.
- 이렇게 2,3번 두개의 인스턴스를 종료하고 1번 하나로만 성능측정해보기 : 502 에러 - 처리불가
![화면 캡처 2021-02-07 183455](https://user-images.githubusercontent.com/62214428/107142546-31a53c00-6973-11eb-8ddf-e49d6d93fd92.png)
- 이로써 cpu-bound 애플리케이션을 nginx의 로드밸런싱을 통해 분산처리했을 때 훨씬 안정적인 트래픽을 유지할 수 있는것을 확인했다.
- 다시 젠킨스에 접속해서 build now를 통해 배포를 하여 종료했던 2,3도 다시 동작시키고
- nginxIp/hello로 접속해서 동작을 확인하고 + 개별 인스턴스도 동작하나 확인해보고
#### 그렇다면 로드밸런싱으로 무중단 배포가 정말 이뤄지고 있는가?
- 확인을 위해 artillery스트레스 테스트를 동작시키는 도중에 1,2번 인스턴스를 하나씩 종료해보면
- 그래도 동작이 진행된다는 것은 - 여전히 3번 인스턴스를 통해 처리중이고 즉 무중단 배포가 진행되는것을 알 수 있다.
- 실행해본 결과 artillery test중에 2,3번을 내리고 다시 배포를 했음에도 중단없이 요청이 처리가 되는것을 확인할 수 있었고 결과적으로 무중단 배포가 실행 + 도중에 다시 젠킨스에서 build now를 통해 배포하여 2,3번을 살렸다. 만약 중간에 튀는 부분이 있다면 그것은 2,3번을 내리고 다시 배포하는 동안 1번 혼자서 모든 요청을 처리했기 때문이라고 추측 - 결과보기
![화면 캡처 2021-02-07 185013](https://user-images.githubusercontent.com/62214428/107142912-569aae80-6975-11eb-8784-40d8efe3af08.png)
나의 저장소이거나 저장소를 fork해서 push/webhook설정 권한획득
젠킨스에 접속하여 프로젝트(아이템) -> 구성 -> 소스코드 관리 Git체크 -> 저장소 Url추가 -> Build에서 Excute shell // 자동으로 배포를 위하여 매 배포마다 실행을 해줘야할 명령어를 설정 -깃허브에서 변경사항을 체크하고 다시 패키징을 통해 생성된 jar파일을 배포 -배포를 위해선 메이븐 clean / packing을 통해 타겟디렉토리clean/ 변경사항을 포함하여 다시 패키징을 통해 jar파일 생성 -메이븐 mvnw활용 -> 저장 후 다시 build now -> 빌드가 실패하는 걸 확인 mvnw에 permission denied확인 -> 그러므로 권한을 변경시켜줘야한다. -> 다시 build now - 성공확인
console output을 통해 젠킨스 로그를 살펴보면 현재 실행중인 명령이 docker를 통해서라는걸 확인
그러나 jar파일로 실행을 하기위해 jar path를 복사하여 ->구성 - 빌드 후 조치에서 모든 인스턴스에 대해
당연히 지금도 제대로 동작x - 명령어를 보면 java로 실행하겠다고 한다.
워커인스턴스에서 docker로 동작시키기위해 docker를 다운로드했지만 java는 다운로드한 적이 없다
워커인스턴스 모두 ssh접속하여 java다운로드
당연히 또 안된다 - 로그 출력을 위해 중단이 안된다. 다시 명령어 변경을 해줘야하는데
nohup sudo java -jar cpu-0.0.1-SNAPSHOT.jar > nohup.out 2>&1 &
이전 도커는 8080포트 연결
그러나 지금은 더 이상 도커 x
그러니 지금은 워커인스턴스ip/hello 하면 바로 연결이 된다. = 애플리케이션에서 지정한 80포트를 사용
nginx는 8080포트인데 애플리케이션은 80포트 따라서 애플리케이션 모두 8080포트 변경
이 내용을 푸쉬하고 자동화
우선 자동화를 위해 실행중인 애플리케이션 모두 종료
-워커인스턴스 ssh로 접속해서
-ps -aux | grep java
실행중인 프로자바 프로세스 검색
-3개의 프로세스 실행중인 걸 확인 후 모두 죽임
깃허브 저장소에서 setting - webhook -add webhook에서 payload를 등록
-http://34.64.101.145:8080/github-webhook/
젠킨스 외부ip:8080
-contentType : json으로변경
tail -f nohup.out
으로 로그를 찍어보니Description:
Web server failed to start. Port 8080 was already in use.
Action:
Identify and stop the process that's listening on port 8080 or configure this application to listen on an
other port.
-이미 8080포트를 사용하고 있는 놈이 존재
-프로세스 확인하고 죽이기 위한 명령 lsof를 사용하기 위해 인스턴스 모두 lsof 다운로드 (L임) // ★ sudo yum install -y lsof
-sudo kill -15 $(sudo lsof -t -i:8080)
명령어를 젠킨스에서 모든 ssh server 에 추가
-다시 hello kiseok2로 변경 후 푸쉬하고 배포 후에 확인해보면
sleep 5
ssh에서 sleep 명령어를 사용하면 여기선 5초동안 멈춘 후 그 다음 명령을 받게 할 수 있다.docker run --name pgsql -d -p 5432:5432 -e POSTGRES_USER=postgresql -e POSTGRES_PASSWORD=postgrespassword postgres
이 후 애플리케이션 실행 확인 spring.datasource.url=jdbc:postgresql://localhost
이었지만POSTGRES_DB
This optional environment variable can be used to define a different name for the default database
that is created when the image is first started. If it is not specified,
then the value of POSTGRES_USER will be used.
즉 POSTGRES_DB를 설정해주면 db의 이름을 지정, 여기서는 지정하지않았기때문에 디폴트값으로 username을 사용
sudo yum install docker
// 도커설치
sudo systemctl start docker
// 도커데몬 실행
sudo chmod 666 /var/run/docker.sock
// 권한부여
docker run --name pgsql -d -p 5432:5432 -e POSTGRES_USER=postgresql -e POSTGRES_PASSWORD=postgrespassword postgres
// 도커로 psql실행 ★여기서 원래는 도커에서 psql을 사용하여 계속 저장하기위해 volume을 잡아줘야 db에 있는 내용을 저장가능.
// 기본포트 5432 postgres
는 이미지 이름 , 유저 패스워드는 db에서 사용할
iobound app을 위한 워커인스턴스를 따로 또 만들어서 할 수 있지만 여기서는 기존의 cpu -worker인스턴스 재사용
★대신 젠킨스에서 새로운 배포 아이템을 만들기
이 때 기존 cpu-bound application deploy아이템을 복사하여 생성할 수 있는데 (어차피 배포과정은 jar파일 clean packing을 통해 동일하게 진행할것이기 때문에)
새로운 아이템에서
추가로 깃허브주소는 io bound 저장소 url로 변경 + jar파일 이름도 변경(인텔리제이에서 maven - plugin - jar를 통해 jar파일 생성 후 이름복사로 추가)+ 당연히 명령어도 io-0.0.1-SNAPSHOT.jar실행을 위해 변경 + branch도 여기서는 main으로 변경
sourcetree로 properties변경사항 commit 후 push
현재 저장소에서 webhook설정을 하지않았기 때문에 자동배포x 젠킨스 build now
nginx를 통해 접근해보면 동작하는것을 확인
url: jdbc:postgresql://10.140.0.3:5432/postgresql
이지만 로컬에서 개발을 위해 주석처리 후 localhost로 변경해서사용@GetMapping("/posts")
public Page<Post> getPostList(@PageableDefault(size = 20, sort = "id", direction = Sort.Direction.DESC) Pageable pageable) {
return postRepository.findAll(pageable);
}
@GetMapping("/search")
public List<Post> findPostsByContent(@RequestParam String content) {
return postRepository.findByContentContains(content);
}
이제 이 변경사항을 젠킨스를 통해 배포하기
artillery를 통해 테스트해보기
이 떄 dataset을 만들기 - 구글에서 korean dataset검색을하면 이미 많이 정리되어있음. 다운로드
구글docs 스프레드시트로 파일 - 가져오기- 업로드 (txt파일 csv파일로 확장자 변경해서 업로드) - 필요없는 열 지우기 - 이 후 다운로드(csv로)
artillery test / post요청으로 글 작성테스트 / 333초동안 초당 3개씩
1000건에 대해서 안정적임을 확인
다음으로 1만건에 대해 테스트하기
고도화된 테스트 스크립트
이 2번과 같이 갑자기 요청이 들이닥치는 순간을 잘 해결해야 대용량 트래픽에 대해 대처할 수 있다.
500에러와 3.7만건의 타임아웃발생을 확인
초당 3->100은 무리 / 50으로 조정 + post생성 요청 후 think( 대기) 1초 후 글목록 조회까지 추가하여 다시테스트
글작성 요청 -> 컨트롤러로 들어온 글 작성에 대한 요청들은 따로 queue에 넣어놓고 쓰레드는 다음 다른 요청을 받을 준비를 한다.
톰캣의 queue와 다른 점 : 톰캣의 큐보다 저장에 특화된 큐 / 만약 톰캣의 큐는 톰캣이 종료되면(서버가 죽으면) 큐도 사라지고 그 안에 저장된 내용도 당연히 같이 사라진다.
비동기성 : 요청이 몰리는 경우 mq 같은경우 요청을 저장한 후 하나씩 처리해나갈 수 있다. 즉 톰캣같은경우 서버가 죽으면 큐도 날아가버리는 반면 여기서는 저장이 가능 + 따라서 A -> mq ->B 순서에서 A는 로직에 상관없이★ 자신의 할일을 하고 큐에 넣은 후 다시 요청을 받을 수 있는 상태
애플리케이션간 의존성 제거 : A -> B로 API를 통해 데이터를 전달하는 경우 배포과정에서 B가 죽으면 보내려던 데이터는 사라진다. 반면 큐를 중간에 추가해주면 데이터는 여전히 저장이 되어있다. 이 후 B가 다시 정상작업이 가능해지면 저장된 요청을 처리한다.
큐의 이중화 : 큐도 결국 애플리케이션이기 때문에 죽을 수 있다. 여러개의 큐를 사용하여 하나가 죽더라도 이어나갈 수 있도록
신뢰성 : 요청이 실패하면 다시 큐로 가져온다. 이 후 다시 요청
cmd를 통해docker run -d --hostname my-rabbit --name some-rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3-management
도커이미지 받아서 실행하기 / 5672포트를 통해 메세지를 주고받고 15672포트는 모니터링 툴을 위한 포트 + 도커 데스크톱으로도 rabbit mq 확인
http://localhost:15672
로 username/password : guest로 접속 / 필요할 때 admin에서 계정생성 여기서는 guest로
queue를 이용하기
큐 설정
생성확인 후 접속해보기
메이븐 의존성 추가
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
야믈 or properties에 rabbitmq
spring:
datasource:
# url: jdbc:postgresql://10.140.0.3:5432/postgresql
url: jdbc:postgresql://localhost:5432/postgresql
username: postgresql
password: postgrespassword
jpa:
show-sql: true
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
ddl-auto: update
rabbitmq:
host: localhost
username: guest
password: guest
port: 5672
메세지를 큐에 집어넣는 producer / 큐에서 메세지를 가져오는 consumer가 필요
1. producer
@Component
@RequiredArgsConstructor
public class Producer {
private final RabbitTemplate rabbitTemplate;
public void sendTo(String message) {
rabbitTemplate.convertAndSend("CREATE_POST_QUEUE",message);
}
}
postman을 통해 post요청을 해보고 rabbitmq로 큐에 메세지 저장되어있는지 확인하기( 도커로 pgsql켜주고 로컬에서 실행되는 psql 종료시켜주기)
당연히 db에 안들어갔으니 id는 null
메세지 뽑아서 확인해보면
저장을 위한 consumer
@Component
@RequiredArgsConstructor
public class Consumer {
private final ObjectMapper objectMapper;
private final PostRepository postRepository;
@RabbitListener(queues = "CREATE_POST_QUEUE")
public void handler(String message) throws JsonProcessingException {
Post post = objectMapper.readValue(message, Post.class);
postRepository.save(post);
}
}
- rabbitMQ 인스턴스 새로 만들기
- 당연히 rabbitMQ에서 5672포트와 15672포트를 사용하기 때문에 방화벽 열어주기
- sourcetree를 통해 커밋준비 이 때 host: rabbitmq인스턴스 내부아이피 / url: jdbc:postgresql://postgres인스턴스 내부아이피 확인하기
spring: datasource: url: jdbc:postgresql://postgres인스턴스 내부아이피/postgresql username: postgresql password: postgrespassword jpa: show-sql: true hibernate: dialect: org.hibernate.dialect.PostgreSQLDialect ddl-auto: update rabbitmq: host: rabbitmq인스턴스 내부아이피 username: guest password: guest port: 5672
- 우선 rabbitmq 인스턴스에 도커 컨테이너 띄우기
sudo yum install docker sudo systemctl start docker sudo chmod 666 /var/run/docker.sock docker run -d --hostname my-rabbit --name some-rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3-management
- rabbitmq인스턴스 외부아이피:15672로 모니터링 툴 접속 후 동일하게 queue만들어주기
- 모든 내용 커밋을 위해 dev에서 새로운 브랜치를 따고 커밋 후 푸쉬
- 레퍼지토리에서 pr로 merge하기(당연히 dev <- feat으로 머지)
- feat에서 pull , dev 에서 pull로 확인
- main이랑 dev 병합하기
![화면 캡처 2021-02-13 160103](https://user-images.githubusercontent.com/62214428/107844196-bcbf7f80-6e14-11eb-8f21-87c9108dd08a.png)
- 이 후main도 푸쉬하여 마무리
- 배포 전 글 목록 0번(첫번쨰 페이지 캐싱)추가
### db부하를 줄이기 위해 글 목록 첫 페이지 캐싱하기 / 내부구현보다 redis 사용이 효율적
- 매 번 첫번째 페이지 요청마다 db에 접근하는 대신 미리 첫 페이지를 땡겨와서 저장해두면 db에 부하를 감소시킬 수 있다.
- chron 표현식 : https://www.leafcats.com/94
1. 스케쥴링이 가능하도록 설정하고
![화면 캡처 2021-02-13 160856](https://user-images.githubusercontent.com/62214428/107844329-cb5a6680-6e15-11eb-879c-9d76129fb446.png)
2. 글 목록 요청에서 만약 0번째. 첫 페이지를 요청하는 경우에는
@GetMapping("/posts")
public Page<Post> getPostList(@PageableDefault(size = 20, sort = "id", direction = Sort.Direction.DESC) Pageable pageable) {
if (pageable.getPageNumber() == 0) {
return postCacheService.getFirstPostPage();
} else {
return postRepository.findAll(pageable);
}
}
3. 1초마다 미리 끌어온 첫 페이지에 대한 내용을 반환해주기. / 즉 많은 첫페이지에 대한 요청이 매우 많은 경우에 미리 가져온 데이터를 반환해줌으로 추가적인 쿼리발생 x / 이 경우 yml에서 show-sql: false로 변경해줘서 로그 남기지않기
@Component @RequiredArgsConstructor public class PostCacheService {
private final PostRepository postRepository;
private Page<Post> firstPostPage;
@Scheduled(cron = "* * * * * *")
public void updateFirstPostPage() {
firstPostPage = postRepository.findAll(
PageRequest.of(0, 20, Sort.by("id").descending())
);
}
public Page
- 확인을 위해 localhost에서 show-sql: true로 실행해보면 계속 미리 땡겨오는걸 알 수 있다.
![화면 캡처 2021-02-13 163354](https://user-images.githubusercontent.com/62214428/107844714-47a27900-6e19-11eb-9e74-fdc766f70c79.png)
- 동일하게 dev에서 브랜치 따서 커밋 후 push 하여 pr로 merge한 후 dev브랜치 pull당긴 후 main병합하여 push
- 배포 후 확인
### artillery를 통해 글 작성 테스트
- rabbitmq를 적용했을 때 글 작성 테스트의 결과는 ?
테스트 스크립트 config: target: "http://35.229.133.12" phases:
![화면 캡처 2021-02-13 192450](https://user-images.githubusercontent.com/62214428/107847716-2a79a480-6e31-11eb-9a10-fb3e3c5b7ba2.png)
결과 : 이전보다 rabbitmq를 적용한 후 훨씬 많은 양이 처리되었다.
그러나 여전히 전체적으로 정상처리가 안되는데 - 워커인스턴스는 region서울 / nginx는 타이완 / rabbitmq는 일본
즉 하나의 요청을 처리하는데 지리적 위치로 인한 전송속도로 지연
이를위해 워커인스턴스2,3번을 지우고 네트워크 지연을 막기위해 그 자리에 rabbitmq와 nginx를 끌어온다
★만약 cpu bound app이라면 이 경우 워커인스턴스가 줄어드니 당연히 성능이 저하된다.
★ 그러나 지금 중요한 것은 cpu bound x / io bound . 즉 네트워크의 속도가 성능을 결정한다.
그럼 당연히 네트워크 지연을 막는것 > 요청을 처리할 cpu의 갯수 보다 중요
워커인스턴스2번 삭제 후 nginx 인스턴스 - 새 머신 이미지 생성 - 머신이미지로 새로운 인스턴스 생성(서울로)\
nginx2에서 nginx서비스 시작
이전에 nginx인스턴스를 복사했기 때문에 워커인스턴스 3번에 대한 정보를 지워줘야한다.
sudo vi /etc/nginx/nginx.conf
에서 instance3에 대한내용 삭제
sudo systemctl start nginx
어차피 머신이미지로 파일들은 모두가져왔고 설정,상태에 대해서만 다시 설정해주면된다.
sudo yum install docker
sudo systemctl start docker
sudo chmod 666 /var/run/docker.sock
docker run -d --hostname my-rabbit --name some-rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3-management
확인을 위해 nginx2 아이피:15672 rabbitmq로 접근해보기
새로운 인스턴스니까 queue추가해주기
인텔리제이에서 rabbitmq host 주소를 변경해주기 nginx2로 들어갈거기 때문
rabbitmq:
host: nginx2인스턴스 내부아이피
username: guest
password: guest
port: 5672
당연히 레퍼지토리에도 올리기 / 단 이경우에는 간단한 변경이기때문에 메인브랜치에서 바로 커밋 푸쉬
마지막으로 젠킨스 구성변경 - 3번 워커인스턴스 삭제 후 buildnow를 통해 메인브랜치 배포
이제 다시 artillery로 테스트
로그를 보기위해 nginx2인스턴스에서 sudo tail -f /var/log/nginx/error.log
(24: Too many open files) - 구글링 - https://medium.com/hbsmith/too-many-open-files-%EC%97%90%EB%9F%AC-%EB%8C%80%EC%9D%91%EB%B2%95-9b388aea4d4e
각 프로세스의 NOFILE Limit를 변경해줘야한다.
nginx의 프로세스 아이디를 알기위해
sudo prlimit --nofile --output RESOURCE,SOFT,HARD --pid 1309
를 통해 pid 1309의 리밋확인
sudo cat /proc/sys/fs/file-max
를 통해 최대 max값 확인 = 368595
sudo prlimit --nofile=100000 --pid=1309
으로 리밋 올려주기 10만으로 / 1310도
//100000 --pid 띄워야한다 중간에 . 개고생함
마무리로 다시 스트레트 테스트 진행
모두 성공 정상처리
시스템 설정에서 젠킨스에서 새로만든 인스턴스 ssh에 접근할 수 있도록 추가 / 프로젝트 구성에서 배포스크립트의 ssh서버 추가
이ㅣ 후 배포
이 후 테스트
config:
target: "http://34.64.207.46"
phases:
- duration: 60
arrivalRate: 3
name: Warm up
- duration: 120
arrivalRate: 3
rampTo: 50
name: Ramp up load
- duration: 6000
arrivalRate: 50
name: Sustained load
payload:
path: "ratings_test_50k.csv"
fields:
- "content"
scenarios:
- name: "just post content"
flow:
- post:
url: "/post"
json:
content: "{{ content }}"
- think: 1
- get:
url: "/posts"
현재 db에 60만 건에 대한 post insert완료
search로 60만건에 대해 검색해보고 시간이 얼마나 나오나 확인하기
keyword : 영화
1번째 시도 2번째 시도
keyword : 재미
keyword : 한국
50만건인데 이정도 검색속도
★만약 데이터가 500만건이면 데이터베이스가 검색속도를 여전히 유지할 수 있을까?
★검색을 위해서는 데이터베이스는 부족한점이있다.
이를 위해 elastic search
추가로 에러가 났을 때 각인스턴스에서 에러로그를 확인해보고 설정 혹은 설치해야할 것을 다시 확인
db : 직관적
ES : 문서- >내용에 추가로 단어 ->문서로 찾을 수 있는 테이블이 추가된다.
즉 특정 단어가 포함된 문서를 빠르게 찾을 수 있다. (역 색인)
그런데 만약 "재미"라는 단어로 검색하면 여기서는 "재미있다"를 포함한 문서는 검색이 안된다. /한국어는 ES에서 제공하는 플러그인 NORI를 사용하여 형태소 분석
샤드는 각각의 인스턴스마다 서로다른 데이터를 저장
레플리카는 복사본
만약 여기서 1번 인스턴스가 죽으면 다른 인스턴스에 1번의 복제본인 레플리카를 저장 / 단 여기서 2번 인스턴스에 1번인스턴스의 데이터를 저장하는것은 당연히 쓸모없는 일.. 똑같은 데이터이기때문에
rabbitmq:
host: 10.178.0.21 / nginx내부아이피
username: guest
password: guest
port: 5672
# ES 노드에서 실행해야 할 명령어
# 1. 공통
sudo yum install -y docker
sudo systemctl start docker
sudo chmod 666 /var/run/docker.sock
sudo sysctl -w vm.max_map_count=262144 // 가상메모리를 많이 사용하기때문에 사이즈 늘려주기
블루그린 / 배포를 위해 기존 서버만큼 그린 서버 구축 -> 그린 서버에서 배포준비가 완료되면 앞 쪽 로드밸런싱을 담당하는 곳에서 요청을 모두 새로운 그린서버로 보낸다.
카나리 배포도 존재( 블루그린에서는 이전 버전과 새 버전이 공존 x / 카나리는 요청이 두 곳 모두에 들어가서 공존)
vm을 통해 배포하기
1. gcp에서 vm인스턴스 생성
2. gcp vm인스턴스에서 ssh를 사용하여 명령
sudo yum install docker
sudo systemctl start docker
sudo docker run -d -p 80:80 docker/getting-started
ssh란? : Secure Shell Protocol, 즉 네트워크 프로토콜 중 하나로 컴퓨터와 컴퓨터가 인터넷과 같은 Public Network를 통해 서로 통신을 할 때 보안적으로 안전하게 통신을 하기 위해 사용하는 프로토콜.
여기서는 gcp,aws의 인스턴스 서버에 접속하여 해당 머신에 명령을 내릴 때 ssh를 사용
3. 배포하고자하는 프로그램 jar파일로 패키징 후 깃허브에 업로드
4. 깃허브에 올려둔 jar파일을 gcp인스턴스에서 다운로드
Dockerized 애플리케이션 배포
https://spring.io/guides/gs/spring-boot-docker/ : 도커파일 작성법
도커허브 저장소 create
인텔리제이에서 메이븐 빌드 명령어 : docker build -t 도커허브사용자이름/저장소이름 . 를 통해 이미지빌드 여기서는
docker build -t skarltjr/spring-boot-cpu-bound
인텔리제이에서
docker run -p 8080:8080 springio/gs-spring-boot-docker
: 로컬에서 실행해보기 여기서는docker run -p 80:80 skarltjr/spring-boot-cpu-bound
vm에서는 jar파일을 직접실행 / 여기서는 도커이미지안에 있는 jar파일을 실행한것
도커이미지를 도커허브에 푸쉬하여 이미지를 저장소에 저장/업로드
docker push skarltjr/spring-boot-cpu-bound:tagname
docker push skarltjr/spring-boot-cpu-bound
을 수행GCP인스턴스에서 저장소에있는 이미지를 풀로 다운로드
sudo yum install docker
sudo systemctl start docker
로 도커 실행하기sudo docker pull skarltjr/spring-boot-cpu-bound
로 인스턴스에서 pull하기sudo docker run -p 80:80 skarltjr/spring-boot-cpu-bound
를통해 80번 포트를 사용하기 때문에 내부외부 연결 후 실행다운로드된 이미지를 run하면 컨테이너가 되어 애플리케이션이 실행된다.
Jenkins
// sudo yum install jenkins를 하면 패키지가 없다고 뜬다. -> 따로 패키지를 추가해줘야한다 sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key sudo yum install jenkins // 이 후 젠킨스 다운로드 sudo systemctl start jenkins // jenkins 데몬 실행 sudo systemctl status jenkins // 데몬 실행 확인
[kisa0828@cpu-worker-instance-1 .ssh]$ chmod 700 ~/.ssh [kisa0828@cpu-worker-instance-1 .ssh]$ chmod 600 ~/.ssh/authorized_keys