unix sftp 계정은 있는데? 인증은 됐는데? 접속이 끊기네?


작성자 : 김민석 ( lemonfish at g m a i l dot com )
UNIX류 OS에서는 보통 실제 터미널 접속이 필요한 사용자가 아니라면 nologin 쉘을 할당한다. 예를 들어 특정 데몬 응용을 위해 한정된 권한의 계정을 생성하고 관리가 필요한 경우에는 su 커맨드를 통해 해당 계정으로 전환한 뒤 작업하는 식이다. 그런데!

어느날 들려오는 장애소식! sftp를 통해서 파일을 주고받도록 되어 있는데 상대쪽에서 접속이 안된단다.

  • 그동안 잘 되던거라 하고
  • ssh 설정은 건드린 사람도 없다는데
  • 방화벽도 정책이 바뀐게 없단다
  • 22번 포트로 연결도 원활한데
  • 외부망에서 VPN 으로 붙고 있는게 살짝 거슬리지만 그게 문제는 아닌것 같고
  • 서버쪽 로그를 보니 접속 기록이 있기는 있다
  • 내부망에서 다른 계정으로 테스트 해보니 어랍쇼? 잘되네.
  • 그쪽에서 접속시 사용하는 계정으로 붙여보니까... 어? 안붙네?
  • 서버의 iptables 에 등록된 내용도 없고.
  • 계정 아이디나 비번도 정확하다.
  • 유독 그놈만 안되는 이유는?

위의 상황을 토대로 어떤것부터 의심해야할까?
처음에는 네트웍쪽에 작업이 있었겠지. 내지는 보안감사 지적이라도 나와서 서버 설정등이 바뀐게 아닌가 했다. 보통 추궁하면 "아~~ 그러고보니" 라며 실토하기도 하니까. 그런데 다들 아니라고 하니. 이건 무슨 밀실살인도 아니고. 아리송한 상황이다.

마냥 손 놓고 있을 수 없으니 담당자는 서버 재부팅부터 시도. 그래도 증상은 똑같다. 그럼 일단 ssh 로그 레벨부터 올려보자. 설정 바꾸고 서비스 재시작하는데 어랍쇼? 이젠 터미널도 안붙네? 망했다... 설정 잘못 넣었나비네. 서버실로 후다닥 가서 콘솔 통해서 설정을 다시 수정하고 재시작. 휴... 되네. 다시 자리로 와서 접속안되는 그 계정으로 접속을 시도하며 서버 로그를 확인해본다.

  • 연결 시도
  • 인증 요청
  • 인증 오키
  • 사용자에의해 연결종료

엥? sftp 클라이언트에서 연결을 종료했다고? 난 캔슬 누른적 없는디? 무슨 지연 차단 기능이 있는 방화벽이 있나... 붙었다가 종료될건 머람?
싸움이 나면 한쪽 얘기만 듣지말고 양쪽 얘기를 다 들어봐야한다고 했다. 그래서 sftp 클라이언트의 로그레벨을 높여봤다.

  • 연결 시도
  • 인증 요청
  • 인증 오키
  • 메인 채널 생성 요청
  • 메인 채널 생성 실패
  • 폴백 채널 생성 요청
  • 서버에서 종료 시그날이 날라옴
  • 종료

머야이건.... 서버 지가 그래놓고 클라이언트가 끊었다고 구라를 치네. 하여간 기계는 믿지말아야지. 로그 메시지를 토대로 구글신에게 물었다. 딱히.... 머가 없다. 한페이지 두페이지 글을 읽다가 winscp 사이트 FAQ에 접속 안될경우 원인이 정리된 글이 있더라. 곰곰히 읽다보니 헐... 어떤 sftp 는 사용자 계정이 nologin 쉘같이 커맨드를 실행할 수 없는 쉘일 경우 접속이 안된단다. 아차....

passwd 파일을 확인하니 그 계정이 nologin 쉘이네.... 후다닥 bash 로 일단 이젠 될거라고 통보했다. 한 숨은 돌렸는데 의문이든다. 원래부터 sftp 만 쓰는 계정에도 정상 쉘이 할당되어야 했었나? 안그랬던것 같은데? 임시조치는 했더라도 제대로 다시 설정하기위해 관련 정보를 찾아보니.
엄훠나~ 이렇게 잘 정리된 글이!
저 글을 찾기전에 다른 글들을 통해 왜 안되고 왜 저렇게 하면 되는지에 대한 지식은 갖춘 덕분에 쉽게 이해가 가더라. 역사가 있는 녀석이었어...



후일담인데 나중에 정상화 되고 밝혀진 바에 의하면 우리는 sftp 를 22번 포트에서 돌리고 저쪽은 ftp 21번을 접속하고 있었단다... 뻔질나게 해결 했더니 남의집 외양간을 고친격!! 크하하하하하


by killy | 2017/07/27 12:54 | 삽질 | 트랙백 | 덧글(0)

Natural-JS 아직 갈길이 멀지만 쓸만한 국산 자바스크립트 프레임웍


작성자 : 김민석 ( lemonfish at g m a i l dot com )
Natural-JS 라는 Javascript Framework 이 있다.

원 개발자의 네이티브한 발음에 따르면 "네후럴 제이에스" 란다. 살짝 욕같이 들리는데 기분 탓이리라.

정확히 언제부터인지는 모르겠지만, 본인 경험상 아마 2006년쯤 이었던 것 같다. jQuery가 세상에 처음 나온 게 2006년 경이였으니 그 이후가 맞겠지. AJAX의 급부상과 함께 온갖 Javascript 라이브러리(프레임웍)들이 해외에서 쏟아져 나오며 그 멋들어진 기능을 자랑했는데 당시 국내에서는 딱히 그런 걸 개발해서 공개한 곳은 없었던 것(NHN에서 개발한 Jindo 가 유일했을 듯) 같다. 있었다고 해봐야 window scope에 묶인 유틸성 함수들의 집합이었으니 딱 봐도 엉성하기 그지없었지. 어쩌면 지금처럼 코드를 공유하기 위한 다양한 서비스들이 당시에도 있었다면 은둔 고수들이 가내수공업으로 개발한 씨크릿웨폰이 국내에도 많이 등장했었을지도 모르겠다.

어쨌든, Nescape에서 서버와 클라이언트 통신량을 줄여보고자 만들었던 LiveScript가 시대의 흐름을 타고 "javascript 실행 안 함 이라는 브라우저의 옵션은 도대체 왜 있는 거냐?" 는 말이 나올 정도로 필수가 되어 버렸다. 

요새 누가 쌩짜로 웹개발 합니까? 글치? 
Bootstrap, AngularJS, Dojo, Ext JS, Vue.js, React, ... 나열하려면 한도 끝도 없을 것 같은 잘 만들어진 프레임웍(라이브러리)의 홍수! 각각 Killing Feature가 있고 잘만 다루면 서로 Mix 해서 쓰는 것도 가능한 미남미녀들이 판치는 부조리한 세상 같으니라고! 세상이 좋아져도 너무 좋아진 게 아닌가 싶다. 

잡설이 길었지만 그 와중에 또 하나의 프레임웍(라이브러리)을 소개해본다. 

물론, 제목에도 썼듯이 이미 나와 있는 것들보다 강려크하냐? 그렇지 않다. 그러면 열라 풍부한 컴포넌트가 있느냐? 그렇진 않다. 그러~나아~ 화개장터 노랫말 처럼 있을 건 다 있고, 없을 건 없다. 그래서 평을 곁들여 나열식으로 소개하자면 (특장점이 아니라) 

  • Natural이라는 이름처럼 있는 그대로의 HTML을 쓸 수 있다. (원 개발자는 디자인/퍼블과의 협업이 용이하다는 표현을 쓰더만. 이건 써봐야 느낌이 온다.)
  • 프레임웍에 덤으로 UI 컴포넌트(그리드, 팝업, 달력, 탭 등등)도 제공한다. 
  • 그리드 컴포넌트의 경우 대량 데이터에도 쓸만한 성능을 제공한다.
  • 제공되는 UI 컴포넌트에 한해 양방향 바인딩을 제공한다.
  • 혼자 개발한 것 치고는 퀄이 상당히 높다. (아~ 이건 기능이 아니군요. ㅎ)
  • 문서화가 되어 있기는 하다. (개인차가 있을것 같은데. 혼자 만들어서 그런지 예제가 좀 부족한 편)
  • 사용된 사례가 있다. 
  • 원 개발자가 상당히 열심이다. (본인이 알기로 7년 정도 된 것 같은데 꾸준히 업글 중)
  • 진입장벽이 낮다. (요즘 나온 프레임웍들을 배우기 전에 중간 단계로 배워봄직도 하다)
  • jQuery 기반이고, 의외로 타 라이브러리들과 접붙이기가 쉽다. (only 본인 생각)
  • SI에 맞는 프레임웍(라이브러리)가 아닌가 하는 생각이 80% 정도 든다.
  • SPA 개발에도 쓸 수 있는 수준이다.
  • UI 컴포넌트를 제외하고는 소스가 방대하지 않기 때문에 분석하고 커스터마이징하기 적당하다.
  • 동적 요소들의 가비지 컬렉션도 고려했단다.
  • SI쪽 적용 사례가 많은지 공통적으로 뭔가 처리하기위한 기능들이 존재한다.

요약해보자면. 기본적인 기능은 거의 다 갖춰진 국산 오픈소스 자바스크립트 프레임웍(라이브러리) 되시겠다.
당장 필드에서 써도 문제가 없는 수준인데. 눈이 높은 웹 개발자들은 훠~이 훠~이. 다른거 쓰시면 되고.
초중급 개발자들이 무리없이 익히고 실무에서 쓸 수 있는 프레임웍(라이브러리)이라고 보면 좋을 것 같다. 
3~4년 전부터 불어온 Active-X 걷어내기 바람에 X-Internet 제품 팔던 벤더들도 HTML5 기반 제품을 내어놓는데 툴만 없다 뿐이지 수준은 그 제품들과 비슷하다고 본다. 

최신 트렌드를 쫓아가는 사람도 있겠지만, 프레임웍(라이브러리)의 부족한 부분을 채워가며 스스로를 업그레이드해나가는걸 즐기는 사람이라면 한 번쯤 써보라고 권해본다. 컨트리븉과 피드백은 언제든 환영한다니 자세한건 git에가서 보시라. 

흥해라~ 국산 프레임웍~


by killy | 2017/07/26 16:38 | 스크립트 | 트랙백 | 덧글(0)

Oracle Statement Cache 설정 시 메모리 증가 이슈


작성자 : 김민석 ( lemonfish at g m a i l dot com )
JDBC를 이용해 데이터베이스를 다룰 때 일반적으로 사용하게 되는 클래스는 PreparedStatement다. 
응용에서의 주된 사용 패턴은 아래와 같다. 
  1. 바인딩 변수를 포함한 쿼리로 해당 클래스의 객체를 생성
  2. 바인딩 변수에 실제 값을 바인딩
  3. 쿼리 수행
  4. 2~3을 반복
  5. 종료

바인딩 변수를 사용해 쿼리의 형태는 유지한채로 조건만 달리하여 수행함으로서 아래와 같은 이점이 생긴다. 

  1. 데이터베이스 서버 입장에서는 바인딩 변수를 제외한 부분이 동일할 경우 실행계획의 재활용이 가능
  2. 응용 서버 입장에서는 Statement 클래스 대비 객체를 한번 생성하여 재활용할 수 있으니 객체 생성 비용면에서 절감

하지만 또 다른 트랜잭션이 발생할 경우 매번 1~5를 반복하기 때문에 이 또한 PreparedStatement의 생성과 초기화라는 비용이 발생하게 된다. (이는 일반적으로 Pooling이 이뤄지는 Connection 객체를 의미하지 않음) 

그래서 많은 Connection Pooling 라이브러리들 혹은 WAS들은 ( Weblogic, JBoss, WebSphere 등) Statement Cache 기능을 제공한다. 
이는 Pooling된 각각의 Connection 마다 지정된 갯수의 PreparedStatement를 보관할 수 있는 기능이다. 즉, 보관된 PreparedStatement는 각각의 트랜잭션이 발생할 때마다 생성과 초기화 없이 재활용이 가능하다. Connection도 재활용하는데 PreparedStatement라고 못할까.

위의 내용을 토대로 아래와 같은 간단한 공식이 나온다. 

어느 시점에 존재할 수 있는 캐싱된 PreparedStatement 의 최대 갯수 =
Connection Pool 크기 X Statement Cache 크기

예를 들어 Connection Pool Size가 20 이고, Statement Cache 크기를 50으로 잡았다면 최대 1000개의 PreparedStatement가 캐싱된 채로 메모리에 존재할 수 있다. 

지금까지의 내용 만으로는 메모리 이슈가 될만한 내용은 없다. 고작 PreparedStatement 객체 1000개가 머 별거라고... 이슈가 될 수가 없다. 

하지만,.... 여기서 Oracle의 구현방식으로 인한 문제가 발생한다. 

Oracle에서 제공하는 JDBC driver의 PreparedStatement 구현체는 T4CPreparedStatement인데 이 클래스는 PreparedStatement의 특성상 발생하는 반복 실행을 최적화하기위해 최초 실행 시 생성되는 ResultSet 정보를 토대로 버퍼를 생성한다. 이 때 버퍼의 크기를 산정하는 기본 공식은 아래와 같다.

버퍼 크기 = ResultSet에 포함된 컬럼의 사이즈 총합 * PreparedStatement에 지정된 기본 패치 사이즈

ResultSet에 포함된 컬럼의 사이즈 총합을 Oracle 샘플 스키마인 HR의 EMPLOYEES 테이블을 변형해서 예로 들어 보면

employee_id varchar2(10) -> 10byte 
first_name varchar2(100) -> 100byte
last_name varchar(100) -> 100byte
email varchar(200) -> 200byte
phone_number varchar(20) -> 20byte
hire_date date -> 7byte
job_id varchar2(10) -> 10byte
salary number(8,2) -> 21byte (number는 일단 최대치로 잡아본다)
commission_pct number(2,2) -> 21byte
manager_id varchar2(10) -> 10byte
department_id varchar2(10) -> 10byte 

509byte가 나온다. 여기에 기본 패치 사이즈 50으로 둘 경우를 적용해보면 버퍼의 크기는 509 * 50 = 25450byte 이다. 계산을 간편히 하기위해 25KiB 라고 하면 앞서 PreparedStatement 객체의 사이즈가 이 값이 된다. 

1000개의 PreparedStatement가 캐싱됐을 때 

1000 X 25KiB = 약 25MiB 

별 무리가 없어 보인다. 하지만 실무에서는 훨씬 큰 컬럼들이 존재하며 최대 컬럼사이즈의 합이 8KiB가 될 수 있음을 고려해야한다. 이를 토대로 실무의 사례를 들어본다.

어떤 WAS에 설정된 데이터소스 목록
A 데이터소스 : Pool Size 30, Statement Cache Size 100, 주요 테이블의 컬럼사이즈 합 평균 2KiB, 패치사이즈 50
B 데이터소스 : Pool Size 30, Statement Cache Size 100, 주요 테이블의 컬럼사이즈 합 평균 0.5KiB, 패치사이즈 50 
C 데이터소스 : Pool Size 30, Statement Cache Size 100, 주요 테이블의 컬럼사이즈 합 평균 4KiB, 패치사이즈 50

A에서 필요로 하는 메모리 약 300MiB ( 30 X 100 X ( 2KiB X 50 ) ) 
B에서 필요로 하는 메모리 약 75MiB ( 30 X 100 X ( 0.5KiB X 50 ) ) 
C에서 필요로 하는 메모리 약 600MiB ( 30 X 100 X ( 4KiB X 50 ) ) 
  
총합이 975MiB에 달한다. 응용에서 사용되는 메모리를 산정할 때 고려하지 않았던 큰 변수라고 볼 수 있다.
최초 응용의 메모리 산정 시 혹은 가용한 메모리 내에서 설정 변경 시 영향을 예상하기 위해서는
아래의 공식을 응용(혹은 WAS)에서 사용하는 모든 데이터소스에 대해 반복 적으로 적용한 후 총 합을 구해보면 된다.

데이터소스를 통해 접근 가능한 테이블 중 자주 참조되는 테이블들의 평균 행 크기 X PreparedStatement fetch Size X Connection Pool Size X Statement Cache Size

by killy | 2014/11/12 11:08 | 트랙백 | 덧글(0)

◀ 이전 페이지          다음 페이지 ▶


rss

skin by FreeCssTemplates