2013년 6월 20일 목요일

Software caused connection abort: recv failed 오류에 대한 고찰


디비 이전 관련해서 발생한 이슈에 대한 해결 방안


원인을 파악하기 위해 조사를 하다가 발견한 사항입니다.

특정 DB 오라클 뿐만이 아니라 대부분의 DBMS의 경우 DB측에서 클라이언트로부터 정기적인 요청이 없는 경우(장시간 요청이 없는 경우)
클라이언트로부터 요청 받았던 DB connection closed한다고 합니다.
java.net.SocketException: Software caused connection abort: recv failed
java.net.SocketException: Connection reset by peer: socket write error
위의 오류의 경우 클라이언트가 DBMS에서 접근하면서 오류가 발생한 것인데 클라이언트가 DBMS와 맺었던 connection을 찾지 못해 발생한 것으로 판단됩니다.

원인 조사와 동시에 해결책에 대하여 찾아보았고
본 시스템의 경우에는 아파치 common 라이브러리 중 org.apache.commons.dbcp.BasicDataSource 라이브러리를 사용 중입니다.
위의 원인으로 발생하는 것이 정확하다면 클라이언트에서 DBMS로 커넥션을 연결 맺고 시간이 지난 후 데이터를 요청하려 할 때 맺었던 connection에 대한
Check를 하는 방법이 있을까? 하는 의문이 들어 해당 라이브러리에 대하여 조사를 진행하였습니다.

관련 라이브러리 옵션 중에 validationQuery 속성이 제가 원하는 기능을 할 수 있을 것이라 판단되어
WAS config에 설정을 하고 테스트를 하였습니다.

테스트는 운영서버 1대를 빼서 validationQuery 속성을 추가하지 않은 상태로 두고 저희 로컬PC에는 validationQuery 속성을 추가하고
동일한 페이지를 일정 시간을 두고 접속을 해보는 것으로 진행하였습니다.

그 결과 운영서버 쪽은 오류가 발생하였지만 로컬PC 쪽에서는 정상적으로 접속되는 것을 확인하였습니다.

validationQuery 속성이 하는 일은 기존 맺었던 connection에 대하여 유효성을 판단하는 기능인데 단순히 “select 1 from dual” 쿼리를 이용하여 확인을 합니다 ^^
클라이언트에서 서비스 쿼리를 DBMS에 날리기 전에 먼저 실행하는 것이고 오류가 발생할 경우 다시 connection을 맺는 것으로 판단됩니다.

추가적으로 재미있는 것은 만일 위와 같은 사항이 상용에서는 일어날까?
제 판단으로는 상용에서는 일어나지 않을 것 같습니다. 이유는 본 서비스는 장시간 DBMS에 데이터를 요청하지 않는 경우가 없기 때문입니다.
하지만 돌다리도 두르려 본다는 심정으로 DB connection 관련 속성 중에 validationQuery와 같은 옵션을 통해 보다 안정적인 DB Connection을 보장해 줄 수 있지 않을까 생각합니다.

Oracle에서의 Software caused connection abort: recv failed 오류가 발생했을 때

오라클 서버 이전을 하게 되었다.
물리적 장비를 사용하다가 이번에 가상화 장비로 이전을 하게 되었고 데이터를 이전 한 후
기존 웹 서비스에 물려 테스트를 하게 되었다.

헌데 그전에는 발견하지 못했던 오류가 발생했다.

Software caused connection abort: recv failed

위의 오류는 웹 서버를 구동한 후 서비스가 활성화 되고 서비스에서 디비 서버 측에 데이터 요청을 하지 않으면 디비 서버에서 커넥션을 close해서 발생하는 문제 였다.

내가 관리하는 웹 서비스는 spring3 framework를 사용하고 있다.
디비에 접속하는 DataSource는 org.apache.commons.dbcp.BasicDataSource를 사용 중이다.

org.apache.commons.dbcp.BasicDataSource 라이브러리에서 위의 오류를 발생하지 않도록 하는 방법이 있을 것 같아 찾아 보았다.

오라클의 경우에는 BasicDataSource 내에 validationQuery 속성이 있고
이 속성은 DB를 연결하기 전에 해당 Connection이 정상적인지 유효성 판단을 한다.

사용 방법은 아래와 같다

<bean id="transactionCPSDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName"><value>${txcps.jdbc.driver}</value></property>
        <property name="url"><value>${txcps.jdbc.url}</value></property>
        <property name="username"><value>${txcps.jdbc.username}</value></property>
        <property name="password"><value>${txcps.jdbc.password}</value></property>
        <property name="defaultAutoCommit"><value>${txcps.jdbc.commit}</value></property>
        <property name="maxActive"><value>${txcps.jdbc.active}</value></property>
        <property name="maxIdle"><value>${txcps.jdbc.idle}</value></property>
        <property name="validationQuery" value="select 1 from dual"></property>
    </bean>

위의 붉은 색 글씨 부분 처럼 넣어주면 된다.

끝!! 머리 아팠는데 우하하

2013년 4월 21일 일요일

Oracle에서 like와 substr 중 어느 것이 빠를까?

업무 중에 메뉴코드를 만들며 설계를 하다가 메뉴코드 조합 상 어쩔 수 없이

LIKE 나 Substr을 사용하게 되었다.

비슷한 기능을 하는 것으로 알고 있는 위의 방식 중 어느 것이 더 빠를까?

여기저기 찾아본 결과 LIKE가 빠르다고 한다.

물론 LIKE 'searce%' 이 형식이 빠르다는 것이다.

근데!! 여기서 Substr로 빠르게 할 수 있는 방법은 없을까? 고민하다가 이런 생각을 했다

ORACLE의 FBI를 사용하면?

그렇다! FBI(Founction Based Index)를 이용하면 속도(Cost)가 빨라진 다는 것을 찾았다!

그럼 어떻게 쓰는 걸까?


CREATE INDEX jini_substr_idx
    ON JINI_TABLE( substr( field,1,6 ) );


위와 같이 인덱스를 생성하면 되고 아래와 같이 사용하면 된다.


SELECT ... FROM ... WHERE substr(field,1,6) = 'search';


끝!

2013년 4월 4일 목요일

Spring3를 이용하여 RESTFul web service 생성하기 - XML, ATOM

Restful 웹 서비스 Build

이전 시간에는 JSON 타입으로  변환하는 것을 공부했다.
이번 시간은 XML과 ATOM 타입으로 변환하는 것을 공부하려고 한다.

XML

Spring3의 내장 변환기인 MarshallingHttpMessageConverter는 Object와 XML 사이에 매핑하는데 사용한다.

==> MarshallingHttpMessageConverter 구성

--------------------------------------------------<bean id="marshallingConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
    <constructor-arg ref="jaxbMarshaller" />
    <property name="supportedMediaTypes" value="application/xml"/>
</bean>

<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
    <property name="classesToBeBound">
         <list>
              <value>jini.web.study.bean.User</value>
              <value>jini.web.study.bean.UserList</value>
         </list>
    </property>
</bean>
--------------------------------------------------

앞서 공부한 소스 내용 중 @RequestBody Annotation 속성에서 headers="Accept=application/json, application/xml 을 추가만 하면된다.

ATOM Feed

==> AtomFeedHttpMessageConverter 구성

--------------------------------------------------
<bean id="atomConverter" class="org.springframework.http.converter.feed.AtomFeedHttpMessageConverter">
    <property name="supportedMediaTypes" value="application/atom+xml" />
</bean>
--------------------------------------------------


==> TestController에서 정의된  ATOM Feed 요청 처리

--------------------------------------------------
@RequestMapping(method=RequestMethod.GET, value="/users"headers="Accept=application/atom+xml")

public @ResponseBody Feed getUsersFeed() {    
    List<User> users = userDao.getAll();   
    return AtomUtil.employeeFeed(users, jaxb2Mashaller);



public static Feed userFeed(
List<User> users, Jaxb2Marshaller marshaller) {

    Feed feed = new Feed();

    feed.setFeedType("atom_1.0");

    feed.setTitle("Employee Atom Feed");

                       

    List<Entry> entries = new ArrayList<Entry>();
    for(User e : users) {
        StreamResult result = new StreamResult(new ByteArrayOutputStream());
        marshaller.marshal(e, result);
        String xml = result.getOutputStream().toString();
                                    
        Entry entry = new Entry();
        entry.setId(Long.valueOf(e.getId()).toString());
        entry.setTitle(e.getName());
        Content content = new Content();
        content.setType(Content.XML);
        content.setValue(xml);
           
        List<Content> contents = new ArrayList<Content>();
        contents.add(content);
        entry.setContents(contents);
        entries.add(entry);
    }

    feed.setEntries(entries);
    return feed;
}
--------------------------------------------------
  • getUserFeed() method는 앞선 JSON 코드에서의 getAllUsers()와 동일한 URI로 매핑되지만, header에서 Accept 항목이 다르다.
  • userFeed() method를 통해 User Object를 XML로 변환하고 이를 Feed 항목의 content 요소로 추가하는 것을 볼 수 있다.
끝!!


2013년 4월 3일 수요일

Spring3를 이용하여 RESTFul web service 생성하기 - JSON

Restful 웹 서비스 Build

오늘은 Android App을 개발하기 위해서 Application이 아닌 Server에 대한 학습을 했다.
수많은 Application 중에 단독으로 수행하는 App들도 있지만 대부분은 Server와 통신을 통해 데이터를 주고 받아 서비스하는 것이 많다.

Spring3에서 Restful 웹 서비스를 구현하기 위해서는 HttpMessageConverter를 구성해야 한다. HttpMessageConverter 인스턴스를 사용자가 정의하여 오브젝트를 서로 다른 매체로 변환하여 사용할 수 있다. 매체 유형으로는 JSON, ATOM 그리고 XML이 있다.

첫 번째 시간에는 JSON으로 변환하는 것을 공부하려고 한다.

JSON

아래는 간단한 예제다. JSON은 작은 데이터를 Server와 Client 간에 주고 받기에 쉽다. 여기에서 Client는 Application이다.

==> spring-servlet.xml에서 HttpMessageConverter 구성
--------------------------------------------------------------------
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
   <property name="messageConverters">
       <list>
           <ref bean="jsonConverter" />
           <ref bean="marshallingConverter" />
           <ref bean="atomConverter" />
       </list>
   </property>
</bean>

<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
   <property name="supportedMediaTypes" value="application/json" />
</bean>
--------------------------------------------------------------------

위의 내용에서 MappingJacksonHttpMessageConverter는 오브젝트를 JSON으로 변환하고 JSON 유형을 그 반대로 변환하는 경우에 사용된다

==> TestController에서 정의된 JSON 요청 처리
--------------------------------------------------------------------
@RequestMapping(method=RequestMethod.GET, value="/user/{id}", headers="Accept=application/json")
public @ResponseBody User getUser(@PathVariable String id) {
    User user = userDao.get(Long.parseLong(id));
    return user;
}
           
@RequestMapping(method=RequestMethod.GET, value="/users", headers="Accept=application/json")
public @ResponseBody UserList getAllUsers() {
     List<User> users = userDao.getAll();
     UserList userList = new UserList(users)
     return userList;
}
--------------------------------------------------------------------

@ResponseBody Annotation은 리턴 Object(User 또는 UserList)를 응답하여 정보를 전달하는 데 사용되고, 이것은 MappingJacksonHttpMessageConverter를 통해 JSON으로 맵핑된다.

HttpMessageConverter와 @ResponseBody Annotation을 사용하여 Spring의 View 방식을 사용하지 않고 여러 유형의 데이터를 생성하거나 전달할 수 있다.








Eclipse에서 Android Project를 만들어보자!!!

이번엔 이클립스에서 안드로이드 Project를 어떻게 생성하는지 공부하려고 한다.
이전 블로그 글에 환경 셋팅을 위해 안드로이드 개발자 페이지에서 SDK를 다운 받으면 패키지로 이클립스도 함께 다운로드를 받을 수 있다.
다운 받은 이클립스를 기반으로 안드로이드 Project를 만들어보려고 한다.

첫번째툴바 메뉴에서 클릭을 한다.

두번째. 툴바 메뉴를 클릭하면 다음과 같은 화면이 나타난다.
개발을 하고자 하는 안드로이드 프로젝트 유형을 선택하여 Next 한다.
여기서는 Android Application Project 유형을 선택하여 진행한다.















세번째. 위 화면에서 Next를 클릭하면 다음과 같은 화면이 나타난다.
새로운 안드로이드 Application에 대하여 Application Name, Project Name, Package Name을 입력한다. Application Name에 jini First App으로 입력을 하면 자동 완성으로 통해 Project Namer과 Package Name이 만들어진다. 아래 표기되는 Minimum Required SDK와 Target SDK, Compile With, Theme는 Application을 테스트하는 Device에 따라서 적당하게 선택하면 된다.
디폴트의 경우는 현재 release 된 최상위 버전 형태로 셋팅된다.
Next를 버튼을 눌러 다음으로 진행한다.




네번째. 기본으로 Launcher Icon을 생성할 것인지, activity를 생성할 것인지, 임의로 선택한 workspace에 프로젝트를 생성할 것인지에 대한 확인을 하는 화면이 나타난다. 기본 선택된 항목을 확인하고 Next 버튼을 눌러 다음으로 진행한다.

다섯번째. Launcher Icon에 대한 구성을 셋팅하는 화면이 나타난다. 일단 Next 버튼을 눌러 다음로 진행한다.

여섯번째. Activity를 생성하는 화면이 나타난다. 이 부분은 초기 Application의 UI layout을 어떻게 셋팅할지에 대해서 선택하는 부분이다.
Blank Activity, Full Screen Activity, Master/Detail Flow를 선택할 수 있고 그에 맞는 Template이 생성된다. 여기서는 기본으로 Blank Activity를 선택하여 진행한다.

일곱번째. Blank Activity를 선택하고 Next 버튼을 누르면 Activity Name, Layout Name, Navigation Type을 선택하는 화면이 나타난다.
여기에서 Navigation Type은 화면의 이동 방법을 선택하는 부분으로 지금은 none으로 선택한고 진행한다.

여덟번째. 마지막 Finish 버튼을 눌러 Project를 생성한다. 아래는 프로젝트를 생성한 최종 화면이다.


이번 시간에는 이클립스를 이용하여 Android Project를 생성하는 방법에 대하여 알아보았다. 다음 시간에는 생성된 Project에 대하여 알아보는 시간을 갖으려고 한다.

여기까지는 참 쉽네요~ 근데 앞이 깜깜하네요~
으악!!!!





2013년 4월 2일 화요일

Mac에서 Andriod 개발 환경 셋팅

mac에서 안드로이드 개발 환경을 셋팅하는 방법을 찾다가 결국 내 스스로 정리하기로 결정했다. 어려운건 아닌지라 그냥 주저리주저리 써내려가려고 한다.

자바 개발에서 안드로이드에 대한 개발을 위한 첫 걸음으로 천천히 배우고 습득하려한다.

안드로이드 개발 환경은 안드로이드 개발자 사이트에 자세히 잘 나와 있어서 기본적인 것을 배우는 것은 어려움이 없을 것 같다.

- 개발 환경 셋팅
http://developer.android.com/training/basics/firstapp/index.html
안드로이드 개발자 사이트에서 위와 같은 페이지로 이동하면 개발에 필요한 sdk와 eclipse를 다운로드 받을 수 있다.

- 프로젝트를 생성하는 방법은 보여주는 페이지
http://developer.android.com/training/basics/firstapp/creating-project.html

엡실행에 대한 가이드
http://developer.android.com/training/basics/firstapp/running-app.html

기본 UI 구성
http://developer.android.com/training/basics/firstapp/building-ui.html

개발 환경을 셋팅하면 이클립스와 sdk가 설치된다. 
여기 이클립스를 실행하면 첫 화면에 activity_main.xml과 strings.xml 에디터가 열려있다.

이것을 이해하면 basic UI는 구성할 수가 있게 된다고 한다.

난 아직 그냥 실행만 해봤다 ㅋㅋ

일단 여기까지 기본 셋팅 방법에 대해 공부한 것을 기술해 보았다.

이제 어떻게 진도를 나갈까 고민 중인데 책으로 할것인가? 아니면 웹을 찾아다니며?
그냥 책으로 하려고 한다..

시작이 반이라고 했다. 고고싱!!!!