2011년 2월 14일 월요일

All threads (200) are currently busy, waiting. Increase maxThreads (200) or check the servlet status

2011. 2. 13 오후 9:26:36 org.apache.tomcat.util.threads.ThreadPool logFull
심각: All threads (200) are currently busy, waiting. Increase maxThreads (200) or check the servlet status

tomcat에서 이런 메세지를 종종 볼 수 있다.

다른건 필요없고 해당 원인이 발생되는 이유는
톰켓 내부에서 사용되는 쓰레드가 특정 코드에서 lock 걸리고
그 lock가 maxThreads(default:200)을 넘어버리면서 나는 현상이다.

그런데 이 문제를 해결하기 위해서 단순하게 maxThreads 값을 늘려버리는데,
이것은 근본적인 문제를 무시하고 단순히 2시간 뒤면 뻗을 서버가 3시간으로 연장하는
수준밖에 되지 않는다.

이런 문제점을 해결하기 위해서는 제니퍼(Jennifer) 같은 모니터링 서비스를 설치하는게 좋으나,
여건 상 불가능 한 경우가 많다.

* 하단에 다른 방법도 추가했습니다.- Probe를 이용 (2013-01-02)

하지만 방법이 없는 것은 아니다.

다행이도 대부분의 리눅스, 유닉스 시스템에서 java thread dump 기능을 제공한다.
이것을 모든 것을 파악하기는 힘들지만,
최소한 어디선가 발생하는지 원인을 파악할 수 있으니, 모름지기 큰 도움이 될것이며,
이것을 알아두면 더 좋은 스킬을 쌓을 수 있다.

구글창에 java thread dump 검색하면 수두룩하게 좋은 결과가 많으니,
공부하는 것도 좋다고 생각한다.

백마디 말보단 간단하게 예제소스를 적어주는 것이 도움이 되지 않겟는가?
환경 : SunOS + apache2 + tomcat5.5

# ps -ef grep java
root 1139 1 0 11월 27 ? 465:58 /usr/jdk/latest/bin/java -version:1.5+ -jar /usr/lib/patch/swupna.jar -wait
search 28634 1 0 11월 29 ? 670:24 /usr/jdk/j2sdk1.4.2_13/bin/java -Xmx256m -Xbootclasspath/a:/user/search/sf-1/wn
tomcat 26601 1 0 14:21:50 pts/8 9:33 /usr/java/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/loggi
root 8110 21046 0 15:58:16 pts/8 0:00 grep java

톰켓이라는 계정으로 실행된 프로세스가 확인된다. (요놈이 바로 톰켓 프로세스이다.)
계정명으로 확인이 안되면 뒤에 옵션면에 톰켓 폴더가 있는걸로 확인하면 된다.

빨간색을 표시되는것이 pid(프로세스아이디)이다.

해당 톰켓 프로세서 스레드덤프를 확인해보자.

# kill -3 26601
* 참고로 kill -3 명령어가 안 먹히는 경우에는 (보통 리눅스인)
# jstack 26601 을 활용하자.
이렇게 실행한 후에 tail 명령어로 catalina.out를 확인하자.

# cd $CATALINA_HOME
톰켓 홈 디렉토리로 이동
# cd logs
# tail -2000f catalina.out

...

확인하면 해당 OS벤더에 따른 java thread dump 내용을 확인할 수 있다.

본 인의 경우에는

"TP-Processor121" daemon prio=3 tid=0x005016f8 nid=0xca runnable [0xa90fe000..0xa90ff8f0]
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at com.javaservice.lwst.SocketWrapper$InputStreamWrap.read(Unknown Source)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:256)
at java.io.BufferedInputStream.read(BufferedInputStream.java:313)
- locked <0xe48782f0> (a java.io.BufferedInputStream)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:681)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:626)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:974)
- locked <0xe4867208> (a sun.net.www.protocol.http.HttpURLConnection)
at org.apache.jsp.html.tsearch.XmlTrans_jsp.getHtmls(XmlTrans_jsp.java:32) at org.apache.jsp.html.tsearch.XmlTrans_jsp._jspService(XmlTrans_jsp.java:90)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:98)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:331)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:329)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:200)
at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:283)
at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:773)
at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:703)
at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:895)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
at java.lang.Thread.run(Thread.java:595)

이런 내용이 존재하였는데

/html/tsearch/XmlTrans.jsp 소스 내부에서
BufferdInputStream 객체가 제대로 해제가 안되고
해당 메소드(getHtmls)의 파라메터도 제대로 넘어가지 않아서 해당 객체가 리퀘스트 자체가 lock가 걸려서 theard Poll 에서 full이 나는 경우였다.

다행히 관련 소스를 수정하니 더 이상 문제가 발생하지 않았다.

다들 java thread dump를 이용해서 관련 문제를 잘 해결하시길 바랍니다.


_________________________________________________________________________

더 좋은 방법이 있음!

Probe 라는 웹어플리케이션을 설치하면 됩니다.
일종의 모니터링 프로그램인데요. 제니퍼와 같은 상용에는 못 미치나
그럭저럭 사용할만 합니다.

단, tomcat에만 적용이 가능합니다.

https://code.google.com/p/psi-probe/downloads/detail?name=probe-2.3.3.zip

여기에서 최신 버전을 다운 받을 수 있습니다. (현재는 개발 중지 상태인 듯)

해당 War를 이용하여 설치하시고 톰켓 관리자 ($CATALINA_PATH/conf/tomcat-user.xml)
권한으로 로그인하면 사용이 가능합니다.

아래와 같은 화면을 통해서 GUI를 통해서 모니터링 및 각종 리소스 현황 등을 확인할 수 있습니다. Thread full과 관련해서는 Threads 라는 메뉴를 통해서 확인하시면 쓰레드가 지속적으로 lock 되는 부분을 확인 하는 것도 가능합니다.




Probe 좋네요 ㅇㅇ

2010년 8월 11일 수요일

톰켓에서 일부 폴더(common, bin, webapps 등) 접근 (404 에러) 이슈

톰켓에서 일부 폴더 (common, bin, webapps, server)가

접근이 안되고 404에러가 나는 경우가 있다.

 

이유는 간단한다.

 

보통 서버 설정시에 가상호스트를 많이 사용하는데

 

<Host name="dev.domain.com">
   <Context path=""
    docBase="/data/homepage/domain"      
          reloadable="true"
          debug="true">
         </Context>
   <Alias>dev.domain.com</Alias>
  </Host>

 

이렇게들 많이 설정할 것이다.

 

이렇게 되면 Host의 appBase 속성이 빈 문자열이 되면서

자동적으로 $TOMCAT_HOME 를 바라보게 된다.

 

이로인해 $TOMCAT_HOME 하단 폴더를 먼저 바라보는 기이한 현상이 일어나게 된다.

ex) common, bin, webapps, server, conf, logs, shared, temp, work 등

 

고로 Host의 appBase 속성을 꼭 지정하도록 한다

본인은 그냥 webApps로 지정하였다.

 

<Host name="dev.domain.com" appBase="webapps">
   <Context path=""
    docBase="/data/homepage/domain"      
          reloadable="true"
          debug="true">
         </Context>
   <Alias>dev.domain.com</Alias>
  </Host>

 

* 되도록이면 지정하는 폴더는 내부에 아무런 내용이 없는 것으로 하는 것이 좋다.

그래야 또 겹치는 폴더가 없으므로 ㅇㅇ

 

 

* 참고로 본인이 개발한 환경은 apache2 + tomcat5.5 + mod_jk 연동에서 난 오류 이므로 버전이 다르거나 연동하지 않는 경우에는 어떻게 될련지 모릅니다.

 

 

이것 때문에 4시간 삽질한게 자랑 ㅠ

apache usage경로(폴더) 접근제한(403 forbidden) 이슈

 

아파치 설치 경로가 /etc/httpd 라고 할 경우

 

/etc/httpd/conf.d/webalizer.conf 파일 내용에

 

Alias /usage /var/www/usage

<Location /usage>
    Order deny,allow
    Deny from all
    Allow from 127.0.0.1
    Allow from ::1
    # Allow from .example.com
</Location>

 

이런 내용이 가상 디렉토리로 잡아서 생기는 문제이다

이 부분을 주석처리 하면 된다.

 

 

2010년 7월 28일 수요일

ASP 다국어 이슈 (UTF-8)

ASP
1. Response.AddHeader "content-type","text/html;charset=UTF-8"
2. Response.Charset = "UTF-8"
3. Session.CodePage = 65001 '새로고침 대응

위 내용은 공통 Include 페이지에 포함 시킨다.

4. <%@ LANGUAGE='VBSCRIPT' CODEPAGE='65001' %>
-> 위 문장은 리퀘스트에서 넘어가는 값들(ex:Request("name"))을 UTF-8로 변환시킨다.

5. .asp 소스 파일은 꼭 UTF-8로 형식으로 저장 한다.
HTML <meta> 태크 추가
-> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

6. 단... 메일 관련된 HTML 파일의 경우 (ex: /mail/joinConfirm.html)
->내부적으로 Server.CreateObject("Scripting.FileSystemObject") 이용하여 파일 내용을 긁어올 경우
대상 HTML 파일은 일반 ANSI 형식으로 저장한다.

7. 파일 다운로드 관련....
Response.AddHeader "Content-Disposition","attachment;filename=" & Server.URLPathEncode(Realname)
다운로드 이름을 꼭 URL 인코드해야 한글 다운로드가 제대로 인식된다.

MS-SQL
1. nvarchar, nchar, ntext 형 데이터를 사용한다
-> varchar, char, text 형 데이터 사용금지.
2. 만일 커맨더 객체를 사용할 경우 nvarchar, nchar, ntext 형 맞게 수정해야한다.
3. Collate (정렬방식을 Unicode 방식으로 정의한다.)
ex)
CREATE TABLE [dbo].[t_admin](
[adminid] [nvarchar](25) COLLATE Korean_Wansung_Unicode_CI_AS

 

 

* 만약 다국어가 아니라 UTF-8 일 경우에는 마지막 MS-SQL 세팅은 굳이 nvarchar 형을 사용하지 않고 varchar 형을 사용해도 된다.

2010년 7월 21일 수요일

fedora 12 svn 설치

-SVN 설치

# yum install subversion

 

-mod_dav_svn.so 설치

# yum install mod_dav_svn

 

-sqlite 설치

# yum install sqlite

 

-저장소 만들기

# mkdir /svnroot

# cd /svnroot

# svnadmin create --fs-type fsfs svn

# svnserve -d -r /svnroot/svn

 

-svn repository 설정
# cd /svnroot/svn/conf
# vi svnserve.conf --파일을
열어서 #표시가 있는 부분은 모두 제거(authz-db= 제외)


-권한설정

# chmod -R g+w /svnroot/svn
# chown -R apache.apache /svnroot/svn

 

-사용자 아이디와 패스워드 파일 /svnroot/svn/svn-auth-file 생성
# htpasswd -cm /svnroot/svn/svn-auth-file 사용자아이디 -- 최초 생성시.
# htpasswd -m /svnroot/svn/svn-auth-file 사용자아이디 --사용자 추가시.
명령어를 입력하면 패스워드 입력 프롬프트가 발생한다.

 

Apache를 /etc/httpd에 설치했으므로 설정파일은 /etc/httpd/conf/httpd.conf 입니다. dav, dav_svn 모듈이 설정되어 있는지 확인 합니다. 주석처리 되어 있으면 주석을 없애고 없다면 아래 두줄을 추가합니다.

LoadModule dav_module         modules/mod_dav.so
LoadModule dav_svn_module     modules/mod_dav_svn.so
 
- 아파치 연동을 위한 설정
# vi /etc/httpd/conf/httpd.conf

--VirtualHost 부분에 svn 설정내용을 추가한다.
<VirtualHost *:80>
<Location "/svnroot/svn"> --svn 접속경로
  DAV svn
  SVNPath /svnroot/svn
  AuthType Basic AuthName "SVN repository"
  AuthUserFile /svnroot/svn/svn-auth-file
  Require valid-user
</Location>
</VirtualHost>

-서버 재시작

# service httpd restart

-방화벽에서 80포트, 3690포트를 연다.

vi /etc/sysconfig/iptables

-A INPUT -m state --state NEW -m tcp -p tcp --dport 3690 -j ACCEPT

 

# service iptables restart

 

 

 

 

* 방화벽 관련

방화벽 상태 알아보기
/sbin/service iptables status

방화벽 올리고 내리기
/sbin/service iptables stop
/sbin/service iptables start

방화벽 설정 수정하기
vi /etc/sysconfig/iptables

 
※ 주의 사항 ※
selinux 가 실행중이라면 정상작동을 하지 못하는 경우가 있다.
이럴때는 #vi /etc/selinux/config
SELINUX=disabled -> 로 변경해 주거나
[GUI]
프로그램메뉴의 시스템 설정 -> 보안수준 -> SELinux -> 사용안함으로 설정하면 된다.


2010년 6월 24일 목요일

oracle create user example 오라클 데이터베이스 생성

create tablespace ts_test
  logging
  datafile '/home/oracle/oracle/product/10.2.0/oradata/gears/ts_test.dbf'
  size 32m
  autoextend on
  next 32m maxsize 2048m
  extent management local;

 

여기서 SID = gears

-테이블스페이스 생성후

사용자를 매칭

 

되도록이면 테이블 스페이스 명과 사용자명이 1:1로 매칭 되도록하자.

 

CREATE USER 사용자명
IDENTIFIED BY 패스워드
DEFAULT TABLESPACE 테이블스페이스명
TEMPORARY TABLESPACE TEMP
PROFILE DEFAULT
ACCOUNT UNLOCK;

GRANT DBA TO 사용자명;

ALTER USER 사용자명 DEFAULT ROLE ALL;

GRANT CREATE TABLE TO 사용자명;

GRANT UNLIMITED TABLESPACE TO 사용자명;

GRANT CREATE SESSION TO 사용자명;

GRANT CREATE VIEW TO 사용자명;

 

GRANT CREATE PROCEDURE TO 사용자명;

2010년 6월 8일 화요일

MySQL console 명령어

일반적으로 mySQL 같은 경우 /usr/local/mysql 폴더에 설치가 되어있다.

 

데이터베이스 접속

$ mysql -u 사용자명 -p dbname


설치 직후에는 root 사용자에 비밀번호가 없으므로 다음과 같이 접속하여 MySQL을 관리할 수 있다.

$ mysql -u root mysql



비밀번호 변경
MySQL을 설치한 직후에는 root 계정에 암호가 지정되어 있지 않다.
다음 세가지 방법으로 비밀번호를 변경 할 수 있다.


  • mysqladmin이용
    $ mysqladmin -u root password 새비밀번호

  • update문 이용
    $ mysql -u root mysql

    mysql> UPDATE user SET password=password('새비밀번호') WHERE user='root';
    mysql> FLUSH PRIVILEGES;


  • Set Password 이용
    SET PASSWORD FOR root=password('새비밀번호');


일단 root 비밀번호가 설정된 상태에서는 mysql이나 mysqladmin 명령을 실행할 때 -p 옵션을 붙여주고 기존 비밀번호를 입력해야만 한다.

사용자 추가/삭제

mysql> GRANT ALL PRIVILEGES ON dbname.* TO username@localhost IDENTIFIED BY 'password';


username 이라는 사용자를 password라는 비밀번호를 갖도록 하여 추가한다. username은 dbname이라는
데이타베이스에 대해 모든 권한을 가지고 있다.
username 사용자는 로칼 호스트에서만 접속할 수 있다. 다른 호스트에서 접속하려면

GRANT ALL PRIVILEGES ON dbname.* TO username@'%' IDENTIFIED BY 'password';


위를 또한 번 실행한다. '%'에서 홑따옴표를 주의한다.
추가 : '%'를 호스트네임으로 지정해도 모든 호스트에서 접속할 수 없었다. 각 호스트별로 다 지정해야 했다.
아래 댓글에서 rukikuki님이 알려주셨습니다.
GRANT ALL PRIVILEGES ON testdb.* TO 'username'@'%' IDENTIFIED BY 'password' ;
처럼 'username' 이런식으로 홑따옴표를 username 에도 붙여야 하더군요..


불필요한 사용자 삭제는

mysql> DLETE FROM user WHERE user='username';
mysql> FLUSH PRIVILEGES;



데이터베이스 생성/보기


  • 데이터베이스를 생성하고,
    mysql> CREATE DATABASE dbname;

  • 현재 존재하는 데이터베이스 목록을 보여준다.
    mysql> SHOW DATABASES;

  • 특정 데이타베이스를 사용하겠다고 선언한다.
    mysql> USE dbname;

  • 쓸모 없으면 과감히 삭제한다.
    mysql> DROP DATABASE [IF EXISTS] dbname;

    IF EXISTS 옵션은 비록 데이타베이스가 없더라도 오류를 발생시키지 말라는 의미이다.



테이블 생성/보기


  • 테이블을 생성하고,
    mysql> CREATE TABLE tablename (
    column_name1 INT,
    column_name2 VARCHAR(15),
    column_name3 INT );

  • 현재 데이타베이스의 테이블 목록을 보고
    mysql> SHOW TABLES;

  • 테이블 구조를 살펴본다.
    mysql> EXPLAIN tablesname;
    혹은
    mysql> DESCRIBE tablename;

  • 이름을 잘못 지정했으면 이름을 변경할 수도 있다.
    mysql> RENAME TABLE tablename1 TO tablename2[, tablename3 TO tablename4];

  • 필요 없으면 삭제한다.
    mysql> DROP TABLE [IF EXISTS] tablename;



현재 상태 보기


mysql> status

--------------
mysql Ver 11.18 Distrib 3.23.58, for pc-linux (i686)

Connection id: 26
Current database: study
Current user: study@localhost
Current pager: stdout
Using outfile: ''
Server version: 3.23.58
Protocol version: 10
Connection: Localhost via UNIX socket
Client characterset: latin1
Server characterset: euc_kr
UNIX socket: /var/lib/mysql/mysql.sock
Uptime: 2 hours 9 min 59 sec

Threads: 1 Questions: 160 Slow queries: 0 Opens: 28 Flush tables: 1
Open tables: 1 Queries per second avg: 0.021
--------------



INSERT

mysql> INSERT INTO tablename VALUES(값1, 값2, ...);

혹은

mysql> INSERT INTO tablename (col1, col2, ...) VALUES(값1, 값2, ...);



SELECT

mysql> SELECT col1, col2, ... FROM tablename;


컬럼명을 *로 하면 모든 컬럼 의미.

mysql> SELECT col1 AS '성명', col2 AS '국어점수' FROM grade;


컬럼의 이름을 바꿔서 출력.

mysql> SELECT * FROM tablename ORDER BY col1 DESC;
mysql> SELECT col1, korean + math english AS '총점' FROM tablename ORDER BY '총점' ASC;


DESC는 내림차순 ASC는 오름차순.

mysql> SELECT * FROM grade WHERE korean < 90;


조건줘서 SELECT.

mysql> SELECT * FROM grade LIMIT 10;


결과중 처음부터 10개만 가져오기

mysql> SELECT * FROM grade LIMIT 100, 10;


결과중 100번째부터 10개만 가져오기. 첫번째 레코드는 0번 부터 시작한다.

UPDATE

mysql> UPDATE tablename SET col1=새값 WEHER 조건



DELETE

mysql> DELETE FROM tablename WEHRE 조건



mysql에서 쿼리 결과 세로로 보기
-E 옵션을 줘서 실행한다.

$ mysql -E -u root -p mysql



mysql에서 발생한 오류나 경고 다시 보기

mysql> show errors;
mysql> show warnings;