달력

5

« 2024/5 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
2013. 8. 9. 11:29

부산 여행 Tip I.lib()/I.lib(etc)2013. 8. 9. 11:29

.. .. ..

[펌] : URL이 날아갔다 죄송 ㅜㅠ

 

여행 팁

부산 여행 꼼꼼 관광 정보

 

 

 

 

부산 여행, 이것도 모르고 가면 되나, 안 되나? 마!

여행에선 아는 것이 힘! 부산 여행에 유용한 알짜 정보를 모았다.

글 송보배 기자

교통정보

1일권

지하철을 4회 이상 이용할 경우 1일권이 더 유리하다. 1일권을 구입하면 발매 당일에 한해 횟수 제한 없이 지하철을 이용할 수 있다. 각 역 승차권 자동발매기에서 구입할 수 있으며 요금은 4000원이다.

교통카드

티머니 교통카드는 타 지역에서 사용하던 것이라도 그대로 이용할 수 있다. 후불 신용카드 역시 지역에 관계없이 사용 가능하다.

환승

교통카드 이용 시 버스나 지하철에서 내린 후 30분 이내에 다른 대중교통으로 갈아타면 2회까지 환승 할인을 받을 수 있다.

짐 보관

당장 필요 없는 짐이라면 지하철 물품보관함을 찾아보자. 1200~1500원의 비용으로 이용할 수 있다. 대부분의 지하철역에 물품보관함이 갖추어져 있는데 특히 자갈치역, 해운대역, 광안리역 등에는 사이즈별로 마련되어 여행자의 편의를 돕고 있다.

문의 1544-5005 www.humetro.busan.kr

숙박

찜질방

광안리 아쿠아펠리스호텔 찜질방(051-790-2345)과 해운대구의 로데오찜질타운(051-741-3753)은 널찍한 규모에 비해 덜 알려져 있어 도심보다 덜 붐비는 곳이다. 광안리의 호메르스호텔 찜질방(051-750-8056), 부산역 인근의 발리아쿠아랜드(051-442-1551)도 숙박이 가능한 찜질방이다.

게스트하우스

나 홀로 여행자나 여성 여행자라면 게스트하우스를 권할 만하다. 해운대 하이코리아호스텔(070-4409-3132), 해운대구 중동의 포비게스트하우스(051-746-7990)는 깔끔한 인테리어와 2만~3만원의 저렴한 비용으로 많은 여행객들이 찾는 곳.

호텔

가족 단위로 방문했다면 호텔이 편리하다. 해운대 파라다이스호텔(051-742-2121)은 해운대해수욕장의 특급 호텔 중에서도 단연 최고의 명성을 자랑한다. 달맞이고개 입구의 호텔일루아(051-744-1331)는 인근 호텔에 비해 비교적 저렴한 가격이 장점. 씨클라우드호텔(051-933-1000)은 피트니스센터, 수영장을 함께 이용할 수 있다. 동래에는 50년 전통의 농심호텔(051-550-2100)이 유명한데 온천욕 시설 허심청이 갖춰져 있다. 부산역이나 중앙동에서는 코모도호텔(051-466-9101)에 머물 만하다. 이순신 장군을 형상화한 독특한 외관이 특징. 광안리해수욕장 인근에는 호메르스호텔(051-750-8000)이 있다. 저렴한 비용의 호텔로는 토요코인이 제격. 현재 해운대지점(051-256-1045), 서면지점(051-638-1045), 부산역1지점(051-466-1045), 부산역2지점(051-442-1045)이 운영되고 있다.

부산 버스투어.jpg

부산 시티투어버스

시티투어 버스

순환형 버스로는 해운대와 태종대 코스가 매일 30분 간격으로 운영된다. 이층 버스가 특색 있고 관광지도 쉽게 둘러볼 수 있어서 인기 만점.

순환형 버스는 티켓 1장으로 해운대와 태종대 두 코스를 모두 이용할 수 있고 이 밖에 역사 문화 탐방 코스, 해동용궁사 코스, 을숙도 자연 생태 코스, 야경 코스도 하루 1~2회 운영된다.

출발 장소 부산역 광장

해운대 코스 부산역 - 부산박물관 - 광안리해수욕장 - 누리마루- 해운대해수욕장 - 해운대역 - 신세계백화점 - 시립미술관(벡스코) - 광안대교 - UN기념공원 - 부산역

태종대 코스 부산역 - 연안여객터미널 - 75광장 - 태종대 - 국립해양박물관 - 남항대교 - 송도해수욕장 - BIFF광장·자갈치 - 부산역

요금 어른 1만원, 어린이 5000원 문의 1688-0098, 051-464-9898

관광 문의처 안내

축제

부산국제영화제(10월 4~13일) 1688-3010

부산세계불꽃축제(10월 26~27일) 051-501-6051

관광안내소

부산역관광안내소 051-441-6565

남포동관광안내소 051-253-8253

송정관광안내소 051-749-5800

해운대종합관광안내소 051-749-5700

교통

철도 1544-7788

부산종합버스터미널 1577-9956

동부시외버스터미널 1688-9969

서부시외버스터미널 1577-8301

부산-유람선.jpg

바다를 가르는 태종대 유람선

유람선

팬스타크루즈 1577-9996

테즈락크루즈 051-463-7680

티파니21 051-743-2500

해운대관광유람선 051-742-2525

해운대·자갈치관광유람선 051-441-2525

태종대관광유람선 051-405-2900

 

'I.lib() > I.lib(etc)' 카테고리의 다른 글

리눅스에서 아파치 설치 및 설정  (0) 2013.11.08
에디트 플러스 (Edit Plus) 칸단위 선택  (1) 2013.08.14
PMD Rule Set 정리 [펌]  (0) 2013.07.30
겔럭시 s 부두 패치 경로  (0) 2013.04.19
[펌] TDD  (0) 2013.03.28
.
:
Posted by .07274.
2013. 8. 8. 16:28

jBoss 기초 및 설치 I.lib()/I.lib(jBoss)2013. 8. 8. 16:28

.. .. ..

[펌] : http://ssiso.net/cafe/club/club1/board1/content.php?board_code=jsp%7Csetting&idx=30224&club=jsp

 

JBossAS 설치하기


본 기사에서는 JBoss를 처음 접하는 사용자가 JBoss를 설치하고 동작시키는 그 과정을 설명합니다.


JBossAS란?


JBossAS(JBoss Application Server)란 오픈소스 Java EE 서버입니다. Java EE 서버란 Java Enterprise Edition(EE) 표준에 따라 구현된 서버를 의미합니다. Java EE 서버를 흔희 Java EE 서버를 WAS(Web Application Server)라고 부르는데 이러한 서버는 BEA WebLogic, Tmax JEUS, IBM WebSphere, Adobe JRUN, JBoss, Apache Geronimo 등이 있습니다.


Apache Tomcat과 JBossAS


Apache Tomcat은 Java EE 표준에 포함되어 있는 JSP, Servlet, JSTL 등과 같은 웹 애플리케이션 개발을 위한 표준을 구현한 웹 컨테이너입니다. Java EE 표준에는 다양한 컨테이너가 정의되어 있는데 대표적인 컨테이너가 웹 컨테이너와 EJB 컨테이너입니다. 웹 애플리케이션을 개발하기 위해서 필요한 웹 컨테이너를 구현한 것이 바로 Apache Tomcat이며, JBossAS는 Java EE 표준에 포함되어 있는 모든 표준을 구현한 완전한 Java EE 서버라고 할 수 있습니다.

예를 들면 EJB나 JMS를 사용한 애플리케이션을 개발하고자 하는 경우에는 반드시 JBossAS와 같은 Java EE 표준을 모두 구현한 서버를 사용해야 겠습니다. 그러나 단순한 웹 애플리케이션을 구현하는 경우에는 Apache Tomcat을 사용할 수 있습니다. JBossAS에는 기본적으로 Tomcat이 내장되어 있으므로 Tomcat을 사용했었던 사용자는 손쉽게 JBossAS로 웹 애플리케이션을 이전할 수 있습니다.



JBossAS 다운로드하기


현재 릴리즈되어 있는 JBossAS는 4.2.1GA입니다. 이 버전은 기본적으로 JDK 1.5를 기반으로 동작하므로 http://java.sun.com/javase/downloads/index_jdk5.jsp 에서 JDK 1.5를 다운로드하여 설치해야 합니다.



JDK 1.5가 이미 설치되어 있다면
http://labs.jboss.com/jbossas/downloads에서 JBoss 4.2.1GA를 다운로드 합니다. 그리고 난 후 C:\jboss-4.2.1.GA에 압축을 해제함으로써 설치가 완료됩니다.




JBossAS 설정하기

JBossAS를 구동하기 위해서는 JDK 1.5를 JBossAS가 사용하도록 설정해야 합니다. 이 작업은 시스템 환경변수를 통해 할 수도 있으며 서버 구동 스크립트(run.bat 또는 run.sh)를 통해서 할 수도 있습니다. 저는 후자를 더 추천합니다.

우선 JDK 1.5를 JAVA_HOME을 설정하기 위해서 C:\jboss-4.2.1.GA\bin\run.bat 파일을 다음과 같이 수정하도록 합니다.


@echo off
rem -------------------------------------------------------------------------
rem JBoss Bootstrap Script for Win32
rem -------------------------------------------------------------------------

set JAVA_HOME=C:\jdk1.5.0_11

rem $Id: run.bat 63249 2007-05-30 13:20:25Z dimitris@jboss.org $

@if not "%ECHO%" == "" echo %ECHO%
@if "%OS%" == "Windows_NT" setlocal

... 생략

이제 JBoss를 구동하기 위한 기본 환경이 완료되었습니다.



JBossAS 구동하기

이제 마지막 단계로 JBossAS를 구동할 차례입니다. 구동을 하기 이전에 JBoss의 구동 방식을 먼저 확인해볼 필요가 있습니다. JBoss는 하나의 서버내에 여러 개의 설정을 구성하고 그 구성을 선택하여 구동시킬 수 있습니다. 예를 들면 어떤 설정은 모든 서비스가 다 구동되도록 할 수 있으며, 어떤 설정은 애플리케이션을 동작시키기 위해서 필요한 최소한의 설정만을 포함하도록 하여 구동시킬 수 있습니다. 저는 이것을 Profile이라고 부릅니다. 이 Profile은 <JBOSS_HOME>/server 디렉토리에 설정되어 있습니다. 기본적으로 JBossAS를 설치하면 all, default, minimal이 설정되어 있으며 다음과 같이 구동시키는 경우 default가 적용되어 구동합니다.

C:\jboss-4.2.1.GA\bin>run.bat
===============================================================================

JBoss Bootstrap Environment

JBOSS_HOME: C:\jboss-4.2.1.GA

JAVA: C:\jdk1.5.0_11\bin\java

JAVA_OPTS: -Dprogram.name=run.bat -server -Xms128m -Xmx512m -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000

CLASSPATH: C:\jdk1.5.0_11\lib\tools.jar;C:\jboss-4.2.1.GA\bin\run.jar

===============================================================================

13:44:34,062 INFO [Server] Starting JBoss (MX MicroKernel)...
13:44:34,093 INFO [Server] Release ID: JBoss [Trinity] 4.2.1.GA (build: SVNTag=JBoss_4_2_1_GA date=200707131605)
13:44:34,093 INFO [Server] Home Dir: C:\jboss-4.2.1.GA
13:44:34,093 INFO [Server] Home URL: file:/C:/jboss-4.2.1.GA/
13:44:34,093 INFO [Server] Patch URL: null
13:44:34,093 INFO [Server] Server Name: default
13:44:34,093 INFO [Server] Server Home Dir: C:\jboss-4.2.1.GA\server\default
13:44:34,093 INFO [Server] Server Home URL: file:/C:/jboss-4.2.1.GA/server/default/
13:44:34,093 INFO [Server] Server Log Dir: C:\jboss-4.2.1.GA\server\default\log
13:44:34,093 INFO [Server] Server Temp Dir: C:\jboss-4.2.1.GA\server\default\tmp
13:44:34,093 INFO [Server] Root Deployment Filename: jboss-service.xml
13:44:34,812 INFO [ServerInfo] Java version: 1.5.0_11,Sun Microsystems Inc.
... 생략


만약에 다른 Profile를 구동하고자 하는 경우 다음과 같이 구동시키도록 합니다.

C:\jboss-4.2.1.GA\bin>run.bat -c all

필요한 경우 이 Profile를 복사하여 구동할 수도 있습니다. 예를 들면 default를 test라는 이름으로 복사한 후 "run.bat -c test"로 구동시킬 수도 있습니다.


JBossAS 웹 콘솔 접근하기

이제 마지막으로 JBossAS를 구동시키고 난 후 웹 콘솔에 접근해 보는 방법입니다. JBossAS는 기본적으로 웹 컨테이너를 Tomcat을 사용하므로 기본 포트로 8080 포트를 사용합니다. 따라서 다음과 같이 웹 브라우저에서 http://localhost:8080 을 입력하면 웹 페이지가 나타납니다.




JBossAS의 구동 IP 변경하기

JBossAS를 다른 PC 또는 서버에 설치하고 난 후에 이 장비에 접근하고자 하는 경우 JBossAS의 구동 스크립트(run.bat) 파일을 호출할 때 IP를 지정해야 합니다. 기본적으로 JBossAS를 구동하면 127.0.0.1 IP로 바인딩 되므로 접근이 불가능해 집니다. 예를 들면 개발 PC는 192.168.1.2이고 JBossAS는 192.168.1.3 Linux 머신에 설치되어 있는 경우 JBossAS를 run.bat로만 구동하게 되면 192.168.1.3 IP로 접근할 수 없게 됩니다(예; http://192.168.1.3:8080). 이러한 이유로 JBossAS를 192.168.1.3 IP로 바인딩 되도록 하려면 다음과 같이 IP를 기술하도록 합니다.

C:\jboss-4.2.1.GA\bin>run.bat -c all -b 192.168.1.3

이렇게 하게 되면 이제 웹 콘솔 및 JBoss JNDI에 접근할 수 있게 됩니다.
[본문링크] JBoss설치하기

 

.
:
Posted by .07274.
.. .. ..

[펌] : http://yally93.egloos.com/2991005

 

1. 역시 CXF를 다운 받아 압축을 풀어 놓는다.
2. 자바 및 서버를 설치한다.
3. WEB-INF/web.xml을 수정한다. 이렇게 되면 아래의 WS 가 들어간 URL은 모두 CXF를 타게 된다.
- 블로그의 특성상 <url-pattern>/WS/ * </url-pattern> 로 띄어쓰기를 빼고 수정하여 넣어라.

<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/beans.xml</param-value>
</context-param>

<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

<servlet>
<servlet-name>CXFServlet</servlet-name>
<!--display-name>CXF Servlet</display-name-->
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/WS/-</url-pattern>
</servlet-mapping>
</web-app>
4. WEB-INF/lib 폴더에 CXF 라이브러리(*.jar파일)를 집어 넣는다. 귀찮아서 모두 다 넣어 버렸다. ㅋㅋㅋ
- 일단 정리


5. WEB-INF/beans.xml 을 설정한다(web.xml에 이렇게 정의 하였다.).
- 테스트 이므로 cxf.xml, cxf-extension-soap.xml, cxf-servlet.xml 파일은 정의 하지 않았다.
- endpoint 를 주의해서 보기를 바란다. 이 부분이 해당클래스와 URL을 매핑하여 주는 부분인 듯 싶다.
- 클래스 생성 시 endpointInterface 를 통하여 넣을 수 있을 것도 같은데 그 쪽 테스트가 진행이 되지 않는다. 아직 모르겠다.
- endpoint 를 통하여 접속 URL이 어떻게 바뀌는지를 확인하여 본다.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint id="orderProcess" implementor="demo.order.OrderProcessImpl" address="/OrderProcess" />
<jaxws:endpoint id="testProcess" implementor="demo.order.TestProcessImpl" address="/TestProcess" />
</beans>
7. 두 개 정의된 XML중 간단한 TestProcess를 구현한다(나머지 하나는 알아서 필요하면 만들기를...).
- TestProcess.java
package demo.order;

 

import javax.jws.WebService;

@WebService
public interface TestProcess {
String getTest(String src);
}
- TestProcessImpl.java
package demo.order;

import javax.jws.WebService;

@WebService(endpointInterface = "demo.order.TestProcess")
public class TestProcessImpl implements TestProcess {
public String getTest(String src) {
return "TEST rtn:"+ src;
}
}

이렇게 되면 URL로 접속하여 볼 수가 있다.
현재 server.xml 에 포트등을 일부러(서버 두대를 띄우기 위하여) 8090으로 바꾸어 테스트를 진행하였으니 포트나 URL을 자세히 분석하기를 바란다.

먼저 web.xml에 WS를 CXF로 리턴시키기 때문에 아래의 URL을 확인한다. (sever의 path도 /로 잡혀 있어 아래의 URL을 만들었다.
http://localhost:8090/WS


OrderProcess 와 TestProcess가 보인다.
이 두 웹서비스는 processOrder 웹메소드와 getTest 웹메소드를 각각 하나씩 가지고 있음을 확인할 수가 있다.
이 정보에서 WSDL을 클릭하여 보면 http://localhost:8090/WS/TestProcess?wsdl 해당 wsdl URL을 얻을 수가 있으며 이 정보가 서로 주고 받는 입출력 정의가 된다.

이상 끝~~~~

 

'I.lib() > I.lib(Axis2)' 카테고리의 다른 글

AXIS2 정리 및 요약  (0) 2010.09.06
Axis + eclipse 이용 client 설정  (0) 2010.05.20
axis2 + eclipse Server 올리는 설정  (1) 2010.05.20
AXIS2 관련 ERROR  (2) 2010.05.19
Axis2 설치 / 설정  (2) 2010.04.27
.
:
Posted by .07274.
.. .. ..

이클립스의 에러 메시지를 보면 아래와 같은 에러 메시지를 확인할수 있다.

 

faceted project problem (java version mismatch)

 

해결 방법은 아래와 같다.

 

1. 프로젝트 선택 마우스 우클릭 -> properties -> project facets -> java 버젼 확인 및 설정

2. 프로젝트 선택 마우스 우클릭 -> properties -> java compiler -> jdk compile 버젼 설정

 

해결 되시면 댓글 부탁드릴께요^^

.
:
Posted by .07274.
.. .. ..

[펌] : http://cafe.daum.net/dbmsclub/LLPP/21?docid=1Ex4ELLPP2120091217141531

 

일반적으로 텍스트 데이터의 적재프로그램을 만들다보면, 기존에 있는 자료에 대해서는 업데이트를 수행하고 신규자료인 경우는 등록을 해야하는 업무가 있습니다. 비단, 적재뿐아니라 통계분석 데이터의 생성인 경우에도 이 내용은 해당이 되는데 보통은 upsert라고 해서 delete and insert기법을 많이들 활용하십니다만, 오라클에서는 merge구문을 지원합니다. 이 문장은 oracle이 알아서 update할것인지 insert할것인지 데이터를 선별해서 처리를 해주게 되는데요. 뭐 많이 어려운 구문도 아니고 사용하기도 간편하니까 어떤 방식으로 사용할 수 있는지 확인해봅시다.

 

문장 표준) MERGE INTO TARGET_TABLE A /* 실제 데이터가 저장될 TARGET TABLE입니다. */

USING (SELECT COL_A,COL_B... /* TARGET에 저장할 데이터가 있는 원본 데이터가 있는 테이블 또는 QUERY입니다 */

FROM SOURCE_TABLE

WHERE 조건들....) B

ON ( A.COL_A = B.COL_A ) /* 원본과 타겟의 컬럼이 어떤 값으로 중복되는지 체크할 조건입니다. 이 값으로 */

/* 오라클은 업데이트해야할지 INSERT해야할지를 결정합니다. */

WHEN MATCHED THEN /* 만약 조건이 같은 경우 UPDATE할 내용을 기술합니다. */

UPDATE SET

A.COL_B = B.COL_B

,A.COL_C = B.COL_B

WHEN NOT MATCHED THEN /* INSERT해야할 내용을 기술합니다. */

INSERT (COL_A,COL_B,COL_C....)

VALUES ( B.COL_A,B.COL_B,....);

위의 형식으로 구문을 사용하시게 되면, 오라클은 데이터가 UPSERTED되었다고 결과가 나오게 되고, 몇개의 ROW가 UPDATE또는 INSERT되었는지 확인하실 수 있습니다.

 

예제)

MERGE INTO DATA1004_6 M
USING (SELECT TRADE_DATE AS YMD
,MIN(REAL_CLASSCODE||LPAD(REPLACE(UNIT_SIZE,' ',''),7,'0')||UNIT_CODE) PM_KEY
,REAL_CLASSCODE
,REPLACE(UNIT_SIZE,' ','') AS UNITSIZE /* RPAD쓰지 않아도 CHAR TYPE이라 자동 ' '추가됨 */
,UNIT_CODE AS UNITCODE
,GRADE_CODE AS GRADECODE
,AVG(JOSA_PRICE) AS P_MEAN
FROM SRC_DATA1004
WHERE TRADE_DATE >= in_st_dt
AND TRADE_DATE <= in_ed_dt
AND JOSA_GUBUN_CODE = '6' -- 도소매
AND JOSA_PRICE <> 0
GROUP BY TRADE_DATE,REAL_CLASSCODE,UNIT_SIZE,UNIT_CODE,GRADE_CODE) T
ON ( M.YMD = T.YMD
AND M.PM_KEY = T.PM_KEY
AND M.GRADECODE = T.GRADECODE)
WHEN MATCHED THEN
UPDATE SET
M.P_MEAN = T.P_MEAN
WHEN NOT MATCHED THEN
INSERT (YMD,PM_KEY,REAL_CLASSCODE,UNITSIZE,UNITCODE,GRADECODE,P_MEAN)
VALUES (T.YMD,T.PM_KEY,T.REAL_CLASSCODE,T.UNITSIZE,T.UNITCODE,T.GRADECODE,T.P_MEAN);

위 예제의 경우는 SRC_DATA1004 테이블의 데이터를 읽어서 해당하는 값이 DATA1004_6에 존재하는 경우는 UPDATE하고

존재하지 않는 경우는 INSERT하는 프로그램입니다. 일주일치를 수행하는데 약 1만건 정도인데, 2-4초정도 걸리는군요.

 

프로그램코딩시 유의할 오류유형)

1.ORA-30926 에러가 발생하는 경우

ORA-30926 원본 테이블의 고정 행 집합을 가져올 수 없습니다.

ORA-30926 unable to get a stable set of rows in the source tables

- MERGE 를 사용하는 경우

1) INTO 절에 사용되는 테이블에 Primary Key 를 사용하는 경우
즉 INSERT 구문에서 DUPLICATE가 발생하거나 UPDATE 에 MULTI
ROW가 UPDATE되는 경우

2) ON 구문에서 UPDATE되는 ROW가 1개 이상일 경우
즉 ON 구문에서 맞는 테이블 값이 하나 이상일 경우

2.ORA-00001 에러가 발생하는 경우

이 에러는 TARGET이 되는 테이블에는 중복건이 없어서 UPDATE를 할려고 했는데,

SOURCE테이블 자체에서 데이터가 중복건이 있어서 두번INSERT하려고 하다가 문제가 발생합니다.

보통 문자타입이나 사이즈를 잘못잡아서 INSERT할 대상자체를 중복인지 아닌지 모르는 경우에

발생하게 되므로, TRIM처리를 해서 비교하시든 파일자체에 중복이 있는지 확인을 하시든 하는 방법으로

에러를 처리하실 수 있습니다.

.
:
Posted by .07274.
2013. 8. 6. 11:56

spring transactionManager 설정 I.lib()/I.lib(Spring)2013. 8. 6. 11:56

.. .. ..

[펌] : http://springmvc.egloos.com/499291

 

 

<tx:annotation-driven />
<aop:config>
<aop:advisor advice-ref="transactionAdvice" pointcut="bean(*Service)" />
</aop:config>

<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="exceptionPut" propagation="REQUIRES_NEW" />
<tx:method name="get*" propagation="REQUIRED" read-only="true" />
<tx:method name="*" />
</tx:attributes>
</tx:advice>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

전 장에서 <aop>까지 했으니 이제 <tx> 요소에 대해 설명할 차례네요. <tx>는 스프링 트랜잭션 기술의 집약체입니다. 스프링의 트랜잭션 기술은 전장에서도 말했듯이 어노테이션 적용법과 AOP 적용법 2가지가 있으며 위의 예제는 당연히 AOP 적용법입니다.

먼저 <tx:advice>로 트랜잭션 어드바이스를 하나 만듭니다. 여기에 적용한 트랜잭션을 선택하는데 만약 트랜잭션 빈의 이름이 'transactionManager'이라면 위의 'transaction-manager' 속성은 생략될 수 있습니다. 위의 예제에서는 다만 원리를 설명하기 위해 속성을 넣어둔 것 뿐이므로 현재 'transaction-manager'은 생략이 가능하다 할 수 있겠네요.

그다음 <tx:attributes>의 <tx:method>로 세밀하게 메서드별 속성을 조절해주도록 합시다. 우리는 이 부분에서 어느 메서드에 트랜잭션을 적용할 것인지 선택할 수 있으며 속성에는 다음과 같은 값들이 존재합니다.

name - 메서드명
메서드의 이름이며 와일드 문자(*)를 사용할 수 있습니다. 예로 'get*'은 get으로 시작하는 모든 메서드를 가리키며'*get'은 get으로 끝나는 모든 메서드를 가리킵니다.

timeout - 제한시간 (기본값 : -1)
트랜잭션의 제한시간을 설정합니다. DB가 해당기능을 지원해야 하며 기본값으로는 -1인 제한시간 없음이 설정됩니다.

propagation - 전파옵션 (기본값 : REQUIRED)
REQUIRED : 부모 트랜잭션 내에서 실행하며 부모 트랜잭션이 없을 경우 새로운 트랜잭션을 생성합니다.
REQUIRES_NEW : 부모 트랜잭션을 무시하고 무조건 새로운 트랜잭션이 생성되도록 합니다.
SUPPORT : 부모 트랜잭션 내에서 실행하며 부모 트랜잭션이 없을 경우 nontransactionally로 실행됩니다.
MANDATORY : 부모 트랜잭션 내에서 실행되며 부모 트랜잭션이 없을 경우 예외가 발생됩니다.
NOT_SUPPORT : nontransactionally로 실행하며 부모 트랜잭션 내에서 실행될 경우 일시 정지 됩니다.
NEVER : nontransactionally로 실행되며 부모 트랜잭션이 존재한다면 예외가 발생합니다.
NESTED : 해당 메서드가 부모 트랜잭션에서 진행될 경우 별개로 커밋되거나 롤백될 수 있습니다. 둘러싼 트랜잭션이 없을 경우 REQUIRED와 동일하게 작동합니다.

isolation - 격리수준 (기본값 : DEFAULT)

DEFAULT : DB에서 설정된 기본 격리 수준을 따릅니다.
SERIALIZABLE : 가장 높은 격리수준을 가지며 사용시 성능 저하가 있을 수 있습니다.
READ_UNCOMMITTED : 커밋되지 않은 데이터에 대한 읽기를 허용합니다.
READ_COMMITTED : 커밋된 트랜잭션에 대해 읽기를 허용합니다.
REPEATABLE_READ : 동일한 필드에 대한 다중 접근 시 동일한 결과를 얻을 수 잇는 것을 보장합니다.

read-only - 읽기전용 (기본값 : false)

해당 메서드는 오로지 읽기에만 사용됩니다. INSERT나 UPDATE, DELETE문은 허용되지 않습니다. 만약 쓰기나 삭제가 실행될 경우 에러를 발생시킵니다.

rollback-for - 예외처리 (기본값 : RuntimeException)

특정 예외가 발생했을 경우에 롤백되도록 설정합니다. 설정하지 않을 경우 오로지 RuntimeException을 상속받은 예외에만 롤백처리를 해줍니다.

no-rollback-for - 예외처리 (기본값 : 없음)

특정 예외가 발생하더라도 롤백되지 않도록 설정합니다.

위의 속성과 값들이 <tx:method>에서 설정할 수 있는 전부입니다. 잘 알아본 다음 자신에게 맞는 속성을 설정한 후에 완성된 <tx:advice>를 <aop:config>에 주입하기만 하면 자동프록시검색기가 알아서 <tx>어드바이스와 pointcut을 해석하여 해당 요청을 대신 처리해 줄 것입니다.

이제 거의 막바지에 왔네요. 다음은 <tx:annotation-driven />에 대한 설명입니다. 이 요소가 설정되있다면 트랜잭션을 어노테이션으로 설정 가능하게 합니다. 설정방법은 트랜잭션을 원하는 메서드에 @Transactional이란 어노테이션을 붙이면 그만이며 <aop>설정은 어노테이션과 전혀 무관합니다. 어노테이션 트랜잭션은 오로지 <tx:annotation-driven /> 요소만을 요구합니다.

@Transactional(isolation=Isolation.DEFAULT, propagation=Propagation.REQUIRES_NEW)

어노테이션으로 트랜잭션으로 설정하는 방법은 직관적이고 알기 쉽지만 수정이 필요할 때에는 코드 자체를 수정해야 한다는 단점이 있습니다. 위의 예시처럼 어노테이션도 <tx:method>와 같이 똑같은 옵션설정이 가능합니다. 설정방법은 이클립스의 자동완성기능(CTRL + F1)으로 알아보시면 편리하니 따로 설명하지는 않겠습니다 :D

일단 어노테이션으로 트랜잭션을 설정할 시 주의할 점은 가장 우선적으로 고려되는 순서가 있다는 것입니다. 만약 인터페이스 - 클래스 - 메서드 모두에 트랜잭션 어노테이션이 설정되있다면 스프링은 메서드 어노테이션을 제일 먼저 고려하고 그 다음이 클래스, 인터페이스 순서으로 적용합니다. 개인적으로는 가급적 어드바이스를 활용해 트랜잭션 경계를 설정하는 게 좋다고 생각하는데 어노테이션 트랜잭션을 남발할 경우 작성된 프레임워크의 잦은 수정이 불가피해지기 때문입니다.

트랜잭션도 상황에 따라 자주 설정이 변경되어줘야 하는데 어노테이션으로 설정을 고정해버리고 매번 수정이 필요할 때마다 소스자체를 바꾸다보면 다른 코드에 영향을 줄 수도 있고 이용하는 사람 입장에서도 상당히 불편할 수 있습니다. 가급적 어드바이스로 트랜잭션 경계를 설정하고 정말 불변하는 트랜잭션에 대해서만 어노테이션을 이용하길 권장합니다.


이제 마지막으로 트랜잭션 매니저 설정을 위한 PlatformTransactionManager을 설명하고 끝마치려 합니다 ^^. 스프링은 다양한 플랫폼과 환경에서도 완벽하게 트랜잭션 클래스들의 DI가 가능 하도록 PlatformTransactionManager 인터페이스를 갖고 있다는 사실을 알고 계신가요?

우리가 구현했던 소스에서는 볼 수 없었지만 분명 <tx:advice>를 구성하는 소스에는 PlatformTransactionManager 인터페이스를 통해 구현 클래스의 주입을 요구하고 있습니다. 현재의 소스는 제가 JDBC/MyBatis를 이용하고 있으므로 위의 예제와 같이 DataSrouceTransactionManager 클래스를 이용해 트랜잭션 매니저를 구현했지만 만약 하이버네트나 JTA같은 다른 플랫폼을 이용할 경우에도 소스에 변경 일절 없이 오로지 트랜잭션 매니저만 변경해주면 간편하게 모든 설정을 끝마칠 수 있습니다.

이렇게 트랜잭션에 대한 모든 설명이 끝났네요. 사실 부족한 부분이 많지만 이정도면 스프링에서 어떻게 트랜잭션을 설정하였고 활용방안에 대한 감을 잡을 수 있다는 생각이 듭니다. 부족한 부분이나 이해가 안가시는 부분은 피드백 주시구요. 다음에 좀 더 좋은 포스트로 찾아올게요 ^^
.
:
Posted by .07274.
2013. 7. 30. 14:36

PMD Rule Set 정리 [펌] I.lib()/I.lib(etc)2013. 7. 30. 14:36

.. .. ..
[펌] : http://blog.benelog.net/2702876

Rule Set Rule name Message 분류 의견 설명, 의견 사유 참고자료
Basic Rules EmptryInitializer
Warning 제외요망 PMD 5.0에서 추가될 룰로 Maven plugin에서는 지원되지 않음
Braces Rules IfStmtsMustUseBraces Avoid using if statements without curly braces Warning 논의필요 if문뒤의 한줄짜리 처리문도 {}가 없으면 경고를 줌. 가독성을 높여주므로 포함시키는 것이 바람직.
Code Size Rules TooManyMethods This class has too many methods, consider refactoring it. Warning 논의필요 한 클래스에 지나치게 많은 메소드가 포함되면 나는 경고. 적당한 클래스 크기를 정하는데 도움을 주나, 정말 논리적 연관성이 있는 작업을 많이 담고 있는 클래스도 존재할 수 있으므로 적정 숫자에 대해서는 논의 필요함
Controversial Rules OnlyOneReturnRule A method should have only one exit point, and that should be the last statement in the method Warning 제외요망 메서드 중간의 return문은 복잡한 조건문의 구조를 단순하게 하는데 도움이 경우가 많고, 권장하는 사례도 있음. 켄트백의 구현패턴 - 7장 중 '보호절'
Controversial Rules DataflowAnomalyAnalysis Found 'DD'-anomaly for variable ... Info 제외요망 전체 데이터의 흐름을 분석해서 return값과 상관없는 변수에 값을 쓴다든지 하는 상식적이지 않은 경우를 잡아내줌. 캐쉬나 interceptor등 그런 흐름이 꼭 필요한 코드도 경고해줘서 지나치게 많은 경고를 생성함
Controversial Rules Unused Modifer Avoid modifiers which are implied by the context Warning 논의필요 interface는 당연히 모든 method가 public이니 따로 선언해줄 필요가 없는 현상등을 주의를 줌. 개발자에 따라서는 public이 있는 것이 더 명시적이라고 생각할 수도 있고, 이미 모든 인터페이스가 public으로 다 선언되어 있는 상황에서는 개발자들에게는 무의미한 수정으로 인식될 위험도 있음.
Design Rules UnnecessaryLocalBeforeReturn Consider simply returning the value vs storing it in local variable …. Warning 제외요망 return 전에 따로 local 변수로 반환할 값을 선언할 때 주는 경고. 기능적으로는 별 의미 없는 코드이나, return 문장에는 @SupressWarning 의 Annotation을 추가할 수 없기 때문에, Annotation 적용 범위를 최소화하기 위해 그런 선언이 필요한 때도 있음. Debug Mode에서도 값의 추적에 약간의 편리성이 생길 수 있음. Java Language Spec 9.7, Effective Java 2ed - Item 24
Design Rules UncommentedEmptyConstructor Document empty constructor Warning 제외요망 빈 생성자에 comment가 없어도 코드의 이해에 무리가 없는 경우가 많음
Design Rules UncommentedEmptyMethod Document empty method Warning 제외요망 Listener류의 인터페이스의 구현에는 특정 메소드는 아무 일도 하지 않는 메소드로 남겨놓을 때도 있고, 종종 발생하는 상황임. 그리고 그 상황에 주석이 없다고 해도, 코드 이해에 무리가 없음
Design Rules ImmutableField Private field '...' could be made final; it is only initialized in the declaration or constructor.
EmptyInitializer
Warning 제외요망 멤버변수 중 선언되어서 한번만 값이 대입된 변수는 final로 할 수 있다고 알려주는 경고. 개발자가 Final로 의도하지 않지만, 현재 기능에서는 한번만 대입하고 있는 상황도 존재할 수 있다고 생각됨.
Jakarta Commons Logging Rules ProperLog Logger should be defined private static final and have the correct class
논의필요 private static final Log log = LogFactory.getLog(해당클래스) 로 로거를 선언할 것을 알려줌. 대체로 무난히 적용가능하나, 프로젝트의 로그 정책이 특별한 경우도 있으므로 논의해볼만 함
Java Bean Rules BeanMemberShouldSerialize Found non-transient, non-static member. Please mark as transient or provide accessors. Warning 제외요망 Java Bean의 명세를 검사하는 규칙. 일반적인 클래스는 transient하지 않으면서도 acessor가 없는 멥버 변수가 올 수 있는 경우가 많음. 스프링에서 선언하는 bean들은 setter만 가지는 경우가 많으므로 대부분 이 규칙에 어긋나게 됨. (스프링에서 bean은 java bean명세보다 보다 넓은 bean을 의미하는 것으로 생각하면 됨)
Java Loggins Rules Systemprintln System.out.print is used Error 논의필요 웹Application에서는 반드시 피해야할 코드라서 출시시에는 꼭 걸러내야하나, 분류가 Error가 되어 있는 것에 대한 논의는 필요함. 그리고 Console에서 도는 간단한 프로그램이나 테스트코드에서는 System.out이 들어가는 것이 결함이 아니므로 폴더 범위나 네이밍룰을 추가한 보다 정교한 Rule지정하는 것이 바람직함(예를 들어 Controller, Service, DAO안에는 System.out불가)
Junit Rules JunitAssertionsShouldIncludeMessage JUnit assertions should include a message Warning 제외요망 테스트 결과를 확인할 때, 메시지가 포함된 것이 바람직하나, 테스트 코드 작성을 장려하기 위해 테스트 코드에 대한 제약은 줄이는 것이 좋을 것으로 판단됨
Junit Rules JunitTestsShouldIncludeAssert JUnit tests should include assert() or fail() Warning 제외요망 assert나 fail이 있는 테스트코드가 의미가 있으나, 그렇지 않은 코드도 없는 것 보다는 나으므로, 테스트 코드 작성을 장려하기 위해 관대한 정책을 권장함
Migration Rules Junit4TestShouldUseTestAnnotation JUnit 4 tests that execute tests should use the @Test annotation Warning 제외요망 Junit3.8로 기준으로 작성된 코드에서 Junit4의 요건을 요구하면서 warning을 냄.
Naming Rules LongVariable Avoid excessively long variable names like … Warning 제외요망 표현력이 높은 변수이름을 짓는 것을 권장하기 위해서 길이제한을 두는 것은 바람직하지 않음
Naming Rules ShortVariable Avoid variables with short names like… Warning 논의필요 "is","os"등의 2글자 변수명일 때 나는 경고. 실제로 2글자만으로도 문맥상으로 충분한 표현력을 가지는 상황도 있고, 한 메소드가 크게 길어지지만 않는다면 local variable의 경우에는 다소 관대한 정책을 넣는 것도 무리는 없음
Optimization Rules AvoidInstantiatingObjectsInLoops Avoid instantiating new objects inside loops Warning 제외요망 Loop안에서 new keyword가 존재하면 나는 경고임. 피할 수 있는 경우라면 피해야 겠지만, GC시점이 약간이나마 늦어질 수 있고, collection.clear같은 청소 매서드 호출이 필요해진다거나, Thread safe해지지 않는 경우 등 손해가 있는 상황이 있으므로, 항상 지켜야할 지침이라고는 보기 어려움
Optimization Rules LocalVariableCouldBeFinal Local variable '...' could be declared final Warning 제외요망 local 변수 중 final이 될 수 있는 것을 알려주는 정보. Final이 되면 경고를 주는 이와 상반된 룰도 존재함
Optimization Rules MethodArgumentCouldBeFinal Parameter '...' is not assigned and could be declared final Warning 논의필요 방어적 프로그래밍을 위해서 파라미터는 final로 선언하는 것이 바람직하나, 모든 메서드를 그렇게 하면 메소드 시그니처가 전부 다 길어지기 단점이 있음. 기술인프라성 공통코드에만 적용하는 방안이 바람직하다고 생각함
Strict Exception Rules SignatureDeclareThrowsException A method/constructor shouldn't explicitly throw java.lang.Exception Warning 논의필요 메소드나 생성자가 throws Exception으로 최상위 Exception을 던질때 주는 경고. Checked Exception의 남발을 막고, 정교한 Exception선언을 돕는다는 장점도 있어서 되도록 권장하고 싶지만, 기존 코드의 Exception 선언이 throws Exception이 남용되어 있을 때 등 프로젝트 후반기에는 적용이 어려움
String and StringBuffer AvoidDpolicateLiterals The String literal " rows, page " appears 4 times in this file; the first occurrence is on line 70 Warning 논의필요 중복 되는 문자열 상수가 많은 경우에 나타남. 내부적으로는 java의 상수풀을 사용하게 되므로 성능에는 영향은 없음. 반복되는 문자열도 따로 상수선언을 하게 하는, 좋은 코딩습관에 도움이 되나 ,테스트 클래스 등의 안내 메시지 등의 그리 중요하지 않은 부분에서 지나친 상수선언을 하게 할 수 있음.

'I.lib() > I.lib(etc)' 카테고리의 다른 글

에디트 플러스 (Edit Plus) 칸단위 선택  (1) 2013.08.14
부산 여행 Tip  (0) 2013.08.09
겔럭시 s 부두 패치 경로  (0) 2013.04.19
[펌] TDD  (0) 2013.03.28
캐리커쳐 그리기 쉬운 사이트  (0) 2012.10.25
.
:
Posted by .07274.
.. .. ..

SocketChannel 의 설정을 알아보던중에 아래와 같은 설정을 확인했다.

 

SocketChannel.socket().setTcpNoDelay(true);

 

무엇을 하는 설정인지 알아보다 귀찮음에 뒤로 미루어 두었다가 다시 한번 알아보고 정리한다.

 

JavaDoc 을 살펴보면 아래와 같이 설명이 되어있다.

 

" Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm). "

 

한글로 풀어보니 대충

 

" TCP_NoDelay 기능을 사용/비사용 (Nagle`s 알고리즘을 On/OFF) "

 

하는 기능으로 조심스래 유추된다.

 

그래서 Nagle`s  알고리즘이 무엇인지 찾아보니 아래와 같은 뜻임을 알수 있었다.

 

Nagle알고리즘? 네트워크 상에 패킷의 수를 줄이기 위해 개발된 알고리즘

 

1. 일반 네트워크 통신방법

- 일반적인 통신알고리즘은 데이터는 패킷으로 만들어 보낸다는 것이며 수신호스트는 이에 대한 ACK를 보낸다는 것입니다. 예를 들어, A,B 두 호스트가 통신을 합니다. A B에게 'Nagle'라는 데이터를 보내기 원하면, 먼저 'N'이라는 데이터를 패킷으로 만들어 출력버퍼로 보냅니다. 그리고 ACK를 받고 안받고 관계없이 'a'를 패킷으로 만들어 보내고 이어서 'g', 'l', 'e' 각 데이터를 패킷으로 만들어 보낼 것입니다. 수신호스트로부터의 ACK가 언제 오는가는 전혀 관계가 없고언제 오든지 오기만 하면 되는 것입니다.

 

2. Nagle 알고리즘

- 네트웍에서 Nagle 알고리즘은 "가능하면 조금씩 여러 번 보내지 말고 한번에 많이 보내라(Effective TCP)" 라는 원칙을 기반으로 만들어진 알고리즘입니다.

- Nagle 알고리즘의 원리는 ACK를 받은 다음에 데이터를 보내고 ACK를 받을 때까지 출력버퍼의 데이터를 저장하였다가 ACK를 받으면 버퍼의 데이터를 모두 패킷으로 만들어 보낸다는 것입니다. 예를 들어 A 'N'이라는 데이터를 패킷으로 만들어 보내고, 계속해서 다음 데이터를 보내는 것이 아니라 출력버퍼로 보내어 저장시켜 둡니다. 그러다가 ACK가 오면 출력버퍼에 저장된 'agle'라는 데이터를 보냅니다.


- TCP 소켓은 Default Nagle 알고리즘을 적용하고 있습니다.

 

3. Nagle 알고리즘의 장단점

  - 장점네트워크의 효율성이 높아짐. (똑같은 데이터를 보내더라도 생산하는 패킷이 적음)

  - 단점 : 송신 호스트가 ACK를 받을 때까지 기다려야 하므로 전송 속도가 느려짐

 

4. Nagle 알고리즘의 중단

- 몇몇 네트웍 관련 프로그램에서는 네트웍의 전송량이나 부하보다는 빠른 응답속도를 더 중요시 여기는 상황이 있습니다. 그러한 때에는 TCP_NODELAY  라는 옵션을 사용하여 Nagle 알고리즘을 제거 할 수 있습니다.

 

- TCP_NODELAY 옵션이

     1(TRUE) : Nagle 알고리즘을 적용하지 않습니다.

     2(FALSE): Nagle 알고리즘을 적용합니다.

 

int opt_val = TRUE;

setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &opt_val, sizeof(opt_val));

 

해당 옵션의 사용은 네트웍 부하를 극대화 시켜주면서 서버의 전체적인 성능을 무척 감소하기때문에 꼭 필요한 경우에만 매우 주의를 해서 사용해야 합니다.

- 전송은 작은 단위로 자주 이루어지지만 즉각적인 응답은 필요 없는 어플리케이션에서만 사용 되어야 합니다.(마우스 움직임 같은)

 

- Nagle 알고리즘은 리얼타임시스템에서의 제어와 특히나 인터렉티브한 키 입력을 하는 어플리케이션에서는 안 좋은 영향을 미칩니다. 선택적으로 Nagle 알고리즘을 통과하는 한가지 방법은 Out-of-bind 메시지 시스템을 쓰는 것입니다. 그러나 이것은 내용물에 제약이 있고 또 다른 문제(순서의 상실: loss of sequentiality)를 일으킬 수 있습니다.

 

 

위 글을 읽어보고 유추되는 setTcpNoDelay 라는 기능은 아래와 같이 정리할수 있다.

 

SocketChannel.socket().setTcpNoDelay(true);

  -- Tcp에 딜레이가 없도록(NoDelay) 하겠다.

      (즉 Nagle 알고리즘을 적용하면 Tcp에 Delay 가 있으수 있으니 Nagle 알고리즘을 적용하지 않겠다.)

 

SocketChannel.socket().setTcpNoDelay(false);

  -- 위와 반대의 개념.

 

일단 위와같이 정리가 된다.

 

보고 도움이 되셨으면 댓글하나 달아주고 가시면 안잡아 먹습니다.

 

ps : 알아보고 설명해달랬더니 모르겠다고 하고 프로젝트를 나가버린 이X영씨는 이글보면 술한잔 사라~!

 

 

'I.lib() > I.lib(Java)' 카테고리의 다른 글

JVM에서 Pid 를 이용하여 Process 정보 읽기 (Attach api)  (0) 2014.01.02
J2EE 란?  (0) 2013.10.30
Network 통신중 TIME_WAIT 관련 정보 정리  (0) 2013.06.17
Deque (덱) 요약  (0) 2013.06.05
[펌] ByteBuffer 설명 정리  (0) 2013.04.23
.
:
Posted by .07274.
.. .. ..

[펌] : http://kldp.org/node/165

 댓글들을 정리하였습니다.

 

 

첫번째 정리

 

예전에 제가 TIME_WAIT 상태에 대해 정리했던 글입니다. 한번 읽어보시길 바랍니다.
Unix나 Linux 상에서 네트워크 프로그래밍을 하실때는 W.Richard Stevens가 저술한 Unix Network Programming을 참고하시면
많은 도움이 됩니다.(유닉스 네트워크 프로그래밍 서적의 바이블이죠.)

Quote:
TCP는 여러개의 State를 가질수 있습니다. 예를들어 CLOSED(연결이 닫혔을때) LISTEN(연결을 기다리고 있을때), ESTABLISHED(연결이 되었을때) 등등의 상태를 가질수 있습니다. 이중에서 TIME_WAIT라는 상태가 있는데, 이해하기 가장 어려운 부분인것 같습니다. TIME_WAIT 상태는 다음과 같은 경우에 발생합니다. 우선 Client와 Server가 TCP로 연결이 되어 있다고 가정합시다. 이때 클라이언트가 연결을 끊으려면 close함수를 호출합니다. 이 함수를 호출하면 서버에 FIN segment를 보내게 됩니다. 그러면 서버는 이 메시지를 받고 클라이언트가 접속을 끊으려고 하는 것을 알게됩니다. 따라서 서버가 CLOSE_WAIT 상태가 되면서 클라이언트에게 ack segment를 보냅니다. 즉 "네가 접속을 끊는 다는 신호를 받았다" 이런 의미입니다. 이 메시지를 받으면 클라이언트는 FIN_WAIT_2 상태가 됩니다. 이 상태에서 서버는 자신의 socket을 close하고 다시 클라이언트에게 FIN segment를 보냅니다. 즉 자신도 연결을 닫았다는 신호를 클라이언트에게 보내는 것입니다. 이 메시지를 받으면 클라이언트는 ack segment를 보내면서 TIME_WAIT 상태가 됩니다. 즉 서로간의 확인하에 완전히 연결이 끊기게 됩니다. 근데 이 상태에서 곧바로 CLOSED 상태가 되는 것이 아니라 2 MSL(maximum segment lifetime - 1분~4분) 동안 TIME_WAIT상태를 유지합니다. 왜 곧바로 CLOSED 상태가 되지 않고 일정시간 동안 TIME_WAIT 상태가 되는 것일까요?

뭔가 이상하지 않습니까? 그 이유는 다음과 같습니다. TCP는 신뢰성을 보장해 주는 프로토클 입니다.(UDP는 아니지요.) 따라서 연결시에도 신뢰성을 보장하기 위하여 Three-way handshake라는 기법을 사용하여 연결을 하고 종료시에도 위와같이 복잡한 과정을 거쳐 서로가 close된것을 확인하게 되는 것입니다. TIME_WAIT 상태도 이와같은 신뢰성 보장을 위한 한가지 방법이라고 보시면 됩니다.

Unix Network Programming에 보면 TIME_WAIT 상태가 있는 이유에 대해 다음과 같이 설명하였습니다.

1. to implement TCP's full-duplex connection termination reliably, and
2. to allow old duplicate segments to expire in the network.

흠 첫번째는 신뢰성있는 연결 종료를 위한 것이라고 쓰여있습니다. 근데 두번째는 무엇일까요?
network에 있는 duplicate segments들이 소멸시키기 위해서?? 무슨 소리인지 -_-;;
이 두가지에 대하여 자세히 설명해 보겠습니다.

 

먼저 첫번째에 대해서 설명하겠습니다.
이것은 말그대로 신뢰성있은 연결 종료를 위한것입니다. 다음과 같은 상황을 가정합시다. 클라이언트가 FIN_WAIT_2 상태에서 서버의 FIN segment를 받으면 TIME_WAIT상태가 되면서 서버에 ack segment를 보낸다고 하였습니다. 하지만 이 ack segment가 네트워 크의 오류로 인해 서버에 도착하지 못할수도 있습니다. 그런 경우라면 서버에서는 일정시간 이후에 다시 클라이언트에게 FIN segment를 보냅니다. 자신이 응답을 못받았으니 다시 보내달라는 의미지요. 만약 클라이언트가 CLOSED 상태 즉 연결이 닫혀 있는 상태에서 서버가 다시 보낸 이 FIN segment를 받으면 어떻게 될까요? 그런 경우라면 ack대신 RST라는 segment를 보내게됩니다. 즉 CLOSED 되면서 이전에 서버와 연결했던 정보들이 전부 없어졌으므로 서버가 다시 요청을 하면 "나는 너를 모른다. 왜 이상한 메시지를 보내느냐?" 하면서 서버가 원하는 ack 대신 RST라는 segment를 보내게 되는 것입니다. 이런 상황을 방지하기 위하여 일정시간 동안 TIME_WAIT라는 상태를 유지하여 서버가 다시 FIN을 보냈을때 대답할수 있게 해줍니다.

 

두번째에 대한 설명입니다.
다음과 같은 상황을 가정해 봅시다.
우선 현재 111.111.111.111:23 번하고 111.111.111.112:1500번이 연결되어 있다고 합시다.둘이 막 패킷을 주고 받다가 둘이 연결을 정상적으로 끊었다고 가정합시다. 그 후에 둘이 곧바로 연결을 해서 방금전과 마찬가지로 111.111.111.111:23 과 111.111.111.112:1500으로 연결되었다고 합시다. 근데 여기서 문제가 발생하였습니다. 바로 이전에 연결이 성립되었을때 111번에서 112번으로 보낸 패킷하나가 라우터의 오류로 인터넷을 뺑뺑이 돌다가 이전 연결이 끊어지고 지금 새로운 연결이 되었을때 112번에 도착했습니다. 무슨 소리냐구요? 예를 들어 라우터 A와 B가 있습니다. 근데 라우터의 일시적인 오류로 라우터 A의 데이타가 B로 전송하면 B가 다시 A로 그 데이타를 전송하여 순간적인 루프에 빠질수가 있을 수도 있습니다. 이렇게 루프에 빠지던 놈이 이전 연결이 끝나고 새로운 연결이 생겼을 때 도착한다면 문제가 발생하겠죠? 즉 원하지 않는 데이타가 전송되었으니 오류가 발생할 수 도 있는 것입니다. 이것을 방지하기 위하여 TIME_WAIT 상태를 둡니다. TIME_WAIT상태에 있는 동안은 같은 연결이 발생하지 못하도록 방지합니다. 즉 이전에 내가 연결되었던 포트가 1500번이라면 다음 연결은 현재 1500번이 TIME_WAIT이므로 1501번으로 연결되게 됩니다. 그렇게 하면 위와같은 문제를 해결할 수 있습니다. 보통 TIME_WAIT상태는 2 MSL입니다. 즉 인터넷 상에서 패킷이 존재하는 시간보다 길게 설정됩니다. 그러므로 TIME_WAIT상태가 끊나면 인터넷 상에서는 이전 연결에 보내졌던 패킷이 모두 소멸되었다고 확신할 수 있으므로 새로운 연결을 만들어도 문제가 발생하지 않는것입니다..

Dream, Passion and Challenge..

 

 

두번째 정리

네트워크 프로그래밍을 하다보면 반드시, 이 문제(TIME_WAIT)를 안 겪고 넘어갈래야 안 겪고
넘어갈 수가 없습니다. 만약, 겪어보지 못했다면 공부를 다시하고 이 분야에서 충분한 경력도
없으신 분일 겁니다.. 이 TIME_WAIT 가 발생하는 문제는 심각한 문제입니다. 왜? 그러느냐?
엄청나게 빠른속도로 접속하고 엄청나게 빠른 속도로 종료되는 시스템에서는 이 TIME_WAIT 문제는
심각한 상태를 만들어냅니다.. 자원고갈되는 사태를 벌어지게 만듭니다. 위에 최초 질문자가
구현한 프로그램은 while 로 도는 무한정의 접속 및 종료의 클라이언트 연결을 만듭니다.
이런 프로그램은 포트 스캐너 같은 프로그램과 유사한 면이 있습니다. 저도 예전에 경험한 적이
있는데 수많은 접속과 종료가 순식간에 발생하면 서버 뿐만 아니라 클라이언트에서도 자원고갈이
발생합니다.. netstat 로 보게되면 TIME_WAIT 상태가 산더미 같이 쌓이게되죠.. 그럼 나중에
접속을 더이상 할 수가 없게됩니다.. 왜? 자원고갈 상태가 되어버립니다.. 소켓이 죄다 열려
있는 상태인데 사용할 포트는 65535 가 최대거든요? 이 문제가 서버에서도 발생합니다..
그래서, 클라이언트가 명확하게 접속을 끊는 경우와 서버가 명확하게 접속을 끊을 경우에는 반드시
TIME_WAIT 없이 깨끗한 상태로 끊어져야 합니다. 그래야 접속폭풍이 일어나는 기업의 상용서비스에
대응할 수 있게되는거죠.. 대기업 서버가 자원고갈이 발생해서야되겠습니까? 무식한 서버가 되는
거죠.. 그리고, 그런 문제는 자바에서는 이미 처리되고 있습니다.. 아~주 깔끔하게.. 그럼, 그게
어떻게 한거냐?

(정답)
- 서버에서 클라이언트를 명시적으로 끊었을때 TIME_WAIT 가 발생하지 않으려면..?
shutdown(sock, sd_both);
closesocket();
소켓을 닫기 전에 셧다운을 시켜야 한다. 그럼, TIME_WAIT 없이 깔끔하게 끊어진다.

- 클라이언트에서 명시적으로 끊어서 TIME_WAIT 가 발생하지 않으려면?
그건 위에 댓글 단 사람들이 이미 설명했다. SO_LINGER 써라..

-(요약)
서버에서 폭풍접속 종료에 깔끔하게 TIME_WAIT 없이 명시적 종료를 하려면 shutdown 을
쓰고, 클라이언트에서 폭풍접속 종료에 깔끔하게 TIME_WAIT 없이 명시적 종료를 하려면
SO_LINGER 에서 타임을 0 으로 바꿔라..
이렇게하는 이유는 어마어마한 속도로 접속과 종료를 반복해서 무한정 돌려야하는 클라이언트와
서버 프로그래밍에서 자원이 고갈되지 않도록(디스크립터 자원고갈 발생 방지) 하기 위함이다.
이걸 지키지 않으면 최초 접속자가 헤메는 그 증상이 나타난다. 즉, 서버와 클라이언트 양쪽
에서 이 규칙을 지켜야 합니다. 어느한쪽이 안지키면 그 안지킨 한쪽은 폭풍접속 및 종료에
있어서 결국에는 자원고갈되며 병신되는거죠..

 

 

어렵구나 네트워크는.. 에구..

 

'I.lib() > I.lib(Java)' 카테고리의 다른 글

J2EE 란?  (0) 2013.10.30
Socket 의 setTcpNoDelay 관련 정리. (Nagle 알고리즘 관련)  (4) 2013.06.17
Deque (덱) 요약  (0) 2013.06.05
[펌] ByteBuffer 설명 정리  (0) 2013.04.23
[펌] 제한자 정리  (0) 2013.04.18
.
:
Posted by .07274.
2013. 6. 5. 17:50

Deque (덱) 요약 I.lib()/I.lib(Java)2013. 6. 5. 17:50

.. .. ..

[출처] [자바][기본] Deque 데크, 디큐, 덱 ( double ended queue )|작성자 카루

 

큐 + 스택 의 기능을 가진 Deque에 대해 알아보자.

 

Deque는 인터페이스므로 구현된 다른 클래스를 사용해야 한다.

 

여러가지가 있지만 본 예제에서는 LinkedBlockingDeque 를 사용한다.

 

큐+스택 인 만큼 넣는 방법도 다양하고.

 

꺼내는 방법도 다양하다.

 

그러나 큐는 먼저 넣은게 먼저나온다.

스택은 먼저 넣은게 나중에 나온다.

 

그 두개가 혼합되어 사용될경우 

즉 큐로서 넣은 값이

 

스택방식으로 꺼내질경우

어떻게 될지에 대해 상상이 가는가.

 

큐로 넣은값이 앞으로 가는가 뒤로 가는가.

스택으로 꺼내는값은 뒤에서 꺼내는것인가 앞에서 꺼내는 것인가.

 

이번 실험으로 애매함을 해결해보자.

 

물론 이 실험으로도 어디가 앞인지 뒤인지 알수 없다.

 

다만 방향을 제시할수 있다. 즉 어떤 방법은 A로 가고 어떤방법은 B에서 꺼내고 라는등...

 

결국 이것을 앞 뒤라고 이해하면 편할 것이다.

 

 

일단 꺼내는 함수들에 대해 알아보자.

 

값을 제거하지 않는 것들

peek()        : 앞

peekLast()  : 뒤

peekFirst()  : 앞

getFirst()    :  앞

getLast()    :  뒤 

값을 제거하는 것들

poll()         :  앞

pollFirst()   :  앞

pollLast()   :  뒤 

pop()         :  앞

 

입력하는 함수들에 대해 알아보자.

 

offerFirst  :  앞

offerLast  :  뒤

offer        :  뒤  

addFirst   :  앞   

addLast   :  뒤

add         :  뒤

putFirst    :  앞  

putLast    :  뒤

put          :  뒤

push       :  앞 

 

정리하자면

 

출력은 Last가 붙지 않은건 전부 앞에서 꺼낸다.

 

입력이 엄청나게 괴랄 하다.

First, Last가 붙은것들은 해당 위치로 다 들어간다.

offer, add, put은 뒤에 넣는다.

push는 앞으로 넣는다.

 

참고로 앞으로 넣는다는 얘기는 먼저넣은게 점점 뒤로 밀려나간다는 얘기이며

뒤로 넣는다는 얘기는 뒤에 먼저 들어간 순서대로 서있는다는 이야기이다.

 

테스트 소스를 첨부함니다.

잘못된 부분이 있으면 댓글로 부탁드려요.

 

[펌] : http://cafe.naver.com/mymejong/378

 

DEQUES

 

Deque는 double-ended queues의 줄임말이다(디큐가 아니라 데크로 발음함). 큐는 한쪽 엔드에서 추가하고 다른 쪽 엔드에서 제거할 수 있는 반면, 양쪽 엔드에서 추가와 제거가 가능한 double-ended queues는 스택과 큐가 결합된 것처럼 작동한다. Deque 인터페이스는 J2SE 5.0에 도입된 Queue 인터페이스에서 확장되는데, 이 기능은 최근에 Java SE 6의 Java Collections Framework에 추가되었다(이 기능이 최종적으로 포함되려면 JCP의 승인을 받아야 함). 인터페이스 구현에는 LinkedList, ArrayDeque와 이에 수반되는 LinkedBlockingDeque가 포함된다.

LinkedList는 아마도 deque의 가장 전형적인 용례일 것이다. LinkedList는 제한 없이 확장이 가능하고 양쪽 엔드에서 신속하게 추가 및 제거 작업이 가능하다. ArrayDeque는 용량 제한이 없는 또 하나의 전형적인 구현으로, 성능을 최상으로 유지하기 위한 wraparound index 구현을 제공한다. 모든 베이스 컬렉션 구현이 그렇듯이, 어느 쪽도 threadsafe하지 않다. (VectorHashtable 같은 역사적인 컬렉션은 threadsafe하지만 고도의 동시발생적인 액세스를 위해 설계되지는 않았다.) 쓰레드 안전이 필요한 경우에는 LinkedBlockingDeque를 이용하면 되는데, LinkedBlockingDeque 클래스는 Deque에서 확장되는 새로운 BlockingDeque 인터페이스를 구현한다. 이 클래스는 사이즈가 제한되거나 제한되지 않을 수도 있다. 용량이 지정되지 않은 경우, 사이즈 제한은 Integer.MAX_VALUE이다.

다음 메소드 중 하나로 deque에 엘리먼트를 추가할 수 있다.

  • void addFirst(E e)
  • void addLast(E e)
  • boolean add(E e)

add() 메소드는 addLast()와 동등하다고 볼 수 있다. deque의 용량이 부족하면 IllegalStateException이 throw된다. 또한 다음 메소드 중 하나를 통해 추가될 엘리먼트를 제공할 수도 있다.

  • boolean offer(E e)
  • boolean offerFirst(E e),
  • boolean offerLast(E e)

addXXX() 메소드로 엘리먼트를 추가하는 경우와 달리, offerXXX() 메소드가 제공되었을 때 항목을 추가할 수 없으면 메소드는 false를 반환한다.

이 외에도 엘리먼트 제거를 위한 한 쌍의 메소드 세트가 있다.

  • remove(), removeFirst(), and removeLast()
  • poll(), pollFirst(), and pollLast()

deque가 비어있을 경우 removeXXX() 메소드는 NoSuchElementException를 throw하고, pollXXX() 메소드는 null을 반환한다. 또한, 아래의 메소드 중 한 가지를 사용하여 특정 개체를 제거할 수 있다(deque가 엔드에서의 추가/제거의 용도로만 의도된 경우라도).

  • boolean remove(Object o)
  • boolean removeFirstOccurrence(Object o)
  • boolean removeLastOccurrence(Object o),

Deque는 엘리먼트를 검사하기 위한 6개의 메소드를 가진다.

  • element()
  • getFirst()
  • getLast()
  • peek()
  • peekFirst()
  • peekLast()

element()는 오래된 Queue 인터페이스로부터 상속한 인터페이스 메소드이기 때문에 get() 메소드가 없다. get 메소드는 removeXXX()와 유사하며 deque가 비어있는 경우 NoSuchElementException을 throw하는데, 이와 대조적으로 peek 메소드는 비어있는 경우 null을 반환한다. 이는 물론 Deque가 null 값의 추가를 허용할 경우 deque의 엔드에 있는 null 항목과 ‘nobody on deck’ 간의 차이를 알 수 없다는 것을 의미한다. 그러나 이 경우에는 size() 메소드를 활용할 수 있다.

Deque는 개념상 이중으로 링크되므로, 어떤 순서로도 엘리먼트들을 traverse할 수 있다. 앞에서 뒤로 traverse하려면 iterator()를 이용하고 역순, 즉 뒤에서 앞으로 traverse하려면 descendingIterator()를 이용한다. 하지만 위치별로 엘리먼트에 액세스할 수는 없다?적어도 Deque 인터페이스로는 불가능하다. LinkedListDeque의 구현이지만 함께 구현되는 List 인터페이스를 통해 색인 액세스(indexed access)를 지원한다. 랜덤 액세스 요건이 없다면 Deque 구현이 더 효과적으로 이루어질 수 있다.

왜 deque를 사용하는 것일까? deque는 maze 또는 parsing 소스를 통한 검색과 같은 반복적인 문제에 특히 유용한 데이터 구조로서, path를 따라 이동하면서(path가 양호하다고 판단되는 한) "good" spot을 저장하고 계속해서 데이터를 추가할 수 있다. path가 bad를 반환할 경우에는 bad 비트를 pop off하여 마지막 good spot으로 복귀한다. 이 경우 스택과 같은 동일한 엔드에서 추가와 제거를 수행하게 된다. 일단 길을 찾으면 처음부터 다시 시작하여 반대쪽 엔드에 해당하는 솔루션을 밝혀낸다. 또 다른 전형적인 예로, 운영체제 스케줄러, 그리고 사람들을 속이기를 좋아하는 악질 카드 딜러 등을 들 수 있을 것이다.

다음 프로그램 BlockedDeque의 용례, 보다 구체적으로는 용량 제한이 있는 LinkedBlockingDeque를 보여주고 있다. 이는 물론 최상의 deque 용례는 아니지만 API와 용량 제한에 도달했을 때의 상황을 예시해준다. 프로그램은 23개의 달 이름(짧은 이름과 긴 이름 모두)을 취하여 이를 6-엘리먼트 블로킹 deque의 헤드에 한번에 하나씩 추가한다. 또 다른 스레드에서는, 현재 컬렉션 내에 있는 엘리먼트의 수를 토대로 엘리먼트를 deque의 헤드와 테일에서 제거한다.

   import java.io.*;
   import java.util.*;
   import java.util.concurrent.*;

   public class Blocked {
     public static void main(String args[]) {
       Calendar now = Calendar.getInstance();
       Locale locale = Locale.getDefault();
       final Console console = System.console();
       final Map<String, Integer> names = now.getDisplayNames(
           Calendar.MONTH, Calendar.ALL_STYLES, locale);
       console.printf("Starting names: %s%n", names);
       final Deque<String> deque = 
           new LinkedBlockingDeque<String>(6);
       // Add one at time to beginning of deque
       new Thread() {
         public void run() {
           Set<String> keys = names.keySet();
           Iterator<String> itor = keys.iterator();
           String element = null;
           while (itor.hasNext() || element != null) {
             if (element == null) {
               element = itor.next();
               console.printf("MapGot: %s%n",  element);
             }
             console.printf("Offering: %s%n", element);
             if (deque.offerFirst(element)) {
               console.printf("MapRemoving: %s%n", element);
               itor.remove();
               element = null;
             } else {
               try {
                 Thread.sleep(250);
               } catch (InterruptedException ignored) {
               }
             }
           }
           // Done. Give time to process rest.
           try {
             Thread.sleep(3500);
           } catch (InterruptedException ignored) {
           }
           System.exit(0);
         }
       }.start();
       while (true) {
         if ((deque.size() % 2 == 1)) {
           // remove head
           console.printf(
               "Remove head: %s%n", deque.pollFirst());
         } else {
           // remove tail
           console.printf(
               "Remove tail: %s%n", deque.pollLast());
         }
         // Sleep between loops
         try {
           Thread.sleep(500);
         } catch (InterruptedException ignored) {
         }
       }
     }
   }

아래에서 보듯이, 프로그램 실행 시 printf 선언문 때문에 많은 아웃풋이 생성된다. 엘리먼트를 소스 맵에서 가져오거나, 소스 맵에서 제거하거나, deque에 제공하거나, deque에서 제거할 때마다 아웃풋 행이 생성된다. deque가 full 상태일 때 어떻게 제공(offering) 동작이 복수로 발생하는지 유의할 것.

   >> java Blocked


   Starting names: {Jun=5, March=2, December=11, April=3, 
   November=10, September=8, October=9, Sep=8, Aug=7, Apr=3, 
   May=4, June=5, Feb=1, Dec=11, Oct=9, Jan=0, Mar=2, Jul=6, 
   August=7, January=0, February=1, July=6, Nov=10}
   Remove tail: null
   MapGot: Jun
   Offering: Jun
   MapRemoving: Jun
   MapGot: March
   Offering: March
   MapRemoving: March
   ...

   Remove tail: Jul
   Remove head: Nov
   Remove tail: August
   Remove head: July
   Remove tail: January
   Remove head: February
   Remove tail: null

여기서 두 가지 사실에 주목할 필요가 있다. 첫째, 24개가 아닌 23개의 짧고 긴 달 이름이 있다(5월인 "May"의 경우에는 짧은 이름과 긴 이름 모두에 해당하기 때문에 23개가 된다). getDisplayNames() 메소드는 Map을 반환하므로 "May"는 짧은 이름과 긴 이름 등 2개 엔트리에 대한 key가 될 수 없다. 둘째는, 한쪽 엔드에서 추가하고 다른 쪽 엔드에서 제거하는 것이 작업의 전부라면 Deque 대신 컬렉션 프레임워크에서 Queue 구현을 이용하는 편이 더 나을 것이라는 점이다.

최소한, STL(Standard Template Library)에서의 유용한 deque/vector 비교 자료를 보려면 An In-Depth Study of the STLDeque Container를 참조할 것(여기서는 두 컨테이너 타입의 성능 차이에 대해 다루고 있음). 자바 플랫폼 상의 실제 수에는 차이가 있지만 전반적인 개념은 나름대로 정확하다고 볼 수 있다.

 

 

.
:
Posted by .07274.