Parameters

  • app_name : 애플리케이션 이름
  • cartridges : 생성할 애플리케이션에 추가할 카트리지 목록
  • scalable : 확장 여부(기본값 false)
  • available : HA 여부
  • init_git_url : 애플리케이션 템플릿 GIT URL
  • gear_profile, gear_size, default_gear_size : 기어 사이즈
  • config : 설정값
  • environment_variables : 환경 변수
  • initial_git_branch : init_git_url에서 사용할 브랜치

Preconditions
  • 애플리케이션 이름이 Blacklist에 등록되어 있는지 확인(OpenShift::ApplicationContainerProxy)
  • Git URL 스키마 확인(OpenShift::Git)
  • 카트리지 스펙 확인(CartridgeInstance)
  • 설정에서 HA가 비활성화 되어있는지 확인(Rails.configuration.openshift - allow_ha_applications)
  • 유저가 HA 애플리케이션을 생성할 수 있는 권한이 있는지 확인


프로세스 상세

  1. Gear 스펙 Hash Array 생성
  2. 지정된 이름의 도메인을 찾거나, 없을 시 생성
  3. 인증
  4. 권한 체크
  5. Application 모델 객체 생성
  6. config 타입 변환
  7. app에 user agent 정보 추가 - 로깅용..?
  8. 인스턴스 변수에 생성된 app 객체 설정
  9. 기어 최대 생성 수보다 많은 지 확인
  10. envorionment_variables 가져옴
  11. user environment variable 유효성 확인(Application.validate_user_env_variables)
  12. cartridge 탐색 및 다운로드(CartridgeCache.find_and_download_cartridges)
  13. 최대 스토리지 사용량 초과 확인
  14. 웹 프레임워크 유효성 확인
  15. 구 버전 카트리지 확인
  16. 요청 결과 생성
  17. 분석 데이터 트래킹(@analytics_tracker 인스턴스 변수)
  18. 카트리지 include
  19. 요청 결과 렌더



OpenShift 분석을 위해 (얕게라도) 알아야 할 것들


아키텍처

  • 아키텍처 설계
  • 아키텍처 문서화
  • 아키텍처 평가


클라우드

  • 클라우드 개념 및 아키텍처
  • CloudForms
  • OpenStack
  • HyperV
  • Xen Hypervisor


리눅스

  • User & Accounts Management
  • SELinux
  • CGroups
  • Shell Script
  • Docker
  • LXC
  • libcontainer
  • libvirt
  • iptables
  • 기타 리눅스 관리를 위한 명령어


언어

  • Ruby, Rails
  • Go


서버

  • DNS Binding
  • 네트워크 개념 전반
  • Routing
  • Load Balancing
  • Clustering
  • Sharding
  • Scaling (Up/Down, In/Out)
  • Redundancy


기타

  • CI(Jenkins or Husdon)
  • Maven


1. 프로젝트 트리(디렉토리)



2. 파일 포함 프로젝트 트리


'밤을 지새다 > OpenShift Origin' 카테고리의 다른 글

OpenShift Origin 설치 트러블 슈팅: Node  (0) 2014.09.22
OpenShift Node Host 설치 [1] - 작성 중  (0) 2014.08.18
OpenShift Origin V3  (2) 2014.08.14
ApplicationsController- create  (0) 2014.08.05
공부할 것들  (0) 2014.07.28

간단히 UML 다이어그램을 그릴 일이 있어 알아본 웹 다이어그램 드로잉 툴

많은 서비스가 나와 있겠지만 단순히 검색해서 상위에 나온 두 가지를 비교했다.

파워포인트를 써도 되었겠지만 좀 더 손쉽게 그리기 위해서이다 :)


1. Gliffy.com

UML을 포함해 순서도, 와이어프레이밍, 관계도 등의 작업을 할 수 있다. 

SVG, JPG, PNG  자체 포맷인 Gliffy로 저장할 수 있으며, 저장하거나 외부 이미지를 가져오려면 회원 가입이 필요하다. 가입은 무료.





2. Creately

Createle도 Gliffy와 비슷한 템플릿을 제공하며, 무료 회원 가입 후 로그인하여 저장 및 가져오기가 가능하다. 환경에 따라 다르겠지만 에디터 로딩은 Creately가 조금 더 느린 듯 하다.



설문 조사 폼을 만들이 있어서 작업 중에 설문 조사의 질문과 선택 옵션의 수는 가변적이므로 Parameter 컬렉션을 사용했다. 작업을 마무리 한 후 정상적으로 동작하는 지 테스트를 한 후 서버에 배포했다.


그런데.


이른바 "내 컴퓨터에서는 잘 되는데요?" 문제가 발생했다.


그렇다. 테스트를 할 때는 아무리 많은 질문과 옵션을 추가해도 잘 동작하던 것이, 서버에스는 IndexOutOfBound 예외를 내면서 설문이 제대로 처리되지 않는 문제가 발생했다.


설문 조사를 올리시는 분께서는 "음.. 7개가 넘어가면 설문 내용이 없어져요."라고 했고, 나는 "그럴리가 없다! 그 부분에 있어서 내 로직이 틀릴 리가 없다!" 라고 했다.

무지하면 용감하다더니, 어찌도 그리 당당할 수 있었을까? 다시 생각하니 부끄럽다.


서버에 배포된 설문 조사 폼을 확인해 보니, 정말 7개 이상으로 질문을 추가하면 죽는 것이 아닌가? 똑같은 설문 내용으로 내 컴퓨터(개발 컴퓨터)에서 테스트를 하니 "내 컴퓨터에서는 잘 된다."..


이 때까지는 자바스크립트로 설문 내용을 추가하는 부분에 이상이 있을 것으로 예상했다. 그런데 역시 이때까지는 Integer의 범위를 벗어나는 것도 아니고, 왜 하필 7개일까? 라며 이상하게만 생각하고는 자바스크립트 부분을 확인해 봤지만, 역시 이상은 없었다.


그러다 문득 톰캣 이 자식이 방해 공작을 하는 것이 아닐까 하는 생각에

"tomcat post form input limit length"를 키워드로 검색하니 한 블로그 글이 검색됐다.

그리고 그 글에는 내 문제의 원인이 무엇인지 명확하게 나와있었다. 그렇다. 파라미터의 수를 제한하는 설정이 있었던 것이다.


테스트 서버의 톰캣 설정은 그 파라미터 갯수 제한이 무한대라서 파라미터 갯수의 제한이 있다는 걸 모르는 상태에서는 그런 문제가 발생할 지 전혀 예측할 수 없었고,

실서버에서는 maxParameterCount="50" 으로 50개의 제한이 있었다.


질문 하나를 구성하는 속성은 제목, 질문 타입, 옵션 5개로 7개였으니, 톰캣이 수용할 수 있는 최대 질문의 수는 7개가 되는 것이고, 그 수 이상이 되면 서버가 빵~ 예외를 터뜨린다. 여태까지 파일 업로드 크기의 제한이 있는 줄은 알았지만, 파라미터의 수에 제한이 있을 줄은 몰랐다. 폼 파라미터의 갯수 및 크기 제한을 하는 설정은 아래와 같다.


server.xml 파일


maxParamterCount 속성은 폼 파라미터의 최대 수이고, maxPostSize는 폼의 최대 전송 용량(byte)이다. 값을 -1로 하는 경우 제한을 두지 않도록 한다.



"내 컴퓨터에서는 잘 되는데요?"

"님 컴퓨터에서도 잘 돌아가요"가 될 수 있도록 내가 사용하는 것들을 잘 알고 써야겠다.

다르다.

몰랐다.

그래서

한참을

돌았다.

그런데.

똑같네?

다른줄

알았다.


이게 무슨 소리지..

처음엔 내가 잘못 알고 있나? 싶었다. 


어떤 숫자가 있는지 없는지만 확인하면 되는 로직에 HashSet<Integer>를 사용했다.

거기에 0부터 24까지의 정수를 추가했다고 하면,

위와 같은 코드가 될 것이다.


그리고 저 아래와 같은 코드를 실행하면 출력 결과가 true인 것은 자명하다.


System.out.println(set.contains(1));


그렇다면 1 대신에 1l 또는 (long)1을 넣으면 true일 것이라고 예상했다.

헌데 결과는 false 이다.

내가 아는 바로는 int 의 표현 범위 내에서 int 와 long은 같은 hashCode를 가진다.

그래서 확인을 해봤다.


System.out.println(Integer.hashCode(1));

System.out.println(Long.hashCode(1));


실행 결과는 생각한대로 둘 다 1이다. int 범위 내의 어떤 값이든 그렇다.

그리고 정수 기본타입은 자신의 값이 곧 자신의 해시코드라고 알고 있었는데,

HashSet 이란 놈이 이렇게 배신을 할 줄이야.

이름만 보면 Set에 포함된 엘리먼트들의 유일성을 Hash 값으로 판단한단 말이 아닌가?


HashSet의 코드를 뜯어보니 HashSet은 내부적으로 엘리먼트의 저장을 HashMap을 사용한다.

왜인지는 모르겠다. 코드의 중복을 줄이기 위해서인지? 구현 편의인지.

HashMap은 Entry를 사용하니까 엘리먼트 하나를 저장하는 것보다 키, 밸류를 저장하는 게 손해아닌가..?

HashSet에서는 HashMap의 Entry의 value 값에 빈 Object객체를 넣는다.

빈 Object 객체는 static 변수로 선언되어 있다.

(private static final Object PRESENT = new Object();)


어쨌거나 어디서부터 잘못 이해하고 있는지 확인 하기 위해서 HashSet에서 contains 메서드가 호출하는 HashMap.containsKey 메서드를 살펴봤다.

containsKey에서는 map의 get메서드가 호출하는 getEntry(key)를 호출하고, key를 이용해서 Entry를 가져오지 못하면 null일 때 containsKey는 false가 되고 있으면 true가 된다.

그럼 getEntry에서는 무엇을 하느냐? key의 해시값을 이용해서 HashMap이 가지고 있는 hashSeed값과 적절한 연산을 통해 해시 값을 만들고, 이 해시를 이용해서 해시 테이블에 있는 엔트리를 찾는다.


결국 hash값으로 찾는게 맞단 소리고, HashMap의 hash 메서드의 인자를 long과 int 타입으로 테스트해보니 값이 같을 때 같은 값이 나온다.


여기까지의 결론으로는 결국 set.contains(1) 이나, set.contains((long)1) 이나 같은 결과를 보여야 하는게 정상인데..

왜 false라는 값이 나올까..?? map과 set을 좀 더 파헤쳐봐야겠다.



검색 중 Why you should not user HashSet/HashMap for Integer number 글 발견..

관련있는 글

안드로이드에서 Gson을 이용해서 서버에서 받은 Json 문자열을 파싱 할 때

필드 중에 Date 타입이 있다.


Gson에서 사용하는 날짜 포맷을 "yyyy-MM-dd HH:mm:ss:SSS z Z" 로 해두고, 서버쪽도 같은 포맷으로 날짜를 문자열로 변환하도록 해두었다.


서버의 타임존을 UTC로 사용하다가 편의상 KST(한국 표준시)로 변경해서 사용하니

받은 날짜의 문자열의 포맷은 아래처럼 된다.


"2014-03-15 21:07:32:221 KST +0900"


정확하게 멀쩡해 보이는 이 문자열을 Date 타입으로 변환하려면 오류가 발생한다.

Date 포맷이 아니라고 한다.

문제는 타임존을 의미하는 KST 부분,

까닭은 안드로이드에서 KST 타임존을 지원하지 않는다.


시간 설정을 한국, 서울 시간으로 해두어도 GMT로 적용되어 간다.


TimeZone.getAvailableIDs()나, TimeZone.getAvailableIDs(int rawOffset)을 이용해서 확인해보고 사용할 것을 그랬다. 라는 생각은 지금에서야 드는 생각이고, 저 예외가 생길 때는 도대체 정말 멀쩡한 문자열이 파싱이 안되서 미치는 줄 알았다. KST가 안되는 줄 꿈에도 몰랐다.

안드로이드에서 테스트하기 귀찮아 그냥 자바 프로젝트에서 같은 문자열을 Date 객체로 변환했을 땐 아~주 문제 없이 잘 파싱이 되었으니깐 말이다.


Moneycomb 진행하면서 시간의 표현에 대해서 많이 배우고 있다.


Ubuntu 위에서 톰캣을 이용해서 웹 애플리케이션을 돌리고 있는데, 이놈의 시간대가 바뀌질 않는다.

"리눅스 시간 설정"을 키워드로 해서 검색한 글들을 참고해서 시스템의 타임존 설정 및 시간 동기화를 해보고,

톰캣에 JAVA_OPTS를 추가해서 톰캣의 타임 존을 설정해보기도 했으나 효과가 없다.

(startup.sh에 JAVA_OPT 변수를 추가한 것은 적용이 전혀 되지 않는 듯 하다. 아마 잘못해서 그런 거겠지만..쉘에서 date 명령어를 실행하면 원하는 대로 한국 시간대에 맞춰 KST로 표현이 되지만, 서버에서 출력하는 타임존은 계속 UTC다.


여러 방법을 시도하던 중에 dpkg-reconfigure tzdata 명령어를 이용해서 아시아/서울로 지정하니, 웹 서버에서 출력하는 시간대가 KST가 되었다.  (이 전에 /usr/share/zoneinfo에 있던 Asia/Seoul 타임존을 /etc/localtime에 링크 했었으나 원하는 대로 동작하지 않았다.)


dpkg-reconfigure tzdata 를 이용해서 서버의 로컬 시간대 설정


date 명령어에서 사용하는 timezone 정보와 자바(혹은 톰캣)에서 사용하는 timezone의 참조 하는 설정 값이 서로 다른가 보다. 이래서 모르면 몸이 고생한다. 얼마나 헤매었는지 모르겠네.


자바(혹은 톰캣)에서 사용하는 타임존의 설정은 /etc/localtime을 참조한다.

$ more /etc/localtime

타임존을 서울로 수정한 후 위 명령을 수행하면 KST-9를 확인할 수 있다.


현재는 해외에서 접속할 일이 없는지라 서버의 시간대를 한국표준시로 설정했지만 나중에 국제화나 지역화를 고려한다면 시간대에 대해 정확하게 이해하고서 사용해야겠다.


References...

리눅스 시간 설정(ikinox님) - http://ikinox.tistory.com/70

http://hacksforge.com/How-to-change-time-zone-in-Ubuntu-Linux.html

http://www.christopherirish.com/2012/03/21/how-to-set-the-timezone-on-ubuntu-server/

https://mail-archives.apache.org/mod_mbox/tomcat-users/200501.mbox/%3C45b72a5705012008352dcc3a39@mail.gmail.com%3E


  Moneycomb 서비스를 개발하면서 메인 도메인인 nabakcompany.com에 서브 도메인으로 moneycomb.nabakcompany.com을 추가하고, 같은 메인 도메인과 같은 웹 서버에서 리스닝 포트 번호만 달리해서 서비스를 하려고 했는데, DNS에 대한 이해가 부족한 탓인지 그게 안된다는 걸 이제야 알았다. 그러니까 포트 번호를 숨길 수는 없다.


  톰캣 문서와 검색을 통해서 서버 아이피가 동일하고, 서브 도메인이 다른 경우에는 웹 서버에서 가상 호스트를 추가하여, 각각의 서브 도메인에 대해 각각의 웹 애플리케이션을 제공할 수 있다는 것을 알게 되었다.


  현재 서버는 Apache 웹 서버 없이 Apache Tomcat 7로만 구동되고 있다.


| server.xml 파일에 호스트 추가

  $CATALINA_HOME 에 위치한 conf 폴더 내에 서버 설정을 위한 server.xml 파일이 있다. 호스트를 추가하기 위해서는  server.xml 파일을 아래와 같이 수정한다.


  Engine 엘리먼트 내에 Host 엘리먼트를 추가한다.

  톰캣을 설치한 후 설정을 수정하지 않았다면 파일의 끝부분에 localhost Host가 있다. 서브 도메인을 위한 호스트는 그 아래에 추가한다.


  Host의 속성으로 name에 DNS 호스팅 서비스(혹은 네임 서버)에서 추가한 서브 도메인을 입력하고, appBase는 웹 애플리케이션이 위치할 디렉토리를 지정한다. 상대경로로 입력할 경우 $CATALINA_HOME 아래가 기준이 된다.

다른 속성에 대한 설명은 아파치 톰캣7 문서를 참고.



| 디렉터리 및 ROOT.xml 파일 추가

  톰캣 5 이하에서는 server.xml 내에 Host 엘리먼트를 추가하면서 그 안에 Context 엘리먼트를 함께 추가해서 호스트 컨텍스트 정보를 포함시켰는데, 톰캣 6이상 부터는 따로 분리할 것을 권고한다.(라는 것을 다른 블로그에서 보았다..)[각주:1]

  $CATALINA_HOME/conf/Catalina 에 서브 도메인 이름과 같은 디렉터리를 만든다.

server.xml에서 설정한 서브 도메인이 sub.domain.com 이므로 디렉터리 이름도 sub.domain.com 이다.

/var/lib/tomcat7/conf/Catalina$ mkdir sub.domain.com 

(위의 /var/lib/tomcat7은 톰캣이 설치된 경로, 일반적으로는 /usr/local/apache-tomcat-7.x.x)

  그리고 만든 디렉터리 안에 ROOT.xml 파일을 생성하고 아래와 같이 입력한다.

docBase 속성은 컨텍스트의 루트로 사용될 애플리케이션이 위치한 경로이고,

privileged 속성은 값이 true일 때. 매니저 서블릿 같은 컨테이너 서블릿을 사용할 수 있도록 허용한다. (Set to true to allow this context to use container servlets, like the manager servlet. - 라고 되어있는데 무슨 의미인지 정확하게는 모르겠다..)



| 웹 애플리케이션 배치

  docBase에 설정한 경로에 웹 애플리케이션을 배치하면 webapps에 있는 것 맨치롬 서브 도메인으로 접속할 수 있다.


| 문제

  Host 엘리먼트의 appBase와 Context의 docBase의 정확한 기능이나..  unpackWARs 속성 값을 true로 했을 때 어디에 위치한 war 파일의 압축이 풀리는 건지 모르겠다.

appBase나 docBase에 넣어봤지만 어디에서도 압축이 풀리지 않아서 그냥 tar 명령어로 풀어서 배치했다. -_- (왜 있는데 쓰질 못하니!)

  매번 파일럿 프로젝트만 개발하고 운영 단계까지 넘어가지 않다보니, 그냥 '돌아만'가는 서버 구축을 하다가, '제대로 돌아' 가는 서버를 구축하려니 공부해야할 것들이 점점 더 쌓이는 것 같다. 웹 서버 로드밸런싱이나, DB 서버 확장 등 어디서부터 시작해야할 지 막막하다.


잘못된 내용이나, 빠진, 부족한 내용에 대한 태클은 환영입니다. :)


References


  1. http://www.sjune.net/archives/807 [본문으로]

Eclipse 기반의 ADT를 사용하고 있는데, 아래와 같이 오타를 냈다.


android:id="@+iv/ivAdPic"


+id로 해야하는 것을 오타로 +iv로 한 탓.

이렇게 된 걸 모르고 당최 R.id.ivAdpic이 잡히지 않아서 찾다보니 이유가 저 오타였다.


헌데 안드로이드에서 xml을 파싱하여 R 파일을 생성할 때 오타난 부분은 문법이 +로만 시작하는 문자열이면 되는지

R파일을 보니 iv 정적 클래스가 추가되어있다. xml에서 컴파일 오류를 알려줬다면 금방 알 수 있었을 테지만, 생각지 못한 부분이라 시간을 좀 잡아 먹은 듯


+ Recent posts