반응형

가상메모리에 대해 설명하기 앞서 자바 기반 솔루션의 경우 설정한 최대 힙 메모리 이상을 사용하지 않기 때문에 최대 힙 메모리가 운영체제의 메모리를 넘기지 않도록 설정됬다면 운영체제의 메모리 부족이 발생할 가능성은 낮다. 하지만 한정된 힙 메모리 내에서 동작하기 때문에 대량의 데이터 처리와 빈번한 GC로 인한 성능 저하가 유발될 가능성이 있다. OS 메모리 용량이 많아 힙 메모리를 과하게 크게 설정한 경우에는 메모리를 청소하는 GC 작업으로 순간 순간 멈추는 시간이 길어져 서비스 안정성이 떨어질 수도 있다.

오라클 버퍼 캐시처럼 데이터베이스는 디스크에서 데이터를 읽어옮으로써 발생하는 성능 저하를 개선하기 위해 메모리에 최근에 사용한 데이터 블록을 캐시해서 재사용하는 알고리즘이 있다. 통상 이 버퍼에 대한 캐시 적중률은 90%이상 나오는 것이 일반적인데, 캐시의 메모리 크기가 너무 작게 설정된 경우 캐시 적중률이 떨어져 디스크에서 데이터 블록을 읽어와야 하는 ㅂ니도가 늘어나 성능 저하를 유발할 수도 있다. 반대로 캐시를 크게 설정해 운영체제에서 스왑이 발생하게 되면 오히려 작게 설정한 것보다 성능이 더욱 악화되어 서비스가 거의 멈추는 상태가 유발될 수도 있다.

Virtual Memory(가상메모리)

서버는 설치할 수 있는 메인 메모리 (Main memory, Physical memory)에 한계가 있고, 예상치 못하게 메모리 사용량이 크게 증가할 수도 있지만 메모리는 비싼 자원으로 언제 발생할지 모르는 상황에 대비해 메모리를 충분히 확보하기 어렵다. 그래서 운영체제는 위와 같은 제약사항을 극복하기 위해 상대적으로 값싼 디스크를 보조 메모리로 사용하는 방식을 사용하고 있다. 디스크의 일정 공간을 할당해 보조 메모리 용도로 사용하는데 이를 페이징스페이스라고 한다. 

메인 메모리(주 기억장치)와 디스크의 페이징스페이스(Pagingspace, 보조 기억장치)를 묶어 하나의 메모리처럼 동작하게 함으로써 메인 메모리 한계를 넘는 메모리 사용을 가능하게 하는 것이 가상 메모리다.

운영체제에서 관리하는 메모리 액세스 단위를 페이지(page)라고 하며 통상 4KB 단위다. 이 페이지 단위로 일부는 메인 메모리에 있을 수도 있고 또 일부는 페이징스페이스에 있을 수도 있는 것이다.

프로세스 내에서 사용 중인 가상 메모리 주소만 봐서는 해당 페이지가 메인 메모리에 있는지 페이징스페이스에 있는지 확인할 수 없다. 그렇다고 페이징스페이스가 메인 메모리와 동일한 것은 아니다. 메인 메모리의 입출력 속도가 디스크에 비해 비교가 안 될 정도로 우수하기 때문에 프로세스가 기동되면 기본적으로 메인 메모리를 사용하다가 부족해지면 페이징스페이스를 사용하게 된다. 이때도 CPU가 페이징스페이스에 있는 데이터를 메인 메모리처럼 바로 사용할 수 있는 것이 아니라 사용 빈도가 낮은 프로세스의 메인 메모리 사용 부분을 페이징스페이스 부분으로 옮겨 여유 메모리를 확보한 후 사용할 페이징스페이스 부분을 메인 메모리로 로드해서 사용하는데, 이를 스와핑이라고 한다. 그래서 CPU가 직접 접근할 수 있는 메인 메모리를 활성 가상 메모리(Active virtual memory)라 하고, 페이징스페이스를 비활성 가상 메모리(Inactive virtual memory)라고 한다. 

가상 메모리 주소는 프로세스 내에서만 유효한 주소다. 각 프로세스는 가상 메모리 주소와 실제 주소 간의 매핑 테이블 (Virtual-to-physical translation table)을 가지고 있어 가상 메모리 주소로 실제 주소를 찾아갈 수 있게 돼 있다. 실제 주소는 메인 메모리와 페이징스페이스의 주소를 가리킨다. 

 

해당 글은 '실무로 배우는 시스템 성능 최적화'의 메모리 부분에서 발췌한 내용입니다.

반응형
반응형

1. 페이징스페이스(Pagingspace)

페이징스페이스는 메인 메모리가 부족할 때 사용하는 디스크 공간으로, 스왑 스페이스(Swapspace)라고도 한다. 

1GB 메모리가 탑재된 시스템에서 이미 900MB 메모리를 운영체제와 다른 프로세스가 사용하고 있는데, 300MB 메모리를 사용하는 프로세스를 새로 실행한다고 가정해 보자. 여유 메모리가 100MB밖에 없어 신규 프로세스를 기동할 수 없는 상황으로 보인다. 그러나 운영체제는 현재 사용 중인 900MB 메모리 중 200MB 정도를 디스크에 존재하는 페이징스페이스라는 곳으로 옮김으로써 메인 메모리에서 300MB를 확보해 신규 프로세스를 수행한다.

즉, 페이징스페이스는 운영체제가 메인 메모리 크기 이상의 메모리를 사용할 수 있게 해주는 역할을 한다. 그러나 시스템 성능 관점에서 보면 페이징스페이스는 디스크에 프로세스 메모리를 쓰고, 읽는 스와핑 작업으로 인해 메모리 접근만으로 처리될 때메 비해 큰 성능 저하가 발생한다. 따라서 스와핑이 발생하지 않도록 메모리 여유율을 유지하는 것이 성능에 중요하다.

2. 페이징(Paging)

가상 메모리 체계에서는 운영체제가 인식하는 일정한 크기(4KB, 64KB)의 데이터 기록 단위를 페이지라고 한다. 메인 메모리로부터 한 페이지의 데이터를 보조 기억장치(디스크)로 복사하거나 보조 기억장치로부터 메인 메모리로 로드하는 것을 페이징이라고 한다.

3. 스와핑(Swapping)

메모리에서 페이지 혹은 세그먼트 단위 데이터를 교환하는 것으로 컴퓨터가 메모리보다 큰 프로그램을 실행하거나 메모리보다 큰 데이터 파일을 다룰 수 있게 한다. 가상 메모리 체계에서는 페이징 기법을 이용해 스와핑을 수행한다. 스와핑은 프로세스가 사용하는 메모리 일부를 페이징스페이스로 옮기거나 페이징스페이스로부터 메모리로 로드하는 것을 가리킨다.

4. 페이지 부재(Page Fault)

페이징 방식의 가상메모리에서 CPU가 사용하려는 페이지가 메인 메모리에 없는 경우다. 사용하려는 가상 메모리 주소에 해당 페이지를 매핑 테이블에서 주소 변환할 때 해당 페이지가 메인 메모리에 없다고 표시돼 있으면 페이지 부재가 발생한다. 이 경우 해당 페이지를 디스크에 있는 파일 또는 페이징스페이스에서 가져와야 하고 메인 메모리가 부족한 경우에는 다른 페이지와 교체해야 한다.

5. 페이지 인(Page In)

가상 메모리에서 페이지 부재가 일어났을 때 디스크에 있는 프로그램이나 데이터를 메모리에 로드하는 것

6. 페이지 아웃(Page out)

가상 메모리에서 페이지 부재가 발생했을 때 메모리가 부족하면 페이지 스틸러(Page stealer)는 기존 메모리를 디스크로 기록하는 페이지 아웃이라는 작업을 수행한다. 기록 대상 메모리가 프로세스의 작업 세그먼트(Work segment)영역에 있는 메모리면 페이징스페이스로 기록하고, 파일에서 읽어 들인 내용(Permanent segment)인 경우 페이지의 내용이 변경됐으면 디스크의 해당 파일에 기록하고 그렇지 않으면 소멸시킨다.

7. 페이지 스캔률(Page Scan Rate)

운영체제는 일정량의 여유 페이지(Free page)를 확보해서 필요할 경우 즉시 제공하기 위해 페이지 스캔 (Page scan)이라는 검색을 통해 해제함으로써 여분으로 확보할 페이지를 찾는다. 여유 페이지 목록(Free page list) 임계치보다 여유 페이지 수가 줄어들면 메모리 관리자는 기존의 페이지 인된 것 중에서 LRU 알고리즘 검색을 통해 페이지 아웃이 가능한 것을 찾아 페이지 아웃시킨 후 여유 페이지로 변경한다. 여기서 페이지 아웃이 가능한 페이지를 탐색하는 빈도를 의미하는 페이지 스캔률이 나오는데 빈도가 높다는 것은 해제할 페이지가 넉넉하지 못하기 때문에 자주 메모리를 탐색해야 한다는 의미로 볼 수 있다. 

 

해당 내용은 '실무로 배우는 시스템 성능 최적화' 책의 내용중 일부를 발췌한 것입니다.

 

반응형
반응형

최근 1월 중순쯤부터 Chrome Samesite이슈에 대응한다고 설연휴전까지 시간이 굉장히 빠르게 지나간 것 같다.

아마 서비스에서 쿠키를 클라이언트들의 브라우저에 심어 무엇인가를 처리하고 있었던 분들이라면 해당 이슈에 대해 이미 파악하고 대처 했을 거라 생각된다. 그럼 구글에서 크롬(Google Chrome)에 어떤 정책을 적용했고 SameSite란 무엇인가? 에 대해 간단히 정리해보려 한다.

SameSite 한 마디로 지금 현재 사이트(도메인, First Party)의 쿠키만 클라이언트 브라우저에 심도록 허용하겠다! 

이 말인 즉슨 기존 크롬 버전 80이전 버전에서는 도메인이 다른 (Third Party)의 서버에서 response.addCookie만 해주면 third party쿠키를 쉽게 심을 수 있었다. 관련한 내용은 이전 포스팅을 참고 바란다.

"다른 도메인 내부에 쿠키 생성하기(이게 가능해?)" https://brocess.tistory.com/146?category=715032

 

[ Spring ] 다른 도메인 내부에 쿠키 생성하기 (이게 가능해???)

다른 도메인 내부에 쿠키 생성하기 (이게 가능해???) 최근 쿠키매칭시스템 설계를 위해 광고 프로세스 전반에 대한 내용을 학습중 우리 도메인 쿠키 내부에 다른 도메인 쿠키값들이 박혀있는 걸 발견하였다. 뭐야..

brocess.tistory.com

그렇다 이전에는 그냥 막 심어도 문제 없었다. 

근데 구글에서 보안 이슈를 명목(사이트간 쿠키기반 요청 위조(CSRF - Cross site request forgery)으로 크롬(Google Chrome) 80버전 부터는 third party(웹서비스와 도메인이 다른 서버)에서 쿠키 심는걸 default로 막겠다는 것이다. 2020년 2월 4일 부터 점차 크롬을 사용하는 사용자들의 브라우저들이 79버전에서 80으로 자동으로 차차 업데이트 되어질거라고 말했었다.

이게 자기들 도메인의 웹서비스에 쿠키를 심어서 사용하는 서비스에는 별문제가 없겠지만 광고서비스와 같이 해당 클라이언트의 쿠키의 특정ID값을 기반으로 유저를 구분해 타겟팅하는 서비스들에서는 큰 이슈거리일 수 밖에 없다. 😱😱😱😱😱😱😱😱

하지만 구글에서는 아예 third party 쿠키를 심지못하도록 원천봉쇄하지는 않았다. 쿠키를 다른 도메인의 서비스에 심을 때 'SameSite=none', 'secure'설정을 쿠키에 하면 기존처럼 허용해주겠다는 것이다!!!! 크롬 버전 80이상부터는 기본적으로 크롬 브라우저의 설정이 'SameSite=Lax'가 되어 버린다. (Lax보다 한 단계 높은 보안 수준인 'strict'도 존재한다.)

 

그럼 어떤식으로 해결을 해주어야 할까?

크롬 Samesite설정을 강제적으로 80버전과 같은 보안수준으로 올리고 테스트를 해보았다. 해당 설정은 크롬 브라우저에 chrome://flags라고  치면 확인할 수 있다.

크롬 80이전 버전에서는 모두 Default로 되어있다.(SameSite=none)이라고 생각하면 된다.

위의 Default값을 Enable로 변경하면 크롬 80버전의 SameSite의 상황을 재현할 수 있다.

크롬80부터는 기본이 SameSite=Lax상태가 되어버린다.

따라서 이렇게 해놓고 테스트를 했을 때 기존에 클라이언트들의 브라우저에 심어놓았던 쿠키를 아예 읽어올 수 없게 되었다.😱😱😱😱

 

그럼 어떻게 해결을 했나?

일단 유저들의 크롬 브라우저가 80으로 업데이트 되기전 클라이언트들의 브라우저에 심긴 우리 서비스의 식별 ID값에 "samesite=none", "secure"설정을 하여 동일한 값으로 쿠키를 덮어씌워줘야 했다. but, "secure"설정이 된 쿠키는 "https"가 설정된 서버에서만 읽을 수 있기 때문에 수 많은 광고주나 매체주에 심겨 우리쪽 서버를 호출하는 url이 http로 되어있을 경우 읽지 못하는 문제가 발생할 수 있었다. 이에 서버 자체적으로 http로 들어오는 요청을 https로 리다이렉트 시키도록 하였다.

추가 검토사항으로는 구글이 크롬관련 작성한 문서에는 다음과 같이 씌어져 있다. 

Versions of Chrome from Chrome 51 to Chrome 66 (inclusive on both ends).
These Chrome versions will reject a cookie with `SameSite=None`

즉, 크롬버전 51~66사이의 버전에서는 우리가 아무리 쿠키에 'SameSite=None', 'secure'설정을 한다고 하더라도 reject시켜 버린다는 것이다....

https://www.chromium.org/updates/same-site/incompatible-clients

 

SameSite=None: Known Incompatible Clients - The Chromium Projects

Home of the Chromium Open Source Project

www.chromium.org

그래서 어떡하지라는 생각이 들어 일단 우리 서비스에 요청오는 request들의 user-agent데이터를 기반으로 해당 버전에 속하는 요청이 얼마나 되는지 확인해보았다. 그랬더니 다행히도 해당 버전으로 부터 오는 요청은 1~2%내외였고 이 1~2%를 위해 무엇인가를 작업하기엔 trade-off가 되는 것들이 너무 많았다. 서버에서 하나 같이 user-agent의 버전을 확인해 해당 버전에서는 별도의 처리를 해주어야 했고 결국에 해당 버전에서 SameSite=None을 reject시켜버리기 때문에 손을 쓰기 힘든 상황이었기에 해당 버전을 위해 별도의 처리는 따로 하지 않기로 결정되었다.

그리고 스프링, 자바 어플리케이션에서 많이 사용하는 javax.servlet.http.cookie class에서는 SameSite관련 API를 지원하지 않기 때문에 SameSite속성을 추가하기 위해서는 HttpServletResponse 객체에 Set-Cookie헤더(header)를 추가해서 처리했어야 했다.

어플리케이션 사이드나 Web Server설정 관련해서 처리한 부분은 잘정리된 포스팅이 있어 해당 블로그를 참고하면 좋을 것 같다.👍(굉장히 잘 정리되어 있다.)

https://ifuwanna.tistory.com/223

 

Cookie SameSite 설정하기 (Chrome 80 쿠키 이슈)

20년 2월 4일 릴리즈된 구글 크롬(Google Chrome)80버전부터 새로운 쿠키 정책이 적용 되어 Cookie의 SameSite 속성의 기본값이 "None"에서 "Lax"로 변경되었습니다. SameSite 를 None 으로 설정할 경우 모든 도..

ifuwanna.tistory.com

작업을 하며 느낀점은....구글이 갑이다....지금도 구글의 영향력이 쌔지만 앞으로는 점점 더 그 파워가 막강해질것이다....그럼 구글 주식을 사야겠다😅......여기서 이만...

반응형
반응형

브라우저에서 특정 사이트를 접속 할 때 브라우져는 어떻게 해당 도메인에 해당하는 IP를 어떤 순서로 찾을까????

 

1. 먼저 브라우저는 Local Cache를 검색한다.

 

2. 그리고 hosts 파일을 검색하여 찾는다. 

 

3. 위의 두 경우에 해당하는 도메인이 없는경우 그 때

DNS(Domanin Name Service)서버에 요청하여 해당 도메인의 IP주소를 받게된다.

 

그래서 보통 테스트 할 때

 

기존 naver.com DNS에 등록되어 있는 도메인의 ip가 323.5.2.1일지라도 

내 로컬 피시, 리눅스 환경에서 hosts파일에 naver.com 127.0.0.1로 등록해 놓게 되면

DNS에 가기전에 hosts파일을 먼저 뒤지기 때문에 127.0.0.1 IP로 요청이 가게 되는 것이다.

(보통 개발하다 보면 특정 도메인 테스트를 위해 이런 방법을 쓰곤 한다.)

반응형
반응형

Mac에서 인텔리제이(IntelliJ)를 사용하시는 분들이라면 무조건 겪어 보셨을거다..(분명해...)

Action검색 : Ctrl + Shift + a (execute maven, execute gradle 등등) 기본 액션을 편하게 해주는 단축키

 

근데 짜증나게도 여러번 단축키를 누르다 보면...

action창이 뜨지 않고 아래와 같은 이상한 노란 메모장같은 화면이 뜬다....(apropos exe - 80 x 48)

경험해보신분들 있죠???

 

해결책

해결법을 알려드리려 한다. MAC에서 제공하는 단축키와 겹치다 보니 아래와 같이 해당 서비스를 disable해주어야 한다.

시스템환경설정 -> 키보드 -> 단축키(탭) -> 서비스 -> 터미널 man페이지 인덱스 검색 => 비활성화(체크 해제)

터미널에서 man 페이지 인덱스 검색 체크를 해제해주어야 한다.

 

체크를 해제 해주게 되면 그 이후 부터는 노란 메모장을 더 이상 마주하지 않을 것이다^_^

반응형
반응형

hadoop streaming, spark batch작업을 하다보면 보통 쉘스크립트로 해당 배치를 동작시키는 경우가 많다.

 

이 때 원하는 데이터가 없어 배치 작업이 정상적으로 동작하지 않는 경우가 있다.

 

보통은 해당 파일이 없으면 안돌아야하는게 맞지만 하루 하루 누적으로 쌓이는 데이터(어제, 그제 데이터와 별차이없는)가 없는 것 때문에 

 

중요한 배치작업이 돌지 않아 문제가 발생할 수 있다.

 

그렇기 때문에 쉘스크립트로 원하는 데이터가 있는 디렉터리의 최신 파일을 가져오는 스크립트를 작성해보았다.

 

 

get_recent_file 메서드에 최신 데이터를 가져오고 싶은 direct의 path를 전달해주면 된다.
해당 method에 direcotry parameter를 넘겨주고 최신 파일 경로를 받아 recent_file_path에 저장한다.

 

옵션에 대한 설명이다. 

hdfs dfs -ls -R ${DIR} : gives all dirs recursively
grep "^d" : gives only directories
sort -k6,7 : sorts them by modification time
tail -3 : gives listing for last 3 modified directory
tr -s ' ' : some formatting
cut -d' ' -f8 : gives only directory path
sort -r : result reverse sotring

 

쉘스크립트를 잘쓰면 프로그래밍삶이 좀 더 윤택해질 것 같다.

 

틈틈히 보고 유용한 스크립트를 작성해서 나만의 유틸 스크립트들을 만들어 나가면 좋을 것 같다.

반응형
반응형

Mac에서 디렉토리별 사이즈를 쉽게 확인 할 수 있는 유틸리티 프로그램을 소개합니다.

 

Disk Innvenntory X

설치를 하시고 실행을 하게 되면 다음과 같이 디렉토리별 용량을 보여줍니다.

 

해당 앱을 사용하여 예상치 못한곳에서 디스크를 공간을 많이 차지하고 있는 불필요한 데이터를 삭제해주면 

 

좀 더 쾌적하게 Mac을 사용하실 수 있을 것 같습니다.

반응형
반응형

보통 어플리케이션 CPU, Load Average가 비정상적으로 높게 튈 때

스레드덤프(thread dump)를 떠서 많이들 보실 텐데요.

jstack PID > 파일명.dump

이렇게 생성된 dump파일을 콘솔에서 분석하기는 매우 힘이듭니다.

이런 덤프파일을 무료로 분석해주고 이쁜(?) 시각화까지 진행해주는 사이트 공유드립니다.

https://fastthread.io

 

fastthread.io

Beyond APM Application Performance Monitoring (APM) tools are great at telling that your application's CPU spiked up by x%, your memory degraded by y%, your response time increased by z milliseconds. But it won't tell you what caused the CPU to spike? what

fastthread.io

해당 사이트에 들어가셔서 dump뜬 파일을 업로드 해주시기만 하면

다음과 같이 분석된 자료를 보기좋은 UI를 통해 제공받으실수 있습니다.(Time Waiting 안습 ㅠ.ㅠ, 분석도중 올립니다)

 

그럼 저는 다시 분석하러~뿅~!

반응형
반응형


클린코드 책에서 읽은 '깨끗한 테스트코드 5가지 규칙(FIRST)'에 대해 포스팅 남겨보겠습니다.


프로그래밍을 할 때 어떻게 보면 테스트 코드의 작성은 가장 기본이면서 중요하다고 할 수 있는데요.


TDD방식의 프로그래밍까지는 아니더라도 테스트코드를 작성해주면 서비스에서의 버그를 확실히 줄여줄 수 있고


기능 추가시에도 빠르게 테스트해보고 적용하는 등 이점을 많이 가지고 있는데요. 


그렇다면 어떠한 기준과 방식으로 테스트코드를 작성해야하는지 5가지 규칙을 보시도록 하겠습니다.


[클린코드] 깨끗한 테스트코드 5가지 규칙(FIRST)

빠르게(Fast)
테스트는 빨라야 한다. 테스트는 빨리 돌아야 한다는 말이다. 테스트가 느리면 자주 돌릴 엄두를 못 낸다. 자주 돌리지 않으면 초반에 문제를 찾아내 고치지 못한다. 코드를 마음껏 정리하지도 못한다. 결국 코드 품질이 망가지기 시작한다.


독립적으로(Independent)
각 테스트를 서로 의존하면 안 된다. 한 테스트가 다음 테스트가 실행될 환경을 준비해서는 안 된다. 각 테스트는 독립적으로 그리고 어떤 순서로 실행해도 괜찮아야 한다. 테스트가 서로에게 의존하면 하나가 실패할 때 나머지도 잇달아 실패하므로 원인을 진단하기 어려워지며 후반 테스트가 찾아내야 할 결함이 숨겨진다.


반복가능하게(Repeatable)
테스트는 어떤 환경에서도 반복 가능해야 한다. 실제 환경, QA 환경, 버스를 타고 집으로 가는 길에 사용하는 노트북 환경(네트워크가 연결되지 않은)에서도 실행할 수 있어야 한다. 테스트가 돌아가지 않는 환경이 하나라도 있다면 테스트가 실패한 이유를 둘러댈 변명이 생긴다. 게다가 환경이 지원되지 않기에 테스트를 수행하지 못하는 상황에 직면한다.


자가검증하는(Self-Validating)
테스트는 bool값으로 결과를 내야 한다. 성공 아니면 실패다. 통과 여부를 알리고 로그 파일을 읽게 만들어서는 안 된다. 통과 여부를 보려고 텍스트 파일 두 개를 수작업으로 비교하게 만들어서도 안 된다. 테스트가 스스로 성공과 실패를 가늠하지 않는다면 판단은 주관적이 되며 지루한 수작업 평가가 필요하게 된다.


적시에(Timely)
테스트는 적시에 작성해야 한다. 단위 테스트는 테스트하려는 실제 코드를 구현하기 직전에 구현한다. 실제 코드를 구현한 다음에 테스트 코드를 만들면 실제 코드가 테스트하기 어렵다는 사실을 발견할지도 모른다. 어떤 실제 코드는 테스트하기 너무 어렵다고 판명날지 모른다. 테스트가 불가능하도록 실제 코드를 설계할지도 모른다.


규칙 하나하나 너무나도 중요한 얘기들인 것 같습니다. 이 규칙을 염두해두시고 프로그래밍을 하신다면

좀 더 안정적인 서비스를 하시는데, 작성한 코드를 테스트하는데 드는 시간을 많이 줄일 수 있을 것 같습니다!

반응형

+ Recent posts