|
Cross DBMS Query Executer인 Arare가 국제인증(?)을 획득하였습니다. ^^ Arare SQL Executer, one of your products, has been added to Softpedia's The description text was created by our editors, using sources such as text
To assure our visitors that Arare SQL Executer is clean, we have granted it More information about your product's certification and the award is Feel free to link to us using the URLs above. If you choose to link to the
![]() 꽤나 오랫동안 끄적거려오던 작업을 baseline을 그으려 한다.일단, 시작은 Oracle작업 시 사용하던 Golden의 기능을 Tibero나 MySql 등의 다양한 DB에서 사용하고자 만들게 되었다. JDBC라는 뛰어난(?) 개념때문에 쉽게 접근가능하리라 생각했으나, 천성이 게을러서 빠른 진도를 못 나갔던 것이 사실이다. 프로젝트는 Google Code에서 진행하고 있었고, 당연히, Member는 혼자이다..ㅋㅋ 100% pure java이며, pure Swing이다. Swing을 다루기 좋은 Netbeans로 작업하였다. 지금까지 작업한 기준으로 Binary와 Source를 Open하고자 한다. 물론, GNU 라이선스를 따름은 당연하다. code사이트는 http://code.google.com/p/arare/ 이다. member로 참여코자 하시는 분 있으시면 신청해 주시길 바란다. 위의 download 링크에서 다운받으신 zip파일을 여시고 첨부된 bat파일을 실행하시면 된다. 많은 사용과 Feedback부탁드린다.
public int[] doSort (int[] aArr) {
int i, j, cipher, num, max; int [][] bucket = new int [10][aArr.length]; int [] count = new int [10]; max = 0; for(i=0;i<aArr.length;i++){ if(max<aArr[i]) max = aArr[i]; } cipher = 1; while(cipher<=max){ for(i=0;i<=9;i++) count[i] = 0; for(i=0;i<aArr.length;i++){ num = (aArr[i]/cipher)%10; bucket[num][count[num]++] = aArr[i]; } num = 0; for(i=0;i<=9;i++){ for(j=0;j<count[i];j++){ aArr[num++] = bucket[i][j]; } } cipher *= 10; } return aArr; } public int[] doSort(int[] aList, int aLow, int aHigh){ int pivot = aList[(lo + hi) / 2]; doSort(aList, aLow, lo - 1);
public int[] doSort(int[] aList){
int h,i,j,k,temp,n = 0; n = aList.length; for(h=n/2;h>0;h=h/2){ for(i=0;i<h;i++){ for(j=i+h;j<n;j=j+h){ temp = aList[j]; for(k=j;k>h-1&&aList[k-h]>temp;k-=h) aList[k] = aList[k-h]; aList[k] = temp; } } } return aList; }
public int[] doSort(int[] aList){
int i, j, temp; for(i=0;i<aList.length-1;i++){ for(j=1;j<aList.length-i;j++){ if(aList[j-1] > aList[j]){ temp = aList[j-1]; aList[j-1] = aList[j]; aList[j] = temp; } } } return aList; }
public int[] doSort(int[] aList){
int k,j,i,temp = 0; for(i=0;i<aList.length-1;i++){ k = i; for(j=i+1;j<aList.length;j++){ if(aList[k]>aList[j]){ k=j; } } temp = aList[i]; aList[i] = aList[k]; aList[k] = temp; } return aList; }
public int[] doSort(int[] aList){
int k,j = 0; for(int i=1;i<aList.length;i++){ k = aList[i]; for(j=i-1;j>=0 && k < aList[j];j--) aList[j+1] = aList[j]; aList[j+1] = k; } return aList; }
회사를 옮기고 맡은 업무가 TA&SA인데...그 중 특히나 J2EE appl에 대한 대처다....
이글 저글 읽다가...발견한 글인데 .... 최고의 글이다.......감동감동감동 !!!!! 여기 오는 독자들은 꼭 읽어보길...권한다...강추한다. http://cafe.naver.com/ArticleRead.nhn?clubid=12263288&menuid=3&boardtype=&page=3&articleid=14 꽤나 오랫동안 연재를 하지 않았기에 혹시나 있지 모를 독자들에게 죄송하단 말을 하고 싶다. ![]() 맞다 간단하다...^^ 이제 코드를 알아보자. 앞서 언급한 바와 같이 Server측과 Applet측은 이미 구현되어 있는 것을 그대로 사용하므로 여기서 새롭게 언급하진 않겠다. 그럼 Ajax관련 코드만 나열하면 아래와 같다. 1. LogTailServlet.java 2. LogViewer.html 아주 간단하다...^^ 또한, 여기서는 기본적인 Web App는 구축되어 있다는 가정과 읽어와야 할 대상이 되는 Log파일이 존재한다는 가정하에 글을 진행하고 있으므로 해당 내용에 대해서 따로 언급하진 않겠다. 그럼 하나씩 알아보자. 먼저 LogTailServlet.java import java.io.*; import javax.servlet.*;
public void doGet(HttpServletRequest request, HttpServletResponse response) public void doPost(HttpServletRequest request, HttpServletResponse response) while((sLine = raFile.readLine()) != null) { private void printOutStatus(String sLine, HttpServletRequest request, HttpServletResponse response) throws Exception { 정말 요즈음 들어 Ajax의 매력에 흠뻑 빠진 느낌이다.
정말 오랜만에 블로그를 다시 시작했다..
아무도 모르는 이 블로그는 내가 누구인지 아무도 모르는 곳이다... 그래서 더 솔직해 질 수 있을지도 모르겠다... 오늘 정말 착한 사람을 다시 만났다 난 그 사람을 슬프게만 했는데....그 사람은 여전히 착했다... 그래서 슬픈걸까? 여전히 같은 모습의 그 사람때문일까? 갑자기 15년전의 내 모습이 떠오는건 왜인지... 마냥 슬퍼진다 그저 아둥바둥대며 살아온 시절은 아니었는지....뒤돌아보게 된다 역시 달라지는 건 없지만....그저 그대로이겠지만...
일반적으로 Windows 에서의 Java Application은 Command Console을 사용하여 구동된다.
이 방식은 아래와 같은 단점을 가지고 있다. 1. 사용자 실수로 인해 Command Console에 Mouse Click이 발생하면 Application이 Hold됨. 2. 사용자가 Logout하면 해당 Application이 종료됨. 3. 특별히 제약이 없는 경우 터미널 서버나 원격 데스크탑 Application을 사용하여 같은 Application을 각 User별로 계속 구동할 수 있음. 이런 단점을 극복하기 위해 Unix에서는 Background Process로 구동시키면 되지만, Windows는 그 태생이 End User를 위한 DeskTop이기에 그 개념이 없다. 그와 유사한 개념이 Windows Service이다. 그러나 애석하게도 현재 JDK는 Windows Service를 사용하는 API를 제공하고 있지는 않다. 그로 인해 Apache나 InstallAnywhere등의 Application 벤더들은 그들만의 방법으로 Service등록을 가능하게 해서 사용하고 있는 실정이다. 지금 제시할 방법은 이러한 Java Application을 Windows Service로 등록하는 간단한 방법이다. 프로젝트에 적용중인 모듈에 적용하기 위해 여러자료를 찾다 발견한 매우 간단한 방법이다. 지금까지 제가 배포한 모듈의 경우 모두 이 방법을 사용해 서비스에 등록했다. 방법은 다음과 같다. JavaService.exe 에 구동 Argument로 설정값을 넘겨주면 서비스 등록이 완료되게 된다. 실제 사용은 아래의 방법을 따른다. 1. JavaService.exe를 구한다. 2. 서비스 등록용 batch파일을 만든다. 아래는 필자가 사용하는 파일의 예이다. C:JavaService -install MyApp %JAVA_HOME%jreinserverjvm.dll -Djava.class.path=.;C:MyAppclasses -start MyApp.StartApp -params INSTALL_DIR=C:MyAppr -out C:MyApplogsstdout.log -err C:MyApplogsstderr.log -auto 3. 서비스 해지용 batch파일을 만든다. 아래는 필자가 사용하는 파일의 예이다. C:JavaService -uninstall MyApp 더 자새한 내용은 http://javaservice.objectweb.org/docs/description.html을 참고하기 바란다.
난 흔히 말하는 SMS 솔루션과 관계된 일을 하고 있다....
솔직히 우리 바닥에서 윈도우는 논외였다. 콘솔만 윈도우면 됬으니까... 크리티컬한 관리대상 장비는 거의 대부분 유닉스나 메인프레임이었기 때문이다 그런데... 아래의 기사는 슬슬 이 시장으로도 M$의 문어발이 접근하고 있다는 생각이 든다.... 솔직히 어찌 될지도 궁금하고 겁나기도 하고 어케 대비해야 할지도 고민이다... 어쨋든..그리 멀지 않은 것만은 사실이다. M$ !! 결국 오는건가? =================================================================================== 윈도우만 편애하던 MS의 CEO 스티브 발머가 마음을 바꾸고, MS가 앞으로 기업들이 보유한 다양한 시스템, 심지어 리눅스가 동작중인 시스템이라도 관리가 용이하도록 지원할 예정이라고 밝혔다. 발머는 지난 20일 그간 MS의 핵심 관리 제품인 오퍼레이션 매니저 소프트웨어에서 비(非) 윈도우 머신에 대한 지원을 강화해달라는 고객들의 요청에 귀를 기울여왔다고 밝혔다. 또한 MS는 올해 말 내놓을 버추얼 서버 제품의 서비스 팩 업데이트에서 리눅스 기반의 버추얼 머신 구동에 대한 지원을 강화할 계획이라고 말했다. 발머가 기조 연설을 하는 동안 레드햇 엔터프라이즈 리눅스가 동작중인 버추얼 서버가 시연됐는데, 연설 도중 발머는 "인정하고 싶지는 않지만 그것이 버추얼 서버 고객들에게 중요한 기능이라는 걸 안다"라고 말했다. 오직 고객을 위해? 현재 버전에서도 리눅스나 다른 운영체제를 구동할 수는 있지만, MS는 고객이 윈도우가 아닌 운영체제를 구동해 곤란을 겪을 때도 지원하겠다는 계획을 세운 것이다. MS는 MS 오퍼레이션 매니저(MOM)로 솔라리스 서버를 제어하는 것을 시연하면서, MOM 콘솔 내에 팝업 형태로 알림 메시지가 나타나는 것을 보여주기 위해 솔라리스가 동작중인 시스템에서 냉각팬을 뽑아버리기도 했다. 발머는 "우리는 썬과 긴밀히 작업해왔다. 알고 있겠지만 전에는 썬과의 긴밀한 협력은 생각할 수도 없었다"라고 말하며, 1년 전 양사가 상호 긴장 완화를 한 이래 두 회사가 함께 작업한 그간의 성과를 기반으로 업데이트를 곧 내놓을 것이라고 덧붙였다. WS-매니지먼트 웹 서비스 표준을 통해 솔라리스 서버 장비를 모니터링하는 데 MOM을 사용한다는 것은, MOM 관리 프로그램이 관리 대상이 윈도우 머신인지 알 필요가 없다는 의미다. MS의 인프라스트럭처 서버 마케팅 부문을 총괄하고 있는 밥 켈리는 반대 상황도 함께 시연하면서 "보는 것처럼 솔라리스가 동일한 프로토콜을 이용해 윈도우 머신을 이렇게 쉽게 관리할 수 있다"라고 말했다. MS의 상호운용성 부족하지 않다 켈리는 “MS의 목표는 윈도우가 수많은 윈도우와 비 윈도우 시스템들을 관리하는 데 가장 비용이 적게 드는 방법을 제공한다는 것을 확실히 보여주는 것”이라고 말했다. 그는 이 관리 소프트웨어가 새로 나온 것이지만 상호 운용성을 이미 제공하고 있다며, 이런 점은 MS가 그 동안 충분히 신뢰를 얻지 못했던 부분이라고 말했다. 켈리는 "우리 제품이 다른 회사 제품과 상호 운용이 되지 않는다는 것을 알고 있다는 것이 정말로 '부끄러운 일'"이라고 말했다. 발머는 20일 연설에서 차세대 데스크톱용 윈도우 제품인 '롱혼'에 대해서도 언급했다. 그는 롱혼이 내년 하반기에 나오면 관리 편의성이 나아지고 운영 비용이 좀더 저렴해질 것이라며, 윈도우 운영체제 최고 책임자인 짐 알친이 지난 주에 언급한 내용을 여러 번 되풀이하며 강조했다. 또한 발머는 롱혼 데스크톱 버전이 출시된 후 약 6개월 뒤에 롱혼 서버가 나올 예정이라며 롱혼 서버 출시 시기에 대해 좀더 자세히 언급했다. 역사적으로 볼 때 서버를 출시하기 전 테스트 기간이 비교적 오래 걸리기 때문에 정확한 스케줄을 맞추는 것을 기대하기는 어려웠다. 켈리는 롱혼의 클라이언트 버전과 서버 버전의 개발 주기를 맞춰가고 있다고 말했다. 이는 서버 출시에 필요한 추가 테스트에 6개월이라는 시간이 필요하다는 것을 의미한다. 그는 "이를 지키기 위해 최선을 다하고 있다"라고 덧붙였다. 발머의 이야기는 MS가 단일화된 시스템 센터 제품을 내놓기로 한 계획을 파기하고, 대신 기존 MOM과 시스템 매니지먼트 서버(SMS) 제품에 대한 업데이트 계획을 세우며 향후 관리 소프트웨어를 어떻게 내놓을지 밝힌 지 하루 만에 나온 것이다.
SUN JAVA STREAMING XML PARSER 소개
현재 dom4j를 사용해서 프로젝트를 수행하고 있다. 성능도 괜찮고 API도 잘 되어 있어서 괜찮다고 생각하고 있었는데 메일로 날아온 SJSXP TechTip을 봤는데 JDBC API를 사용하는 듯한 쉬운 사용법이 일단 맘에 든다. 새로운 프로젝트에 적용해보아야 할듯..... ==================================================================================== XML을 사용하는 대부분의 Java 개발자는 SAX (Simple API for XML) 라이브러리와 DOM(Document Object Model) 라이브러리에 익숙할 것이다. SAX는 이벤트 기반의 API이며, 이는 일반적으로 프로그래머가 파서와 몇 개의 리스너를 등록하고, 특정 XML 문법 생성자(예를 들어 요소나 속성)가 도착되면 리스너 메소드가 호출된다는 의미이다. 그 반대로 DOM은 트리 기반의 아케텍처를 가지며, 전체 문서를 스캔하여 마주치는 각각의 문법 생성자의 오브젝트 트리를 구축한다. 프로그래머는 스캔이 완료된 후 오브젝트 트리에 접근하여 수정할 수 있다 이 두 방법 모두 각각의 결점을 가지고 있다: 리스너를 이용하는 이벤트 기반의 API는 일반적으로 다루기 힘들다. 리스너들이 파서에 의해 조종되기 때문이다. 트리 기반의 API는 스캔되는 문서의 양에 비해 과도한 양의 메모리를 소모할 수 있다. 이제 Java 개발자들이 XML 을 스캔하는데 이용할 수 있는 세 번째 API가 등장하였다. StAX (Streaming API for XML parse)가 그것이다. SJSXP란? SJSXP(Sun Java Streaming XML Parser)는 StAX를 빠른 속도로 구현한다. 썬마이크로시스템즈와 협력하고 있는 BEA Systems, XML-guru James Clark, Stefan Haustein, Aleksandr Slominski (XmlPull 개발자들), 그리고 JCP의 다른 멤버들은 JSR 173를 구현하는 것으로써 StAX를 개발하였다. StAX은 공유 인터페이스들에 기반하는, 파서(parser) 독립적인 Java API이다. SJSXP는 Java Web Services Developer Pack v1.5에 포함되어있다. SJSXP에 대해 처음으로 알아차릴만한 것은 이것이 스트림 API에 기반한다는 것이다. 즉, 개발자가 어느 한 노드에 접근하기 위해 전체 문서를 읽을 필요가 없다. 또한, 파서를 시작하여 파서가 데이터를 이벤트 리스너 메소드에 "push"하도록 허용하는 법칙을 따르지 않는다. 대신에 SJSXP는 "pull" 메소드를 구현하며, 이 메소드는 정렬 포인터를 문서에서 현재 스캔되고 있는 지점에 유지한다. 이는 종종 커서(cursor)라고 불린다. 사용자는 단순히 커서가 현재 가리키고 있는 노드에 대한 파서를 요청하면 된다. XML 문서 파싱에 SJSXP 이용하기 SJSXP를 이용하여 XML 문서를 읽는 것은 아주 쉽다. 대부분의 작업은 javax.xml.stream.XMLStreamReader 인터페이스를 구현하는 오브젝트를 통해 이뤄진다. 이 인터페이스는 XML 문서의 첫 부분에서 마지막까지 이동되는 커서를 나타낸다. 몇 가지 명심해야할 것이 있다. 커서는 항상 하나의 아이템(시작 태그 요소, 진행 명령, DTD 선언 등)만을 가리켜야 한다. 또한 커서는 항상 앞으로 움직여야 하며 (뒤로 움직일 수 없다), 다음에 무엇이 나타나는지 미리 보기를 실행할 수 없다. 다음의 코드 발췌에서 파일로부터 XML을 읽는 XMLStreamReader를 얻을 수 있다. URL url = Class.forName("MyClassName").getResource( "sample.xml"); InputStream in = url.openStream(); XMLInputFactory factory = XMLInputFactory.newInstance(); XMLStreamReader parser = factory.createXMLStreamReader(in); 그 후 다음 코드를 이용하여 XML 파일을 반복할 수 있다. while(parser.hasNext()) { eventType = parser.next(); switch (eventType) { case START_ELEMENT: // Do something break; case END_ELEMENT: // Do something break; // And so on ... } } XMLStreamReader의 hasNext() 메소드는 XML 파일에서 또다른 유효한 아이템이 있는지 확인한다. 만약 있다면, 커서가 다음 아이템으로 넘어가게하기 위해 next() 메소드를 사용할 수 있다. next() 메소드는 만나게되는 문법상 생성자(아이템)의 타입을 가리키는 인티거 코드를 리턴한다. XMLInputStreamReader에는 몇 개의 get 메소드가 있어서 커서가 가리키는 XML 아이템의 내용을 얻는 데 사용할 수 있다. 첫번째 메소드는 getEventType()이다: public int getEventType() 메소드는 커서가 있는 곳에서 파서가 찾은 아이템의 타입을 식별하는 integer 코드를 리턴한다. next() 메소드에 의해 리턴되는 것과 같은 코드이다. 아이템은 XMLInputStream 상수 중 하나에 의해 식별된다. XMLStreamConstants.START_DOCUMENT XMLStreamConstants.END_DOCUMENT XMLStreamConstants.START_ELEMENT XMLStreamConstants.END_ELEMENT XMLStreamConstants.ATTRIBUTE XMLStreamConstants.CHARACTERS XMLStreamConstants.CDATA XMLStreamConstants.SPACE XMLStreamConstants.COMMENT XMLStreamConstants.DTD XMLStreamConstants.START_ENTITY XMLStreamConstants.END_ENTITY XMLStreamConstants.ENTITY_DECLARATION XMLStreamConstants.ENTITY_REFERENCE XMLStreamConstants.NAMESPACE XMLStreamConstants.NOTATION_DECLARATION XMLStreamConstants.PROCESSING_INSTRUCTION 만약 아이템에 이름이 있는 경우, getName()과 getLocalName() 메소드를 사용하여 이름을 얻을 수 있다. 후자는 어떤 다른 정보(예; 확인된 네임스페이스가 없는 요소의 이름) 없이 이름 자체를 산출한다. public Qname getName() public String getLocalName() 만약 당신이 현재 아이템의 네임스페이스를 식별하고 싶다면 getNamespaceURI() 메소드를 사용 할 수 있다. public String getNamespaceURI() 만약 DTD 선언 내의 텍스트나 요소 안의 텍스트 등과 같은 동반되는 텍스트가 있을 때에는 다음 메소드들을 사용하여 얻을 수 있다.(후자는 요소를 위해 단독으로 사용 될 수 있다) public String getText() public String getElementText() 만약 요소가 그것과 관계 되는 속성을 가진다면 getAttributeCount() 메소드를 사용하여 현재 요소가 가진 속성들의 갯수를 얻을 수 있다. 그 후 getAttributeName() 와 getAttributeValue() 메소드를 사용하여 각각의 정보를 검색 할 수 있다. public int getAttributeCount() public Qname getAttributeName(int index) public String getAttributeValue(int index) 만약 속성의 로컬 이름과 요소의 네임스페이스 URI를 안다면, 또한 다음의 메소드를 이용하여 속성값을 얻을 수 있다. public String getAttributeValue( String elementNamespaceURI, String localAttributeName) 추측했겠지만, 모든 접근자 메소드가 특정 상태에 적용가능한 것이 아니다. 예를 들어, 현재 DTD를 프로세싱 중이라면 getElementText()을 호출할 수 없다. 만약 이를 호출한다면, 파서가 충돌하는 이벤트 타입을 식별했다는 XMLStreamException을 얻게 되거나 메소드가 스스로 널(null) 값을 리턴하게 될 것이다. XMLInputFactory 클래스의 setProperty() 메소드를 사용하여 몇 가지 파서 속성을 시작할 수 있다. 예를 들어, 다음은 파서와 마주치는 엔티티 레퍼런스는 교체될 것이라고 지정한다. factory.setProperty( XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.TRUE); 파서가 외부 엔티티를 지원하는 것을 막기 위해 다음과 같이 설정한다. factory.setProperty( XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE); 파서가 네임스페이스를 알아차리게하기 위해 다음과 같이 설정한다. factory.setProperty( XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.TRUE); SJSXP의 현재 버전에서는 다음의 명령은 허용되지만 파서는 확인되지 않는다는 것을 유의하기 바란다. factory.setProperty(XMLInputFactory.IS_VALIDATING, Boolean.TRUE); 만약 이 XMLInputFactory 특성들 중 어느 하나라도 가능하게 된다면 setXMLReporter() 메소드를 사용하여 파서가 만나게되는 오류를 제어할 수 있다. 파서가 만나는 오류의 타입을 가장 빨리 정확하게 결정할 수 있는 방법은 setXMLReporter() 메소드와 상호 작용하는 익명의 이너 클래스를 사용하는 것이다. 이는 다음과 같다. factory.setXMLReporter(new XMLReporter() { public void report(String message, String errorType, Object relatedInformation, Location location) { System.err.println("Error in " + location.getLocationURI()); System.err.println("at line " + location.getLineNumber() + ", column " + location.getColumnNumber()); System.err.println(message); } }); XML 문서 작성에 SJSXP 사용하기 XML 결과를 작성하는 것은 SJSXP를 이용하면 쉽다. 이 경우, XMLStreamReader 인터페이스 대신에 XMLStreamWriter 인터페이스를 사용할 수 있다. XMLStreamWriter 인터페이스는 작성하는 요소, 속성, 코멘트, 텍스트를 비롯해 XML 문서의 모든 부분을 작성하기 위한 직접적인 메소드를 제공한다. 다음의 예제에서는 어떻게 이 인터페이스를 얻어서 XML 문서를 작성하는데 사용하는지 보여준다. XMLOutputFactory xof = XMLOutputFactory.newInstance(); XMLStreamWriter xtw = xof.createXMLStreamWriter(new FileWriter("myFile")); xtw.writeComment( "all elements here are in the HTML namespace"); xtw.writeStartDocument("utf-8","1.0"); xtw.setPrefix("html", "http://www.w3.org/TR/REC-html40"); xtw.writeStartElement( "http://www.w3.org/TR/REC-html40","html"); xtw.writeNamespace( "html", "http://www.w3.org/TR/REC-html40"); xtw.writeStartElement( "http://www.w3.org/TR/REC-html40","head"); xtw.writeStartElement( "http://www.w3.org/TR/REC-html40","title"); xtw.writeCharacters("Java Information"); xtw.writeEndElement(); xtw.writeEndElement(); xtw.writeStartElement( "http://www.w3.org/TR/REC-html40","body"); xtw.writeStartElement("http://www.w3.org/TR/REC-html40","p"); xtw.writeCharacters("Java homepage is "); xtw.writeStartElement("http://www.w3.org/TR/REC-html40","a"); xtw.writeAttribute("href","http://java.sun.com"); xtw.writeCharacters("here"); xtw.writeEndElement(); xtw.writeEndElement(); xtw.writeEndElement(); xtw.writeEndElement(); xtw.writeEndDocument(); xtw.flush(); xtw.close(); 각 요소를 작성하는 것이 끝나면 사용자는 라이터(writer)를 날려보내고 닫아야한다. 이전의 코드는 다음의 XML로 결과가 나타난다.(여기서는 쉽게 읽을 수 있게 라인 별로 나타내었다.) <!--all elements here are explicitly in the HTML namespace--> <?xml version="1.0" encoding="utf-8"?> <html:html xmlns:html="http://www.w3.org/TR/REC-html40"> <html:head> <html:title>Java Information</html:title> </html:head> <html:body> <html:p> Java information is <html:a href="http://frob.com">here</html:a> </html:p> </html:body> </html:html> XML 문서 필터링 만약 각각의 아이템 타입을 스캔하고 싶지 않다면 들어오는 XML 문서에 대한 필터를 생성할 수 있다. 이를 위해서는 javax.xml.stream.StreamFilter 인터페이스를 구현하는 클래스를 생성한다. 이 인터페이스는 단지 accept() 메소드만으로 구성된다. 이 메소드는 XMLStreamReader 오브젝트를 허용하고 원시 Boolean을 리턴한다. StreamFilter의 일반적인 구현은 다음과 같다. public class MyStreamFilter implements StreamFilter { public boolean accept(XMLStreamReader reader) { if(!reader.isStartElement() && !reader.isEndElement()) return false; else return true; } } 그 다음으로 XMLInputFactory의 createFilteredReader() 메소드를 호출하여 필터링된 리더(reader)를 생성하고 이를 원래 XML 스트림 리더와 StreamFilter 구현에 모두 전달한다. 다음과 같다. factory.createFilteredReader( factory.createXMLStreamReader(in), new MyStreamFilter()); SJSXP의 더 자세한 정보는 Sun Java Streaming XML Parser release notes를 참고하기 바란다. Sun Java Streaming XML Parser 예제 코드 구동하기 이번 테크팁에 대한 샘플 아카이브(ttfeb2005sjsxp.jar)를 다운로드한다. Java Web Services Developer Pack Downloads page에서 Java WSDP 1.5를 다운로드, 설치한다. 예제 압축파일을 다운로드 받은 디렉토리를 변경하고, 다음과 같이 샘플 아카이브에 대한 JAR 파일의 압축을 푼다. jar xvf ttfeb2005sjsxp.jar 사용자의 classpath가 ttfeb2005sjsxp.jar와 jsr173_api.jar를 포함하도록 설정한다. 이들은 Java WSDP 1.5 installation의 sjsxp/lib 디렉토리에 위치하고 있다. SJSXPInput를 컴파일하고 구동한다. 다음의 각각의 XML 아이템과 유사한 엔트리가 나타날 것이다. Event Type (Code=11): DTD Without a Name With Text: ----------------------------- SJSXPOutput를 컴파일하고 구동한다. 결과는 XMLOutputFile라는 이름의 파일에 보내지며, 위의 결과 예제에 보여지는 요소들을 포함할 것이다. 1.Resin Install Command Line Argument 2.resin.conf(1) 3.resin.conf(2) 4.Resin Install on UNIX 5.How to Start with Appache 6.How to Start with IIS 7.Resin3.0 변경사항
Resin 역시 Java Application 이기 때문에 “Write Once, Run Everywhere” 를 추구한다. 그러므로 Unix에서 구동하기 위해 특별히 make해야 한다거나 소스를 수정해야 하는 것은 필요치 않다. 즉, JDK만 설치되어 있다면 동일하다는 뜻이다. 아래 문서의 내용은 Linux와 Mac OS-X도 함께 포함된다. 다만, Daemon이기 때문에 기본적으로 Background로 구동되어야 하고 그 구동방법이 Windows의 그것과는 다르기에 필요한 몇 가지 설정이 있을 뿐이다. Unix에 Install하기 위해 고려할 사항은 아래와 같다.
1. Resin 사용자 계정 생성 2. JDK1.4이상 설치여부 3. Perl 5.6 이상 설치 여부(for $RESIN_HOME/bin/httpd.sh) 4. rc.d 등록여부
이 이외에 resin.conf설정이나 web-app 의 deploy방법, command-line argument사용법 등은 windows의 그것과 동일하며 이미 앞선 글에서 설명되었으므로 생략하도록 하겠다.
1. Resin 사용자 계정 생성 A. Install Guide에 의하면 Resin을 구동하기 위한 특별한 계정은 따로 존재하지 않는다.(꼭, Root 이어야 할 필요는 없다. 오히려 보안정책상 일반 User를 추천한다.) B. 필요하다면 JAVA_HOME 과 RESIN_HOME을 설정한다.(구성되어 있지 않다면 설정하는 것이 좋다.)
2. JDK1.4이상 설치여부 A. Caucho에서는 JDK1.4이상을 권고하고 있으며 version확인법은 아래와 같다. # java –version java version "1.4.2_06" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_06-b03) Java HotSpot(TM) Server VM (build 1.4.2_06-b03, mixed mode) B. 주의할 것은 JRE만 설치되어서는 안되고 JDK가 설치되어야 한다는 것이다. 위의 내용은 JRE만 Check 할 수 있을 뿐이다. # javac Usage: javac where possible options include: -g Generate all debugging info -g:none Generate no debugging info -g:{lines,vars,source} Generate only some debugging info -nowarn Generate no warnings -verbose Output messages about what the compiler is doing -deprecation Output source locations where deprecated APIs are used -classpath -sourcepath -bootclasspath -extdirs -d -encoding -source -target -help Print a synopsis of standard options C. 위와 같이 JDK 설치도 확인되어야 한다. D. 각 OS별로 JDK설치 방법은 다르므로 관련 OS의 Tech note를 참조하기 바라며 이 글에서는 언급하지 않겟다.
3. Perl 5.6이상 설치여부 A. Unix에서 resin을 구동하는 방법은 $RESIN_HOME/bin/httpd.sh를 사용하는 것이다. B. Httpd.sh의 내용은 주석부분을 제거하면 아래와 같다. #! /bin/sh # # Extra arguments to Java. If you're passing arguments to the JVM, you'll # need to use -Jxxx. For example, args="-J-ms48m". You can modify # the pid file with args="-pid server-a.pid" # args= # class to start class=com.caucho.server.http.HttpServer # name of the server name=httpd # location of perl executable perl=perl # trace script and simlinks to find thw wrapper script=`/bin/ls -l $0 | awk '{ print $NF; }'` while test -h "$script" do script=`/bin/ls -l $script | awk '{ print $NF; }'` done bin=`dirname $script` exec $perl $bin/wrapper.pl -chdir -name "$name" -class "$class" $args $* 결과적으로 보면 httpd.sh가 있는 디렉토리를 구해서 perl을 사용해서 wrapper.pl이라는 파일을 구동시키고 있음을 알 수 있다. 위의 파일에 포함된 실행옵션들은 글 말미에 별도 설명하고 여기선 생략한다. 자세히 해석하길 원한다면 Unix shell script에 관한 자세한 자료를 참조하길 바란다. C. 위에서 언급한 wrapper.pl의 내용은 아래와 같다. i. Wrapper.pl은 약 800여 line의 perl파일이다. 해당 파일의 내용을 하나씩 해석하는 것은 Perl script 사용법을 언급하며 설명하는 것이고 이 글의 범위를 벗어나게 되므로 지양한다. ii. 다만, 관련 파일의 내용에 대해 나열하고 주의사항을 언급한다. iii. Wrapper.pl의 내용은 아래와 같다. 1. Resin의 start, stop, restart 2. JAVA_HOME설정 3. RESIN_HOME설정 4. configuration file의 변경 5. CLASSPATH설정 6. native thread로 강제 구동 7. green thread로 강제 구동 8. jit 컴파일러 사용여부 9. stdout log file의 변경 10. stderr log file의 변경 11. pid file 설정 12. 자동 restart 여부 iv. Wrapper.pl관련 오류 및 조치사항 1. 먼저 wrapper.pl구동을 위한 Perl은 Version 5.6이상을 권고하고 있으며 확인방법은 아래와 같다. # perl -v This is perl, v5.6.1 built for sun4-solaris-64int (with 48 registered patches, see perl -V for more detail) Copyright 1987-2001, Larry Wall 2. 아래의 내용은 perl이 설치되어 있지 않거나 perl 버전이 낮은 경우 발생한다. # ./httpd.sh start usage: dirname [ path ] Can't open perl script "/wrapper.pl": No such file or directory 3. 아래의 내용의 원인도 역시 perl이 설치되지 않았거나 version이 맞지 않아서 발생하며 참고로 위의 내용은 HP-UX11에서 발생한 내용이다. # ./httpd.sh syntax error in file ./wrapper.pl at line 9, next 2 tokens "use File" syntax error in file ./wrapper.pl at line 72, next 2 tokens "my(" syntax error in file ./wrapper.pl at line 73, next 2 tokens "fileparse(" syntax error in file ./wrapper.pl at line 517, next 2 tokens "0 and" syntax error in file ./wrapper.pl at line 527, next token "}" syntax error in file ./wrapper.pl at line 634, next 2 tokens "setpgrp;" syntax error in file ./wrapper.pl at line 706, next 2 tokens "my $file " syntax error in file ./wrapper.pl at line 715, next 2 tokens "$dir or" syntax error in file ./wrapper.pl at line 717, next 2 tokens "$pwd or" syntax error in file ./wrapper.pl at line 724, next 2 tokens "$dir or" ./wrapper.pl has too many errors. 4. 아래의 내용은 resin이 사용하는 pid파일을 write하지 못할 때 발생하는 내용이다. 해결방법은 해당 디렉토리와 파일의 권한을 확인하고 재설정하도록 한다. # ./httpd.sh start Can't locate Socket.pm in @INC at /resin-2.1.4/bin/wrapper.pl line 10. BEGIN failed--compilation aborted at /resin-2.1.4/bin/wrapper.pl line 10.
4. rc.d등록여부 A. rc.d관련 설정은 해당 시스템 관리자의 role이므로 기본적으로는 권한이 있는 관리자에게 설정해달라고 하는 것이 옳다. B. Caucho의 권고사항은 아래와 같다. httpd.sh를 resin/bin에 resin-a.sh로 이름을 바꾸고 권한을 할당하여 복사한다. resin-a.sh에 JAVA_HOME, RESIN_HOME, PATH, "-pid" 를 설정한다. "resin-a.sh start" 와 "resin-a.sh stop”을 root 계정으로 test한다. 아래와 같이 수행한다. "ln -s /usr/local/resin/bin/resin-a.sh /etc/rc.d/rc3.d/S86resin-a" "ln -s /usr/local/resin/bin/resin-a.sh /etc/rc.d/rc5.d/S86resin-a" "ln -s /usr/local/resin/bin/resin-a.sh /etc/rc.d/rc2.d/K14resin-a"sr/local/resin/bin/resin-a.sh /etc/rc.d/rc3.d/S86resin-a" "ln -s /usr/local/resin/bin/resin-a.sh /etc/rc.d/rc5.d/S86resin-a" "ln -s /usr/local/resin/bin/resin-a.sh /etc/rc.d/rc2.d/K14resin-a"
이글루는 표가 지원안된다...
간신히 미리보기에서 제대로 보이게 만들었더만 정작 올리니까 깨진다. 결국 사내 intranet에 올린 걸 그림으로 떠서 붙이기로 했다...쩝 ![]()
ITSMF korea에서 하는 첫 포럼 기념의 행사였던 ITIL Foundation교육을 받았다.
2일간 교육과 마지막날 인증시험이 있었고 꽤나 힘들게 공부했다. 내용은 쉬웠지만 너무 짧은 기간이 문제였다. 떨어질까 겁났는데 합겼했다....^^ 4일 과정이라면 무난할 듯 하다. 올해 목표가 PMP, CISSP, ITIL Foundation이었는데 일단 하나는 이룬셈이다. 이제 PMP를 향해 달려가야겠다....이건 좀 더 공부해야겠지?...^^
이번 내용은 지난주에 언급한 바와 같이 다중 서비스 구축 방법에 대해서 알아보겠다.
1. 다중서비스 구축방법 이 문제는 resin이 standalone으로 구동된다는 전제하에 해당되는 것이다. 만약 Apache나 IIS에 plugin으로 구동시키고 있다면 두 개의Instance를 띄운다는 것은 Apache와 IIS의 설정과 관련된 일이므로 이 문서의 범위 밖의 일이므로 언급하지 않겠다. 두 개 이상의 instance를 사용하는 방법 현재 resin은 기본적으로 단일 Java 프로세스로 구동되며 내부적으로 Client의 요청마다 Thread를 생성하여 구동하는 기본적인 WebServer구조를 유지하고 있다. 즉, 이 말은 두 개의 instance를 띄운다는 것은 (Oracle에서의 Instance개념과 달리) 두 개의 Java Process를 각각 구동시킨다는 의미가 된다. 그러므로 두 개의 프로세스를 구동시키기 위해서는 Unix나 Windows 모두 권한이 있는 계정으로 접속한 후 command를 통해 여러개의process를 띄우면 되겠으나 두가지 고려할 사항이 있다. 1. port 설정 만약, 같은 port로 두 개를 띄우고 각각 자동적으로 서비스 되길 바란다면 그것은 두 개의 서비스가 아니라 하나의 서비스에 load balancing을 위한 설정을 하겠다는 뜻이다. 그러므로 두 개의 instance를 띄운다는 것은 각각 port가 다르게 설정되어야 함을 의미한다. port가 다르다는 것은 두 개의 resin.conf 파일이 각각 다르다는 것을 의미한다. 즉, $RESIN_HOME/bin/httpd -install -conf $파일명을 사용하여 각각 다른 conf파일을 지정해야 할 것이다. 2. Windows Service명 중복 Unix의 경우 어차피 Daemon Process로 구동되도록 명령을 수행할때, 같은 process명이라도 pid가 다르므로 상관없이 둘 다 daemon 으로 구동되겠지만 Windows의 경우 Background process로 구동하기 위해 service로 구동할 때는 service명이 같으면 안된다는 문제가 있다. 이 문제는 서비스 명을 다르게 주어서 등록하는 방법을 사용해 해결하면 된다. 즉, $RESIN_HOME/bin/httpd -install-as $서비스명을 사용하여 구동하여 중복된 이름을 방지할 수 있다. 이상의 두가지 문제는 이미 올렸던 글 1.Resin Install Command Line Argument을 참조하면 알 수 있다. 다중 web-app 와 가상호스트 지난 글에도 언급했지만 resin.conf의 구조는 아래와 같다. <caucho.com> <http-server> <host id='gryffindor.caucho.com' app-dir='gryffindor'> <web-app id='/'> <servlet-mapping .../> ... </web-app> <web-app id='/test' app-dir='/usr/local/test'> ... </web-app> </host> <host id='slytherin.caucho.com' app-dir='slytherin'> ... </host> ... </http-server> </caucho.com> 이 구조를 잘 살펴보면 하나의 http-server에 두개 이상의 host가 존재하며 하나의 host에 두개 이상의 web-app가 존재함을 알 수 있다. 즉, 아래의 그림으로 설명할 수 있다. ![]() 위의 그림을 보면 의문점이 생길 것이다. 맨 아래쪽의 접근 방식을 보면 하나의 web-app를 사용할 때도 위와 같이 디렉토리명을 사용해서 접근이 가능한데 무엇이 다른가 하는 것이다. 다른점은 다른 app로 작동하느냐 이다. 즉, 하나의 web-app를 사용할 때는 아무리 디렉토리별로 다르게 접근한다고 해도 모두 같은 session을 공유하고 같은 WEB-INF의 class를 사용하도록 되어 있다. 하지만, 위와 같은 경우는 각기 다른 session을 가지며, 또한 WEB-INF 역시 각기 달리 갖는다. 완전히 독립적인 app로 인식한다는 것이다. 게다가 web.xml을 사용할 경우도 역시 각기 다른 web.xml을 사용해야 함은 물론이다. 그렇다면 가상호스트는 무엇인가? 위의 그림에서 하나의 서버에 두 개의 host가 존재한다 각각은 고유의 도메인을 가지고 있지만 같은 host의 같은 ip를 사용한다. 즉, 글자 그대로 가상의 호스트처럼 동작한다는 의미이다. 일단 사용자의 hosts파일은 아래와 같다고 가정한다. /etc/hosts 127.0.0.1 localhost 127.0.0.1 www.sms.co.kr 127.0.0.1 www.maxigent.co.kr 사용자는 www.maxigent.co.kr로 접속을 시도한다. 그러면 먼저 사용자의 hosts파일을 검색해서 해당 도메인에 대한 정보에 해당하는 ip로 접속을 시도한다. 만약 해당정보가 없다면 해당 user의 시스템에 설정된 DNS서버에 quering을 하게 될 것이다. 이 부분에 대한 자세한 정보를 원한다면 internetworking의 구조에 대해 참조하기 바란다. resin은 해당 request가 들어오면 자신의 conf파일을 검색해서 host id와 mapping을 시도한다. 그 결과 해당하는 host id가 존재하면 그부분의 web-app를 반환하게 된다. 결론적으로 기본적인 virtual hosting을 위한 resin.conf는 아래와 같다 <http-server> ... <host id='sms.sds.co.kr'> <app-dir>/home/www/sms/docs</app-dir> ... </host> <host id='maxigent.sds.co.kr'> <app-dir>/home/www/maxigent/docs</app-dir> ... </host> 이 이외에 Virtual Host with Apache or IIS, JVM per Virtual Host, IP-Based Virtual Hosting등의 좀더 깊이있는 주제는 http://www.caucho.com/resin-2.1/ref/virtual-host.xtp 을 살펴보기 바란다. 각 방법별 적용 위에서 두 개 이상의 web-app를 구동하는 방법을 알아봤다. 대부분의 site에서는 위와 같은 방법을 사용하여 운영할 이유는 특별히 없을 것이다. 그러나, 개발중인 경우나 test나 BMT등의 daemo용으로 구축을 요할 때 위의 방법중 하나를 사용하는 것은 필요하다. 위의 방법중 첫 번째 resin을 두 개 이상 구동하는 것을 추천한다. 물리적인 장비의 성능 및 용량이 충분하다면 이 방법을 사용하여 운영중이거나 혹은 다른 개발중인 app에 영향없이 다른 app를 구동할 수 있기때문이다. 물론, virtual host나 web-app를 두 개 이상을 두는 것도 생각해 볼 수 있는 방법이긴 하나 일단 web-app를 두 방법 모두 해당 resin instance의 성능을 나눠 사용하는 것이므로 먼저 운영중인 app에 영향이 생기는 것은 부정할 수 없다. 또한, web-app를 나눠 사용하는 경우 doc-root가 같기 때문에 개발자의 실수로 인한 다른 app의 문제 발생 소지를 가지고 있다. virtual host의 경우 일단 DNS를 설정해야 한다는 문제가 있고, 그렇지 않을 경우 ip-based로 설정해야 하는데 이것 또한 장비의 NIC가 두 개 이상이어야 한다는 제한이 생기게 된다. 즉, 두 개 이상의 서비스가 필요하다면 장비의 성능이 제공하는 범위에서 각기 다른 process로 구동하라는 것이 결론이다. 장비의 성능이 문제가 된다면 -Xms, -Xmx -Xss등의 메모리 관련 command line argument와 <thread-max>, <thread-keepalive>, <request-timeout>, <accept-buffer-size>, <thread-min> 등의 값을 조절하면 될 것이다.
Resin.conf는 크게 아래와 같은 구조를 갖는다.
일반적으로 resin.conf의 Depth는 아래의 예를 따른다. <caucho.com> <http-server> <host id=''> <web-app id='/'> <servlet-mapping url-pattern='/test' .../> </web-app> </host> </http-server> </caucho.com> 대부분의 중요한 설정은 web-app에 속해 있다. Server는 다수의 host element를 포함하며 각 host 는 다수의 web-app 들을 포함할 수 있다. 각 host 는 가상host를 설정하고 각 web-app 는 application을 설정한다. <caucho.com> <http-server> <host id='gryffindor.caucho.com' app-dir='gryffindor'> <web-app id='/'> <servlet-mapping .../> ... </web-app> <web-app id='/test' app-dir='/usr/local/test'> ... </web-app> </host> <host id='slytherin.caucho.com' app-dir='slytherin'> ... </host> ... </http-server> </caucho.com> Simple configurations host 와web-app tag의 생략을 허용한다. 만약 host 와 web-app를 생략한다면 default host 와 default application를 사용하게 되며 http-server element 의 모든 web-app에 동일한 설정을 적용하게 된다. <caucho.com> <http-server app-dir='/usr/local/web'> <servlet-mapping .../> ... </http-server> </caucho.com> 1. <caucho.com>의 하위 엘리먼트 <log id='/log' href='stderr:' timestamp='[%Y-%m-%d %H:%M:%S.%s]'/> 로깅을 위한 설정부분이며 id별로 각기 다른 로그를 지정할 수 있다. rollover-count : 몇번의 로그변경을 보관할지 설정 rollover-period : 로그변경 주기 설정 ex> rollover-period=’1d’라고 설정하면 stderr.log.20050301의 형태로 매일 로그가 쌓이게 된다 <security-provider id='com.sun.net.ssl.internal.ssl.Provider'/> JSSE(Java Secure Socket Extension)를 사용하기 위한 security-provider설정 부분으로 Caucho에서는 설정의 어려움과 성능 저하를 이유로 OpenSSL이나 SSL for Apache/IIS를 사용할 것을 권고하고 있으므로 특별한 경우가 아니면 사용하지 않는 것이 좋다. <java compiler="internal" compiler-args=""/> Compiler옵션으로 internal이 default이며 javac나 jikes등의 외부 컴파일러를 지정할 수 있다. <resource-ref> <res-ref-name>jdbc/test</res-ref-name> <res-type>javax.sql.DataSource</res-type> <init-param driver-name="com.caucho.jdbc.mysql.Driver"/> <init-param url="jdbc:mysql_caucho://localhost:3306/test"/> <init-param user=""/><init-param password=""/> <init-param max-connections="20"/> <init-param max-idle-time="30"/> </resource-ref> JNDI를 사용한 resin connection pool을 사용할 경우 설정이며 res-ref-name 은 pool name을 의미하며 그 외의 설정은 tag와 property를 참조한다. <jsp precompile='true' static-encoding='true' recompile-on-error='true'/> jsp페이지를 precompile하도록 지정하여 다음 접속시 바로 이용할 수 있도록 한다. Recompile-on-error를 지정하여 jsp페이지를 compile시 java.lang.error가 발생하면 자동으로 recompile되도록 한다. Shift-JIS와 같은 인코딩을 이용해서 writing하고 UTF-8으로 printing하려면 static-encoding을 비활성시킨다. 2. <http-server>의 하위 엘리먼트 <doc-dir>doc</doc-dir> Server의 root file이 위치한 디렉토리를 지정한다. Apache : /usr/local/apache/htdocs, IIS : d:inetpubwwwroot로 변경하여 사용할 수 있다. <http port='8080'/> Resin을 Standalone으로 구동할 경우 사용할 http port를 지정한다. <srun host='127.0.0.1' port='6802'/> Load balancing을 위해 Apache나 IIS에 plugin으로 Resin을 사용할 경우의 srun port를 지정한다. <http port=8443> <ssl>true</ssl> <key-store-type>pkcs12</key-store-type> <key-store-file>keys/server_cert.p12</key-store-file> <key-store-password>changeit</key-store-password> </http> SSL을 사용하는 경우 위와 같은 설정을 하며 아래의 내용을 포함한다. key-store-type : key store의 종류(ex:비밀키, 공개키 방식) key-store-file : key store 파일의 위치 key-strore-password : key store파일 access password <user-name>resin</user-name> <group-name>resin</group-name> 만약 Unix에서 bin/httpd.sh을 root로 구동할 경우 web server user를 위해 특정 Group name과 User name을 제공해야 한다. RedHat 9.0이후 Linux에서는 bin/resin을 사용해야 한다. <class-update-interval>2s</class-update-interval> 사용자에 의해 class파일이 update됬는지 여부를 검사하는 주기이다. 이 주기에 따라 resin이 검사하므로 해당 주기를 줄이면 변경즉시 반영되므로 개발시 유용하나 서버에 부하가 가중되므로 운영시는 낮춰주는 것이 좋다. <servlet-classloader-hack>false</servlet-classloader-hack> True로 설정하면 Servlet spec 에 따른 classloader를 사용하고 false이면 JDK spec에 따른 classloader를 사용한다. <error-page exception='connection' location='/my-error-page.html'/>Apache나 IIS를 이용할 시에 srun connection 실패시 표시할 error 페이지를 지정한다. <caucho-status>true</caucho-status> Caucho-status를 표시한다. <thread-max>150</thread-max> 서버당 최대 thread갯수 <thread-keepalive id='100'/> Keepalive할 trhead수. <request-timeout id='65s'/> Socket keepalive 시간. SSL을 사용하지 않는다면 짧게 하는 것이 성능에 좋다. <accept-buffer-size id='256'/> Accept buffer상의 socket 수 <thread-min id='5'/> Socket에서 대기될 때 요청되는 최대 thread 수 <ping sleep-time='1m' retry-count='3' retry-time='1s'> <url>http://localhost:8080/ping/ping.jsp</url> </ping> web server 상태를 확인하기 위해 ping test를 하기 위한 설정이다. test결과 failuer가 발생하면 resin은 서버를 restart한다. 해당 test를 위한 thread가 JDK와 같기 때문에 해당 Thread의 deadlocks이나 Database connection 증가로 인한 memory leak같은 경우는 catch할 수 없다. <ignore-client-disconnect>true</ignore-client-disconnect> Browser를 disconnect할 때 발생하는 ClientDisconnectionExceptions을 무시한다 <cache dir='cache' size='1024' entries='8192'/> internal caching을 가능하게 한다. Dir : cache가 적재될 directory size : memory size(kb) entries : entry의 전체 개수 <cache-mapping url-pattern='/' expires='2s'/> Cache된 파일의 유효시간 일반적으로 운영중에는 15m으로 설정한다. <servlet-mapping url-pattern='*.xtp' servlet-name='xtp'/> <servlet-mapping url-pattern='*.jsp' servlet-name='jsp'/> <host>외부의 servlet 설정이다. 이곳에 위치하면 모든 host에 적용된다. <servlet-mapping url-pattern='/servlet/*' servlet-name='invoker'/> URL로부터 servlet명으로 invoke한다. 예를 들어 /examples/basic/servlet/HelloServlet 은 HelloServlet class로부터 시작한다. 일반적으로, 보안상 헛점이 생길 수 있으므로 개발중에만 사용하며 운영중에는 사용하지 않는다. <welcome-file-list>index.xtp, index.jsp, index.html</welcome-file-list> 시작페이지를 지정한다. 3. <host>의 하위 엘리먼트 <access-log id='logs/access.log' format='%h %l %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i"' rollover-period='1W'/> <error-log id='logs/error.log'/> Resin 단독구동 시 로깅을 위한 내용이다. <war-dir id='webapps'/> Specifies a special directory to place war file이 위치한 특정 directory를 지정한다. War directory에 위치한 어떤 .war (web-application resource) file이던지 자동으로 확장/설치 된다. 일반적으로, war file은 설정을 위해 WEB-INF/web.xml 을 사용하며 구문은 다른 application 설정과 동일하다. 4. <web-app>의 하위 엘리먼트 <classpath id='WEB-INF/classes' source='WEB-INF/classes' compile='true'/> classpath를 지정한다. Source는 option이다. Servlets 과 beans는 일반적으로 WEB-INF/classes에 위치한다. <session-config> <session-max>4096</session-max> <session-timeout>30</session-timeout> <enable-cookies>true</enable-cookies> <enable-url-rewriting>true</enable-url-rewriting> <file-store>WEB-INF/sessions</file-store> </session-config> 세션에 관한 설정이다. Session-max : 최대 session 개수 Session-timeout : session timeout 시간(초) Enable-cokkies : 쿠키 사용여부 Enable-url-rewritin : 세션을 아래의 방법중 하나를 사용하여 외부에 적재할 경우 개발 중 class 변경으로 인한 세션 삭제를 방지할 수 있다. File-store : 세션을 지정된 디렉토리에 적재한다. tcp-store : tcp-ring을 사용하여 세션을 적재한다. Jdbc-store : DB table을 사용하여 세션을 적재한다. <multipart-form upload-max='-1'/> multipart-mime/form 사용을 가능하게 한다. <path-mapping url-regexp='^/~([^/]*)' real-path='/home/$1/public_html/'/> url path를 실제 path에 mapping한다. <context-param info='An application information string'/> Application init parameter이다. <servlet-mapping url-pattern='/snoop/*' servlet-name='snoop-servlet'/> 모든 url에서 /snoop에 대하여 snoop-servlet 이름으로 접근한다. <servlet servlet-name='snoop-servlet' servlet-class='Env'> <init-param info='A servlet information string'/> </servlet> snoop-servlet init parameter로 info='A servlet information string'를 사용하여 구동한다. 가비지 콜렉션2004년 1월의 테크팁이었던 href="http://java.sun.com/developer/JDCTechTips/2004/tt0122.html#2">Monitoring -XX:+PrintGC -XX:+TraceClassUnloading 이것은 -verbose:gc 옵션이 어떻게 번역되는지를 보여준다. 이 옵션은 애플리케이션이 실행되는 동안 가비지 콜렉션 이벤트의 리포트를 요구한다. J2SE v1.4.2에서는 가비지 콜렉터를 컨트롤하는 다른 많은 커맨드 라인이 있다. 코드의 어느 라인도 변경하지 않고 애플리케이션의 성능을 최대한으로 활용하려면, 이 옵션들을 최소한 하나 이상 사용할 수가 있다. 이번 팁에서는 가비지 콜렉터를 컨트롤하는 부수적인 많은 자바 커맨드 라인을 다룰 것이지만, 가비지 콜렉션 튜닝 옵션의 전체를 말하지는 않는다. 자바 애플리케이션 런쳐는 표준 커맨드-라인 스위치와 비표준 커맨드-라인 스위치를 모두 동반한다. -verbose:gc 옵션에 관한 정보에 대해 알아보려면, 특정 플랫폼별로 다음 웹페이지를 참고하자.
위의 참고 페이지에는 몇몇 비표준 옵션들에 대해서도 나와있다. 자바 커맨드 라인 툴에서 표준 옵션인 -X을 실행하면 사용자의 플랫폼을 위한 비표준 옵션을 보여준다. 솔라리스 플랫폼이라면, java -Xmixed mixed mode execution (default) 위의 출력값의 마지막 줄을 주목하자. 그러한 비표준 옵션들을 사용하는 것은 사용자의 책임 하에 있음을 분명히 나타내고 있다. 가비지 콜렉션을 위한 세 가지 특정한 비표준 옵션은 -Xnoclassgc, -Xincgc, 썬의 1.4.2 구현에서 -Xincgc은 -XX:+UseTrainGC 옵션과 동등한 값을 가진다. 즉, -Xincgc은 old generation을 위해서 디폴트 값에서 주어진 "serial" 콜렉터를 사용하기 보다는 "train"콜렉터를 사용한다. ("generations"의 개념은 이번 팁의 후반에서 다루게된다.) train 콜렉터는 약 10%의 퍼포먼스 부하를 발생시킨다. 또한 old generation 전체를 한 번에 수집할 수 없기 때문에 약간의 공간적인 부하(space overhead)도 발생한다. train 콜렉터는 점진적으로 작동하는 장점을 가지기 때문에 휴지 시간이 상당히 짧다. J2SE 1.5.0 베타 릴리즈에서는 -Xincgc 플래그는 train 콜렉터보다는 CMS(concurrent mark sweep) 콜렉터를 인보킹하게 된다. 그 이유는, CMS 콜렉터가 train 콜렉터보다 더 균일하기 때문이다. -Xloggc 옵션을 지정해줌으로써 -verbose:gc 출력값의 등가를 파일로 출력할 수 있다. -verbose:gc 에 의한 출력값과 비교해 보면, -Xloggc 에 의한 출력값은 한 가지 추가적인 항목을 포함하는데, 그것은 애플리케이션에서의 첫 콜렉션이 일어난 시간에서부터 가비지 콜렉션이 발생한 시간에 대한 정보이다. 다음의 -Xloggc 샘플 출력값에서 살펴보자. 0.000: [GC 512K->153K(1984K), 0.0198483 secs] 파일에 재전송할 필요없이 -XX:+PrintGCTimeStamps 옵션을 지정해줌으로써 -Xloggc 출력값에 시간 소인을 나타낼 수 있다. -Xnoclassgc, -Xincgc 과 -Xloggc:<file> 이외에도 가비지 콜렉터를 컨트롤하는 다른 옵션들이 존재한다. 예를 들자면, 콜렉터가 실행할 때 간접적으로 영향을 끼치도록 -Xms와 -Xmx 옵션을 사용하여 메모리 할당의 풀 사이즈를 변경할 수 있다. -Xms의 값을 크게 지정해주면, 그만큼 큰 자바 객체 힙으로 작업하게 된다. 이것은 힙을 채우는 데에 더 많은 시간이 걸린다는 것을 의미하고 결과적으로 콜렉션을 피하지는 않지만 미루게 된다는 것이다. 큰 -Xms 값은 또한 더 많은 시스템 리소스를 소모하게 된다. 반면 -Xmx의 값을 크게 지정하면, 자바 객체 힙의 사이즈가 필요 시에 커질 수 있게 된다. 이렇게 값이 큰 객체 힙은 조금 덜 빈번하게 가비지 콜렉트된다는 점 외에는 모든 점이 동일하다. 따라서 이 옵션을 통해 가비지 콜렉션이 빈번하지만 짧은 시간동안 일어나는 것과, 횟수는 적지만 오랜 시간동안 가비지 콜렉션이 일어나는 것 중 하나를 선택할 수 있다. 하지만 각각의 콜렉션이 부하를 발생하기 때문에, 사용자가 정의하는 요구조건에 따라 더 나은 접근법은 달라지게 되어있다. -Xms 와 -Xmx 외에도 가비지 콜렉션에 영향을 주는 비표준 옵션들이 존재한다. 그 옵션들은 java -X 도움말에서 볼 수 없는데, 그 이유는 이 옵션들은 비표준 옵션이기 때문에 두개의 X를 사용해야하기 때문이다. 만약 힙의 최소값과 최대값을 지정해주고자 한다면 (이 때, 디폴트 값의 범위는 40%~70%), -XX 세트내의 다른 비표준 옵션들은 가비지 콜렉터의 작동 방법에 영향을 끼친다. -XX:+UseConcMarkSweepGC 커맨드 라인 플래그("concurrent mark sweep garbage collection"의 줄임말)는 병행(concurrent) 가비지 콜렉터를 실행시킨다. -XX:+UseConcMarkSweepGC 콜렉터는 old generation을 동시에 콜렉팅한다. 그 이유는 전반적인 콜렉션 같은 old generation 들은 콜랙팅할 때 대체적으로 시간이 오래 걸려서 병행 가비지 콜렉터를 실행시키는 것이 더 효과적이기 때문이다. 이는 애플리케이션에서 가비지 콜렉션 휴지 시간을 짧게 할 수 있도록 프로세싱 파워를 활용한다는 것을 말한다. -XX:+UseParallelGC 커맨드 라인 플래그는 병렬 가비지 콜렉팅을 가능하게 한다. -XX:+UseParallelGC 콜렉터는 오직 다중 프로세서를 이용한 young generation만을 콜렉팅한다. 이 접근법은 처리율은 높이지만, 전반적인 콜렉션의 휴지 시간을 줄이지는 못한다. 또 하나의 흥미로운 옵션인 -XX:+PrintGCDetails 는 각각의 콜렉션에서 각 generation에 어떤 일이 발생했는지를 보여준다. (단, permanent generation 에 대한 자세한 사항들은 보여주지 않는다. 이 점은 JDK 1.5.0.에서 수정되었다.) SwingSet2의 데모에 사용된 -XX:+PrintGCDetails의 예제를 살펴보자. (출력값의 라인들은 테크팁 페이지의 경계선에 맞추기 위해 나누어주었다.) java -Xloggc:details.out -XX:+PrintGCDetails -jar 변경내용이 그 결과에 어떤 영향 (예를 들어서, 콜렉션간의 시간 연장이나 각각 특정 휴지 시간의 감소)을 주는지를 알아보기 위해 -Xms 옵션과 -Xmx 옵션을 조정해보자. 앞서 'generations'의 힙 공간에 대해 언급한 바 있다. 이 말이 무슨 의미인지 궁금하다면, 여기 짤막한 설명을 참조하자. JRE 1.4.2 에서 힙은 young, old, 그리고 permanet와 같이 세 개의 generation으로 구분된다. young generation은 객체가 생성된 장소이다. 이 generation의 사이즈는 -XX:NewSize 옵션과 -XX:MaxNewSize 옵션에 의해 컨트롤된다. 새로운 객체를 보유하게 되면, old generation으로 승격된다. old generation의 사이즈는 전체 힙 사이즈 (-Xms 과 -Xmx) 에서 young generation의 사이즈 (-XX:NewSize 과 -XX:MaxNewSize)를 감한 사이즈로 계산된다. young generation은 명시적 크기보다는 -XX:NewRatio=를 이용하여 더 잘 지정할 수 있는데, -XX:NewRatio= 옵션은 힙 설정의 전체 사이즈를 설정해주기 때문이다. 선택한 사이즈는 콜렉팅 되는 시간에 대해 콜렉션의 횟수를 결정하게 된다. 어떤 애플리케이션들은 짧은 휴지 시간을 요구하는 한편, 콜렉터의 효율성을 필요로 하는 애플리케이션들도 있다. (많은 애플리케이션에서 이 단계의 튜닝을 해줄 필요는 전혀 없다.) 마지막으로 언급할 GC옵션은 -XX:+DisableExplicitGC이다. System.gc()의 호출을 이용하여 가비지 콜렉터를 실행하라는 명령을 했을 때, 시스템이 이를 무시하기를 원한다면 이 옵션을 사용해보자. 가비지 콜렉터는 프로그래머가 명령했을 때가 아닌, 필요시에 계속해서 실행되고 있을 것이다. 하지만 프로그래머의 명령을 무시하는 것이 좋은 생각일까? 아마도 아닐 것이다. 왜냐하면, 프로그래머가 가비지 콜렉터를 실행하기 적당한 시점이라고 생각할 수 있기 때문이다. 물론, 만약 공유 라이브러리를 사용하고 있고, 실행 콘텍스트가 프로그래머의 원래의 계획과 다르다면, 이러한 새로운 상황에 유효하지 않을 수도 있다. 가비지 콜렉션에 관련된 옵션들에 대해 좀더 자세한 정보를 원한다면, href="http://java.sun.com/docs/hotspot/gc1.4.2/">Tuning
|
카테고리
이전블로그
이글루링크
최근 등록된 덧글
퍼갑니다~~
by hsu at 11/02 여러 자료를 보며 공부.. by ^_^ at 01/05 모사이트 를 들어가서 그.. by dfdssds at 12/19 감사합니다 퍼갈께요 by ㄳ at 06/19 좋은 글 잘 보았습니다. .. by Oops at 12/14 아니에요..과한 칭찬... by 제이 at 09/14 머야....누가 우리 알.. by 제이 at 09/14 대부분 아실 내용인데 약.. by 제이 at 09/10 java service 등록관.. by 바나나우유중독자 at 09/10 알님...이미 자격은 .. by 제이 at 09/05 메모장
ITIL Foundation PMP CISSP CISA 기술사 최근 등록된 트랙백
Estradiol.
by Normal estradiol range. Tramadol. by Cheap tramadol. Seroquel. by Seroquel and bipolar. Does fioricet show up.. by Fioricet message bo.. Oxycodone. by Hyrocodone oxyco.. Adipex online best .. by Phentermine adipex .. Butalbital. by Apap butalbital caffe.. Adipex. by Ordering adipex onli.. When someone sniff .. by Oxycodone. Ephedrine. by Ephedrine products fo.. 이글루 파인더
라이프로그
|