'개발자세상/자바세상'에 해당되는 글 23건

  1. 2023.10.06 Scala future/blocking
  2. 2018.06.09 Chronos Notification issue
  3. 2017.11.28 POI로 Pivot테이블 만들기
  4. 2016.06.16 Scala 2
  5. 2016.02.02 Mockup 테스트
  6. 2015.08.15 java.lang.OutOfMemoryError: unable to create new native thread
  7. 2014.05.28 Control character in XML
  8. 2014.03.01 jboss db pooling timeout
  9. 2014.02.25 ResultSet FetchSize
  10. 2014.02.25 Timeout increase for axis soap client

늘 휴가를 가면 뭔가 이슈가 터진다.
이번 여름도 오랜만에 머리 식히려, 회사 이메일 다 무시하고 1주일 쉬고 왔는데, 
와서 체크해보다보니 creative unexpiration script가 일주일간 실행되지 않아 bidding 결과가 떨어 지는 일이 생겼다.
하필 휴가 출발하는 첫날 실행되던 Job이 vertica DB resource 이슈로  DB Connection 을 생성하지 못했는데, 
또 하필 그 Job이 Terminate 되지 않고 Hang up되어 그대로 Schedule 이 멈춰버린 것 이었다.

일단 어찌저찌 수습을 했지만, 이번엔 Tech Support 에서도 꽤 심하게 반응을 해서 Monitoring 방법을 찾아 보게 되었다.

다행히 최근에 Kubernetes 에서 Prometheus 를 통한 metrics를 구현 하게 되어 이 Job도 그렇게 해보기로 생각해 보았다.
docs/content/docs/instrumenting/exposition_formats.md at main · prometheus/docs (github.com)

문제는 CronJob 에 대해서도 Prometheus가 metrics 를 지원하냐 인데 prometheus 관련 annotation을 넣었더니 metrics  end-point를 1분 마다 hitting하는것은 확인이 된다.
그럼 1분 동안의 데이터를 유실할 수 있는 문제가 생기는데, 우리는 Job이 실행되는 거만 체크하려는 거니깐 1분 데이터 정도는 큰 문제가 되지 않을 듯 싶었다. 다만 전에는 모든 처리가 끝나고 메일 보내기 전에 metrics count를 set하게 되어 있었는데, 이걸 매번 creative processing할 때 metrics 를 update 하도록 변경해야 하였다.

당연히 문제 없이 될 줄 알았는데... 이게 Job 시작할 때 50 정도 까지 Counting을 하고 바로 Counting이 되지 않는 거다.
코드를 봐도 문제가 없고, 로그를 보면 Prometheus 가 metrics end point도 잘 hit하는게 보인다.

이게 무슨 문제일까 싶어서 metrics count method에서 로그를 찍게 해보니 Cronjob이 끝날때쯤에 갑자기 count method가 집중적으로 찍히는게 보인다.

이게 무슨 일일 까 싶었는데... 찾아 보니 future에 map을 사용할 경우 같은 future내의 connected processing이 되는 게 아닌 또 다른 future 객체가 생성되어 map operation이 수행되는 것이다.
내 local 환경에서는 map을 써도 단일 thread내에서 처리되듯이 큰 문제 없이 수행이 되는데..
서버에만 가면 metrics 의 count method를 위한 map processing을 처음 50개 정도는 바로 진행하지만 그 이후는 모두 wait 하였다가 cronjob이 끝날 때 한꺼번에 처리 해서 생긴 문제였다.
생각해보면 metrics count같은 method를 매번 처리 하는 것 보다 한번에 몰아서 처리하는 게 성능상으로는 더 좋을 것 같다는 생각이 든다.

어쨋든.. future.map을 이전 process 이후 바로 실행하게 하려고 찾아보다보니 blocking을 사용하면 전체 processing를 하나의 thread로 묶어서 처리 할 수 있게 되어 있다.

Understanding Scala Futures and Execution Contexts – Beyond the lines

 

Understanding Scala Futures and Execution Contexts – Beyond the lines

Viktor Klang recently published a set of useful tips on Scala Futures. While being widespread and heavily used, people (especially newcomers) are still experiencing problems working with Scala Futures. In my opinion many of the problems come from a misunde

www.beyondthelines.net

늘 느끼는 거지만 future가 개념 잡기도 어렵지만 사용하기도 참 어려운 기술이라는 생가이다.
아니면 아직도 예전 blocking 기반의 기술 에서 벗어나지 못해서 인걸 수도 있겠다.

'개발자세상 > 자바세상' 카테고리의 다른 글

Chronos Notification issue  (0) 2018.06.09
POI로 Pivot테이블 만들기  (0) 2017.11.28
Scala  (2) 2016.06.16
Mockup 테스트  (0) 2016.02.02
java.lang.OutOfMemoryError: unable to create new native thread  (0) 2015.08.15
Posted by headiron
,

AppNexus 업무로 넘어 온 후 제일 먼저 했던 일이 Chronos 도입이었다.


OAS하면서 EJB Java코딩만 하던 나에게 완전 환경이 다른 AppNexus환경에서 해당 업무를 해내는 건 정말 골치 아픈 일이었다.도입한 이후로 몇가지 문제가 생겨도 그냥 Internet searching해서 대충 문제 봉합하는 정도..


얼마전에 구글에 등록된 퇴사자 계정을 Disable한 이후로 Chronos에 등록된 모든 Script가 동작하지 않는 문제가 발생했다.

내가 주기적으로 모니터링 하고 있었기에 크게 이슈화 되기 전에 문제를 해결했는데,

근본적으로는 Script 가 Fail했을 경우에 Notification해줬으면 금방 알 수 있었던 문제 이다.


일단 예전에 Chronos에 메일을 보내게 할려면 /etc/chronos/conf 폴더에 mail_server라는 파일을 만들고 해당 파일에 파일 서버명을 적으면 된다는 Article 을 보고 적용했던 일이 생각났다.ps java로 command를 확인해 보면 mail_server option 이 parameter로 잘 적용된 것도 보인다.


우선 Log를 Enable시켜 놓고, 메시지를 확인하면서 Chronos 소스 코드를 확인해 보았다.


chronos script를 확인해 보니 /etc/chronos/conf 폴더에 option이름으로 파일을 만들고 값을 저장하면 해당 옵션을 자바 구동시 넣어 주는 것을 확인했다.결국 ps 로 확인했다고 해서 option이 제대로 적용됐다는 보장이 없는 것이다.


결국은 Chronos 소스를 봐야 할 문제 ...

소스를 Checkout 해보니 언어는 Scala.. ( 예전에 한 참 Chronos일 할 때 Scala로 개발했다는 얘기를 들을 기억이.. )


예전에는 Scala 를 몰라 뜨아 하고 덮었을 텐데 다행히도 AppNexus 업무를 맡은 후 공부를 해 놔서 걱정이 없다.


소스를 보면서  mail_server가 정확한 option인건 확인을 했고,

Module class에서 @Singleton, @Provides Annotation으로 notification actor를 Initial 해주는 것도 확인이 되었다.


좀더 자세히 뒤져 보았더니 

메일 관련 Config중 

mail_server config는 <Server Address>:<Server Port>로 설정이 되어 있어야 하고,

mail_from 이 String으로 Define되어 있어 반드시 입력이 되어 있었어야 하는 것이었다.


결국 /etc/chronos/conf 폴더에 mail_server는 <Mail Server Addr>:25, mail_from은 우선 내 메일 주소를 넣어 보니 메일이 잘 온다.


Scala를 좀 뜯어 볼 줄 알았다면 일찌감치 해결 했을 문제를 2년 동안 전전 긍긍했던 것이다. :-(


오늘도 이렇게 지식의 힘들 느끼며 문제를 해결했다.



이슈를 추적하면서 한가지 궁금했던게...

대체 Chronos 소스가 어디 있는 건가 하는 문제였는데 ...


Script 를 따라 가다보니 /usr/bin/chronos가 실행 Script이고, 

파일을 열어 보니 윗 부분은 Schell script가 아랫부분은 Binary 코드가 있다.


좀 이상해서 검색 해보니 cat을 이용하여  schell script와 jar파일을 다른 File에 redirect하고 x permission을 주면 Shell script와 jar를 한 파일로 만들 수 있는 것이다.

https://coderwall.com/p/ssuaxa/how-to-make-a-jar-file-linux-executable


그리고 Chronos log  enable은 log4j 파일을 작성한 후 

/usr/bin/chronos 의 구동 부분에 -Dlog4j.configuration=file:/etc/chronos/log4j.properties 와 같이 옵션을 추가 하면 된다.


요즘 Docker+ Kubernates 가  Popular해서 Mesos+Chronos 가 밀리고 있는데 

2년 전에 Chronos 도입할 떄 내가 좀 더 기술적으로 잘 알았으면 

적어도 AppNexus에서는 좀 더 각광받는 기술이 되지 않았을 까 하는 생각이 들고 

언제는 기술적으로 준비가 되어 있어야겠다 하는 생각이 많이 든다. 






'개발자세상 > 자바세상' 카테고리의 다른 글

Scala future/blocking  (0) 2023.10.06
POI로 Pivot테이블 만들기  (0) 2017.11.28
Scala  (2) 2016.06.16
Mockup 테스트  (0) 2016.02.02
java.lang.OutOfMemoryError: unable to create new native thread  (0) 2015.08.15
Posted by headiron
,

POI를 써 온지는 꽤 오래 되었다. 주로 테이블 데이터를 엑셀 파일로 만드는 정도를 했는데  생각해 보면 그런 기능 정도는 그냥 csv 파일을 만들어도 되는 기능이었던것 같다.


AppNexus Join이후로는 통계 관련 요구사항이 없어 쓸 일이 없었는데 

얼마전에 Carrier Data Integration 모듈(?)을 개발하면서 

Data refresh전에 데이터 변경 내역을 보여주는 Excel을 만드는 게 어떨까 해서 Excel을 만들어 보았는데 

생각해 보니 이 기능을 실제 Integration Module 에 넣는게 어떨까 해서 다시 POI를 쓰게 되었다.


제일 중요한게 Pivot 테이블 생성 기능인데 

마지막으로 POI를 사용할때는 Pivot 기능이 없었던걸로 기억하는데 다행이 Pivot 테이블 생성하는 기능도 추가가 되었다.


다만 Pivot기능을 사용하기 위해서는   poi이 외에 poi-ooxml도 library에 추가해 주어어 햔다.

"org.apache.poi" % "poi" % "3.17",
"org.apache.poi" % "poi-ooxml" % "3.17",

이렇게  poi와 poi-ooxml을 추가한 후 Excel Sheet를 생성해서 데이터를 해당 Sheet에 저장했다.


val wb = new XSSFWorkbook
val sheet = wb.createSheet("Rawdata") IPRanges.foreach(ipRange => { val row = sheet.createRow(rowIndex) row.createCell(0).setCellValue(ipRange("country").asInstanceOf[String]) ... row.createCell(6).setCellFormula(s"F${rowIndex + 1}-E${rowIndex + 1}+1") rowIndex = rowIndex + 1 })

이렇게 데이터를 생성한 후 Pivot테이블을 위한 Sheet를 생성해서 Pivot테이블의 데이터 영역에 위의 데이터 Sheet를 설정하면 Pivot테이블이 생성된다. val summarySheet = wb.createSheet("Summary") val source = new AreaReference(s"Rawdata!A2:G${rowIndex}", SpreadsheetVersion.EXCEL2007) val position = new CellReference("A3") val pivot = summarySheet.createPivotTable(source, position)

Pivot테이블의 Rows는 아래와 같이 영역내의 몇 번째 Column인지를 지정하면 된다.

pivot.addRowLabel(0) pivot.addRowLabel(1)


Pivot테이블의 Values는 아래와 같이 몇 번째 Column에 어떤 Function 을 적용할지를 지정하면 된다.

pivot.addColumnLabel(DataConsolidateFunction.SUM, 6)


헌데 Pivot테이블의 Columns 부분을 적용할 수 있는 함수를 찾을 수가 없었다.

( 내 Pivot테이블은 국가 , Carrier를 Row로 하고, 데이터에 있는 Before/After 데이터를 Column으로 데이터를 보여 주고 싶은데 이 기능은 Pivot의 Columns 을 통해서 적용이 된다.)


이것 저것 해보다가 안 되서 꽤 오랫동안 Googling을 했더니 아래와 같은 해결 책이 나왔다.


pivot.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(3).setAxis(
org.openxmlformats.schemas.spreadsheetml.x2006.main.STAxis.AXIS_COL);

pivot.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(3).addNewItems();
pivot.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(3).getItems().addNewItem().setT(
org.openxmlformats.schemas.spreadsheetml.x2006.main.STItemType.DEFAULT);

pivot.getCTPivotTableDefinition().addNewColFields().addNewField().setX(3);

데이터 테이블의 3번째 Column의 데이터를 Pivot Table의 Columns에 적용하려면 위에 처럼 몇 개의 함수를 다 선언해야 한다.


구글링하면서 다른 이의 API Naming이 잘못 되었다는 ( addColumnLable-> addValues ) 의견에 전적으로 동의한다.

그리고 왜 Pivot 테이블의 Columns 부분을 저렇게 여러개의 함수를 선언하게 만들었는지 솔직히 이해가 가지 않는다.


뭐... 몇 가지 아쉬움이 있지만 어쨋든 Pivot테이블은 완성이 되었다.


한가지 아쉬운 점은... 엑셀을 오픈하면 Pivot테이블이 있는 Sheet을 Default로 보여주려고 했는데...


wb.setActiveSheet() 으로 Pivot테이블의 Sheet을 적용하면 엑셀 오픈할 때 에러가 발생해서 이 부분은 적용해 주지 못했다.


어쨋든... POI 덕분에 수작업도 줄일 수 있게 되어 뭐.. 기분은 나쁘지 않다.

POI Pivot관련 해서는 아래 페이지들을 참조 했다.

http://www.novixys.com/blog/excel-pivot-table-using-apache-poi/
https://stackoverflow.com/questions/35943812/xssfapache-poi-adding-multiple-column-label-from-single-column-value-in-pivo













'개발자세상 > 자바세상' 카테고리의 다른 글

Scala future/blocking  (0) 2023.10.06
Chronos Notification issue  (0) 2018.06.09
Scala  (2) 2016.06.16
Mockup 테스트  (0) 2016.02.02
java.lang.OutOfMemoryError: unable to create new native thread  (0) 2015.08.15
Posted by headiron
,

Scala

개발자세상/자바세상 2016. 6. 16. 01:27

팀을 옮긴지 근 1년이 되는 시점에 드디어 Scala로 개발한 Product를 Release하게 되었다.


개발자로 경력시작하면서 의도하지 않게 asp, php를 배운이후로 새로운 언어를 배우는게 근 15년 만인듯 싶다.


1년 가까이 Scala, Play를 공부하며 매달려서 드뎌 하나를 개발했다는 자부심도 느끼지만, 아직도 Scala에 대해서 절반도 이해하지 못한 듯 싶어 너무 아쉽기도 하다.


가끔은 이렇게 어려운 언어가 왜 Popular할까 하는 생각도 하게 되는데... 내가 너무 오랫동안  OOP언어에 갇혀 있었기 때문이 아닌가도 생각된다.

아마도 예전에 Cobol로 개발하던 사람들도 Web시대로 오면서 비슷한 느낌이었을 까..


어쨋든 새로운 창 하나를 얻었다는 것이 기쁘고.. 

또 이번 Project를 하면서 얻었던 정보도 잊기 전에 기록해 두는 것이 좋을 듯 싶다.


회사의 Fireglass Framework을 사용하였지만 그 근간은 Play 2.3이다.

Fireglass에는 여러 Module들이 있는데 그 중 Moria라는 DB 모듈이 있다.

원래대로라면 DB Framework으로 이걸 사용해야 하는데, 어찌 하다 보니 다른 솔루션들을 검토하게 되었고, 그 중에  SkinnyORM을 사용하게 되었다.


http://skinny-framework.org/documentation/orm.html


Skinny Framework의 Sub framework 인데 Light weight하면서도  기능도 Powerful한 Framework이다.

ORM자체로서의 기능도 좋고, 근간이 ScalikeJDBC라는 Native SQL을 사용하기 때문에 Native Query를 사용할 수도 있다.

또 Skinny 에서 제공되는 Validator도 사용방법이 간단하면서도 쉽게 Expandable하게 되어 있어서 선택하게 되었다.


물론 MYSQL을 사용할 떄 다른 DB에 있는 TABLE을 지원하지 못하는 제약사항이 있기는 한데.. 

https://groups.google.com/forum/#!topic/skinny-framework/7zF4cQp3CLY

일단 DB만큼의 DB Pooling을 생성하고 각 Model별로 DB connection name을 overloading하는 방법으로 workaround할 수있었다.


Play와 연동은 아래 문서를 참조하면 되었다.

http://scalikejdbc.org/documentation/playframework-support.html


나는 일단 Play 2.0 ~ 2.3의 scalikejdbc-play-plugin을 이용하는 방법을 사용했는데 , 테스트를 진행하다 보니 Play의 DB config를 읽어 와서 자체 DB Pooling을 생성하여 사용하는 구조였다.

Redundant한 DB Pooling이 생기고 Play에서 설정된 DB Pool관련 Enhanced Option을 사용하지 못하는 문제가 발생했다. 특히나 Play에서 설정한 idleConnectionTestPeriod 설정을 읽지 않아서 DB Connection이 close되는 이슈가 발생했다.

이 문제는 scalikejdbc-play-dbplugin-adapter를 사용함으로써 해결이 되었다.


DB Pooling관련 이슈를 Followup하면서 발견한 사실인데 Play의 경우 2.3 에서 2.4로 넘어 가면서 DB Pooling library가 바뀌었다.

2.3에서는 BoneCP 라는 library를 사용하였는데, 2.4에서 Hikaricp로 변경이 되었다.

 BoneCP : http://www.jolbox.com

 HikariCP : https://brettwooldridge.github.io/HikariCP/


왜 바꾸었는지 보다 보니 BoneCP Framework이 Deprecate되어서 HikariCP로 넘어 가게 되었다.


일단 우리는 2.3을 사용하니 BoneCP에 맞추어 아래와 같은 Advanced Option을 사용하였다.


connectionTestStatement = "/* ping */ select 1"
idleConnectionTestPeriod = 1 minute

idleMaxAge = 10 minute
connectionTimeout = 20000
partitionCount = 2
minConnectionsPerPartition = 2
maxConnectionsPerPartition = 5
poolMaxSize = 10

다른 Option들에 대해서는 좀더 체크해 봐야 겠지만 특히나 좋은 부분은 idelConnectionTestPeriod인것 같다.

여기에 설정된 Duration에 맞추어 connection 을 테스트 하기때문에 DB 서버에서 Timeout 되어서  DB close하는 이슈를 방지할 수 있다.


일단 새로운 언어, 새로운 Framework에 대해서 알게 되었으니 좀더 공부해서 완전한 나의 창으로 만들어야 겠다.

특히나  Type System, Actor Model, Monad 등 좀더 고급 기능에 대해서 좀더 파해치다보면 Scala전문가가 될 수 있지 않을까 싶다.

 


'개발자세상 > 자바세상' 카테고리의 다른 글

Chronos Notification issue  (0) 2018.06.09
POI로 Pivot테이블 만들기  (0) 2017.11.28
Mockup 테스트  (0) 2016.02.02
java.lang.OutOfMemoryError: unable to create new native thread  (0) 2015.08.15
Control character in XML  (0) 2014.05.28
Posted by headiron
,

그동안 주로 EJB로 개발하다보니 Mockup테스트를 알고 있으면서도 사용하지 못했었는데 Cron Project를 진행하면서 사용하게 되었다. 알고 있는지는 10년은 된것 같은데 이제서야 쓸 생각을 하다니..

일단 시작은 Mockito를 사용해서 Mock객체를 생성해서 테스트를 진행해 보았다.

http://mockito.org

쓰는 방법은 간단했다.

mock(new ObjectO))를 실행하면 헤당 Object의 method를 실행할 수 있는 Mock객체가 생성된다. 

그 후에 when()등의 메소드를 사용하여 특정 메소드가 호출 될 경우 특정 결과를 Return하게 하도록 한후,

해당 Mock객체를 실제 객체에 Wiring하고  

객체 메소드를 호출하면 Mockup객체에 등록된 메소드에 따라 결과가 Return되고, 이를 통해서 실제 객체가 잘 실행되는지를 확인하게 되는 것이다.


처음 Mock을 사용할 때 when()메소드로 선언하는거 이외에는 원래 객체의 메소드를 호출하는 걸로 오해하고 진행을 해 보니  Mock객체는 객체의 메소드들을 가지고 있는 정말 Mockup객체일 뿐이었다.

특정 메소드 이외에 다른 메소드는 원래 코드를 실행하게 하기를 원할 경우는 mock()이 아닌 spy()를 사용해야 한다.


마침 내가 개발하는 코드가  Method가 여러개이지만,  각 Method가 다른 API를 호출하는 형태에서 API호출하는 부분을 별도의 private  메소드로 추출했고, 해당 부분을 spy() 하게 되면 외부 API를 사용하는 코드도 테스트 할 수 있게 될 듯 했다.

근데 문제는 Mockito는 private메소드에 대해서는 spy()를 진행할 수 없었다.

그래서 Search를 해보니 PowerMockito를 사용하면 private 메소드를 spy()할 수 있다고 한다.

일단 pom.xml에 PowerMockito dependency를 등록하고, 

<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.6.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-easymock</artifactId>
<version>1.6.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.6.3</version>
<scope>test</scope>
</dependency>

import org.powermock.api.mockito.PowerMockito;
...

@

Connector mockConnector = PowerMockito.spy(connector);

....

@Test

public void testThirdPartyConfig(){

PowerMockito.doReturn(configJsons).when(mockApiConnector, "list",
"thirdparty-config", queryParam);
FacebookConfig config = mockConnector.getThirdPartyConfig();

참고로 내가 테스트 하려는 코드를 connect.getThirdPartyConfig 메소드이고, getThirdPartyConfig는 connect.list("thirdparty-config",queryParam) 메소드를 호출하여 외부 API를 호출하고, 그 결과를 파싱해서 사용자에게 객체로 리턴해준다.따라서 list메소드를 spy하면 외부 API를 호출하지 않고 getThirdPartyConfig메소드가 잘 실행되는지 확인할 수 있는 것이다.


잘 되기는 하는데 private메소드에 대해서는 좀 이상하게 실행이 되어서 Abstract메소드를 protected로 변경했더니 잘 싱행이 된다. 

그리고 진행을 하다 보니 PowerMockito가 Mockito를 사용하는 Test보다 훨씬 느리다.

서치를 해보니 내부적으로 객체 생성을 많이 한다고, 가능하면 Mockito를 사용하라는 걸 보니 , 이게 좀 문제 인듯 하다.


성능 부분을 제외한다면, PowerMockito가 꽤 괜찮은 솔루션으로 보인다.




'개발자세상 > 자바세상' 카테고리의 다른 글

POI로 Pivot테이블 만들기  (0) 2017.11.28
Scala  (2) 2016.06.16
java.lang.OutOfMemoryError: unable to create new native thread  (0) 2015.08.15
Control character in XML  (0) 2014.05.28
jboss db pooling timeout  (0) 2014.03.01
Posted by headiron
,

지난번에 Search관련해서 이슈가 있었는데 

오늘 on call로 연락온 내용을 review 하다 보니 같은 이슈가 production 에도 발생했던 걸로 보인다.

예전에 메일을 찾다보니 운호선임이 잘 정리 해 놓은게 보여서 다음번에 필요할 듯 해서 정리 해 놓는다. 

( Thanks Unho ) 

It occurred by limit of max user processes on server configuration.

Check

Check limit of max user processes

[central@01 ~]$ ulimit -u

Check count of processes by elasticsearch

[01 ~]$ ps -eLf | grep elasticsearch | wc -l

728

How to solve 

Update /etc/security/limits.conf
...

<account> soft nproc 30000
<account> hard nproc 30000


'개발자세상 > 자바세상' 카테고리의 다른 글

Scala  (2) 2016.06.16
Mockup 테스트  (0) 2016.02.02
Control character in XML  (0) 2014.05.28
jboss db pooling timeout  (0) 2014.03.01
ResultSet FetchSize  (0) 2014.02.25
Posted by headiron
,

아침에 출근해 보니 Backend Process가 invalid character 때문에 fail 되는 이슈가 발생되어 API 쪽 수정을 요청받았다.

0x3 character가 Field에 들어가서 문제가 생겼다고 하는데,
일단 우리 API도 XML로 processing 하니깐 아마도 API로는 해당 값이 들어가지 않았을 것 같은데,
문제는 어떻게 그 값을 넣는지 모르겠다는 것이다.

Googling 을 해보니 &#x3; 이렇게 넣으면 0x3 값을 넣을 수 있었다.
http://stackoverflow.com/questions/8485436/unicode-characters-like-u0016-in-xml

그리고 찾아 보니 invalid character를 escape 하는 tip도 찾을 수 있었다.( 뭐 물론 테스트 해보진 않았지만.. )

http://blog.mark-mclaren.info/2007/02/invalid-xml-characters-when-valid-utf8_5873.html

다행히 API는 DTD validation 단계에서 invalid character를 detect 하고 있어서 큰 문제는 없는 것으로 확인됐다.

'개발자세상 > 자바세상' 카테고리의 다른 글

Mockup 테스트  (0) 2016.02.02
java.lang.OutOfMemoryError: unable to create new native thread  (0) 2015.08.15
jboss db pooling timeout  (0) 2014.03.01
ResultSet FetchSize  (0) 2014.02.25
Timeout increase for axis soap client  (0) 2014.02.25
Posted by headiron
,

Apahce 의 timeout 숫자를 increase 했던 client 쪽에서 이번에는 에러가 발생한다고 연락이 왔다.
로그를 Review 해 보니 timeout인것 같은데, 정확히 어디서 나왔는지를 모르겠다는 것이다.

02/28/2014 13:37:37,393 WARN  [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.TransactionReaper_18] - TransactionReaper::check timeout for TX a830b16:916:5310bf91:c in state  RUN
02/28/2014 13:37:37,394 WARN  [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_58] - Abort of action id a830b16:916:5310bf91:c invoked while multiple threads active within it.
02/28/2014 13:37:37,394 WARN  [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.CheckedAction_2] - CheckedAction::check - atomic action a830b16:916:5310bf91:c aborting with 1 threads active!
02/28/2014 13:37:37,804 WARN  [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.TransactionReaper_7] - TransactionReaper::doCancellations worker Thread[Thread-7,5,jboss] successfully canceled TX a830b16:916:5310bf91:c
02/28/2014 13:37:37,824 WARN  [JDBCExceptionReporter] SQL Error: 0, SQLState: null
02/28/2014 13:37:37,824 ERROR [JDBCExceptionReporter] Transaction TransactionImple < ac, BasicAction: a830b16:916:5310bf91:c status: ActionStatus.ABORTED > cannot proceed STATUS_ROLLEDBACK; - nested throwable: (javax.transaction.RollbackException: Transaction TransactionImple < ac, BasicAction: a830b16:916:5310bf91:c status: ActionStatus.ABORTED > cannot proceed STATUS_ROLLEDBACK)
02/28/2014 13:37:37,824 WARN  [JDBCExceptionReporter] SQL Error: 0, SQLState: null
02/28/2014 13:37:37,824 ERROR [JDBCExceptionReporter] Transaction TransactionImple < ac, BasicAction: a830b16:916:5310bf91:c status: ActionStatus.ABORTED > cannot proceed STATUS_ROLLEDBACK; - nested throwable: (javax.transaction.RollbackException: Transaction TransactionImple < ac, BasicAction: a830b16:916:5310bf91:c status: ActionStatus.ABORTED > cannot proceed STATUS_ROLLEDBACK)
02/28/2014 13:37:38,548 ERROR [STDERR] org.hibernate.exception.GenericJDBCException: could not inspect JDBC autocommit mode
...


결국 googling을 한 결과 jboss db pooling의 경우 arjuna 모듈을 사용하고 있고, 해당 모듈의 timeout 설정은 deploy/transaction-jboss-beans.xml에서 설정하게 되어 있다.

참조 : https://community.jboss.org/message/95336#95336


일단 기본 값은 10분 인데 더 늘려서, 실행이 되는 것 까지는 확인하였는데..
문제는 transaction이 더 길어 지면 결국은 또 timeout은 발생할 수 있다는 거..
결국은 program이나 시스템 structure를 바꿔야 한다는 얘기..

이번 case는 client측의 사용 패턴을 바꿔야 할 듯 한데..
Tech Support에서 어떻게 유도해 나갈지는 모르겠다..


'개발자세상 > 자바세상' 카테고리의 다른 글

java.lang.OutOfMemoryError: unable to create new native thread  (0) 2015.08.15
Control character in XML  (0) 2014.05.28
ResultSet FetchSize  (0) 2014.02.25
Timeout increase for axis soap client  (0) 2014.02.25
자바 DEBUGGING  (0) 2013.11.20
Posted by headiron
,

Client support 이슈로 작성하게 된 Data Dump API.
기능적으로는 문제가 없었는데.. Performance가 생각만큼 나오지 않았다.
DBA 팀에 속도가 너무 느리다고 문의 해 보니, Query 자체는 빠르게 실행된다고..
그러면서 fetch size를 증가시켜 보란다.

Googling 해보니, Oracle JDBC의 default FetchSize가 10이다.
Query 자체는 Optimize 되어서 빠르게 실행되고 있는데, 한 번 가져올 때 10개만 가져오다보니 Data Entry 개수가 많을 경우에 DB에 Revisiting 하는 회수가 증가하면서 Query 실행시간은 빠른데 JDBC side 에서는 느릴 수 밖에 없었던 것이다.

일단은 ResultSet에 fetchSize를 100으로 늘려 주어서 8초 걸리던 Query가 1초 이내에 실행되게 되었는데, fetchSize는 Statement level에서도 설정해 줄 수 있는 config 이다.

흐... 10 년 넘게 Java 개발하면서 이런 부분을 모르고 있었다니..
좀 많이 쪽 팔리는 일이..
뭐 그래도 어쩃든 DBA 도움 덕분에 성능을 크게 향상시키고 새로운 걸 알게 되었으니,
그게 어디여....

'개발자세상 > 자바세상' 카테고리의 다른 글

Control character in XML  (0) 2014.05.28
jboss db pooling timeout  (0) 2014.03.01
Timeout increase for axis soap client  (0) 2014.02.25
자바 DEBUGGING  (0) 2013.11.20
Spring property  (0) 2013.10.15
Posted by headiron
,

이번에 Client support를 진행하는 중에 큰 데이터를 사용하는 것 때문에 10분 이상의 timeout 세팅을 사용해야 하는 Client issue 가 발생했다.

일단 Timeout은 Apache의 Timeout에 설정되어 있어서 해당 Config를 증가 시키면 되었는데,
문제는 Client side의 timeout 관련 이슈가 계속 발생하는 것이다.

뭐.. 우리 Google 님에게 문의 했고 결과는 아래와 같이 Timeout property를 증가시켜 주면 되었다.

ServiceFactory factory = ServiceFactory.newInstance ();
Service service = factory.createService (url, qname);
Call call = service.createCall (port, operation);
call.setProperty(org.apache.axis.client.Call.CONNECTION_TIMEOUT_PROPERTY, 1800000);
...


위의 Setting은 Axis 에서 Timeout을 설정해 주는 코드 인데..
결국은 다른 Client를 사용하는 Client에 대해서는 다른 코드를 찾아야 한다는..





'개발자세상 > 자바세상' 카테고리의 다른 글

jboss db pooling timeout  (0) 2014.03.01
ResultSet FetchSize  (0) 2014.02.25
자바 DEBUGGING  (0) 2013.11.20
Spring property  (0) 2013.10.15
human readable 한 json 출력  (0) 2013.03.22
Posted by headiron
,