Dec 28, 2010 - PoolLimitSQLException 관련 조치 사항

웹로직에서 PoolLimitSQLException 에러 대응 작업

“PoolLimitSQLException” 오류가 발생하였고, 이유는 웹로직(Weblogic)설정에 Maxinum capacity 가 15로 설정되어있었기 때문으로 추측됩니다.(기본 설정)

접속 Connection 이 많을때는 117까지 Idle이 증가되면서, 해당 오류가 발생된 것으로 파악되면서, 기본형으로 셋팅되었던 몇군대의 문제점이 발견되었습니다.

Home > Summary of Services: JDBC > Summary of JDBC Data Sources > XXX 설정

Test Connections On Reserve 를 Check 합니다. Check 할 경우 120 초 마다 “SELECT 1 FROM DUAL” 을 날려, 성공했을 경우 900초 동안은 검증이 되었다고 판단합니다.

900초는 너무 짧고, 1200 초가 적당하다고 합니다.

또한, 문제가 되었던 Maximum Capacity를 200으로 잡아주었습니다. 그런데 초기 용량이 1 이러다로 증가 수치 또한 1이면 부담이 될 수 있을 거 같습니다.

그 이유는, Monitoring 을 보면, 접속된 connections count 0인데, 가장 높은 count는 52 ~ 117까지 존재하는 걸 확인했고,
만약 초기용량이 1로 증가수치가 1씩 증가할 경우 connections 요청이 많을 경우 문제가 발생할 수 있을 걸로 추정되었습니다.

처음 용량을 5로 잡고 증가 수치 폭 또한 5씩 잡는 게 좋아 보아 같이 수정했습니다.

PS. Diagnostics 에서 Profile Connection Leak를 Check 를 해둬야할 거 같습니다. Monitoring 에서 해당 Leaked Count 를 알 수 있기 때문 있습니다. 이 옵션은 leaked connection이 connection pool에 자동 반환되는 것을 의미하는 것은 아니고, 단순히 로그에 leak정보의 출력을 의미하지만, Monitoring 에는 중요한 정보입니다

Dec 6, 2010 - Client IP 문제(X-Forwarded-For) 해결 방안

L4 에서 IP를 바꿔버리는 문제가 발생했습니다.
스위치를 예전 모델로 교체한다고 하여도 해당문제는 앞 단에 위치하게 되는 Firewall 장비에서 IP Remapping 할 가능성이 존재한다는 답변을 들었습니다.
L4 에서는 IP 를 Remapping 하면서 Client IP 를 아예 없애버리는 게 아니고 X-Forwarded-For 라는 헤더에 남겨 놓는다고 하여 해당 값을 가져다 쓰라고 하였습니다.
(대부분의 Proxy에서 이런 방법으로 IP를 기록한다고 합니다.)

기본적으로는 X-Forwarded-For 정보를 헤더에서 추출하고 그 값이 비어있을 경우 Remote-Addr 헤더로 문제없이 사용이 가능합니다.

참고로 해당 값은 LP VIP 을 통해 들어갈 때만 생기며, 클라이언트에서 보내주는 헤더값이 아니라 L4 VIP 를 통해 들어갈때 L4에서 헤더에 넣어주는 헤더값을 의미합니다.

자바내의 처리로직 :

    HttpServletRequest request

    String ip = request.getHeader("HTTP_X_FORWARDED_FOR");

    if(ip == null || ip.length() == 0 || ip.toLowerCase().equals("unknown"))
        ip = request.getHeader("REMOTE_ADDR");

    if(ip == null || ip.length() == 0 || ip.toLowerCase().equals("unknown"))
        ip = request.getRemoteAddr();

아래는 해외 문서를 참고한 내용입니다.

Getting The Real IP Of Your Users

There are a lot of sites around the internet that try and get your IP address. Most of their reasons are legitimate. For example Google Adsense will log your IP to see where the user clicking the advert is from (and kick you off if its the same IP you logged into that account with).

However, there are some sites that try to look at your IP for various reasons but do it wrong. Rapidshare is a beatifully painful example of this. If you’re on an ISP that uses a transparent proxy, RapidShare will log the proxy address instead of the actual account IP. As they limit the downloading on a per-IP basis, that means everyone using that ISP, going through that proxy, has the same IP to Rapidshare, meaning the limit to how much you download is split among those users.

What I’m saying here is, if you’re going to do your own IP lookups for whatever reason, do them correctly. My initial code here was in VB.net but since I have translated what its doing to the most popular server-side languages. As its based on the server variables, rather than the code’s process, its quite easy to port to something else if you need to.

The lookup that these “incorrect” sites are doing is something like this:

Request.ServerVariables("REMOTE_ADDR")
What then need to be doing is comparing the HTTP_X_FORWARDED_FOR variable against it, to check that there isn’t a non-transparent proxy in the way. Like so:

' Look for a proxy address firstDim _ip As String = Request.ServerVariables("HTTP_X_FORWARDED_FOR")' If there is no proxy, get the standard remote addressIf (_ip = "" Or _ip.ToLower = "unknown") Then _ _ip = Request.ServerVariables("REMOTE_ADDR")
This doesnt help people that are limited to (or otherwise) on anonymous proxies. They will hide the forwarding address (like they’re supposed to) and therefore the lookup will ONLY get the proxy’s address. Some ISPs do this by default to “protect” their users… Its just retarded. If you ISP does this, and you’ve been wondering why RS or other sites don’t work… Now you know.

If you want to check against an existing “wrong site”, try IP Chicken. It will return an incorrect value (eg the proxy). WhatsMyIP.orgis one that will look through the proxy and should give you the correct IP.

Here are some more examples in other languages:

C# —

// Look for a proxy address firstString
_ip = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
// If there is no proxy, get the standard remote address
If (_ip == "" || _ip.ToLower == "unknown")
_ip = Request.ServerVariables["REMOTE_ADDR"];

C# —

// Look for a proxy address firstString
_ip = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
// If there is no proxy, get the standard remote address
If (_ip == "" || _ip.ToLower == "unknown")
_ip = Request.ServerVariables["REMOTE_ADDR"];

PHP — Based on code from OxyScripts.

function GetUserIP() {
if (isset($_SERVER)) {
if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]))
return $_SERVER["HTTP_X_FORWARDED_FOR"];
if (isset($_SERVER["HTTP_CLIENT_IP"]))
return $_SERVER["HTTP_CLIENT_IP"];
return $_SERVER["REMOTE_ADDR"]; }
if (getenv('HTTP_X_FORWARDED_FOR'))
return getenv('HTTP_X_FORWARDED_FOR');
if (getenv('HTTP_CLIENT_IP'))
return getenv('HTTP_CLIENT_IP');
return getenv('REMOTE_ADDR');}

Java and JSP —

String ipaddress = request.getHeader("HTTP_X_FORWARDED_FOR");
if (ipaddress == null)
ipaddress = request.getRemoteAddr();

ASP/VBScript —

ipaddress = Request.ServerVariables("HTTP_X_FORWARDED_FOR")
if ipaddress = ""
then
ipaddress = Request.ServerVariables("REMOTE_ADDR"
)end if

ColdFusion

<CFCOMPONENT>
<CFIF #CGI.HTTP_X_Forwarded_For# EQ "">
<CFSET ipaddress="#CGI.Remote_Addr#">
<CFELSE>
<CFSET ipaddress="#CGI.HTTP_X_Forwarded_For#">
</CFIF>
</CFCOMPONENT>

Perl —

$ip = $req->header('Client-IP') || $req->header('Remote-Addr');
if ($req->header('X-Forwarded-For'))
{ $proxy = $ip; $ip = $req->header('X-Forwarded-For');}

If you know anymore, just ping them in my general direction and they can be added.

C# 계열은 정상 동작했는데, 우리쪽에서는 헤더정보를 읽어오지 못했습니다. 이유는 웹로직에서 포워딩할때 변경하는게 아닌가 추측됩니다. 모든 헤더 정보를 찍어보니 해당 헤더이름은 “X-Forwarded-For”(HTTP-X-FOWARDED-FOR) 로 변환해서 들어오는 것을 확인했습니다.

그것은 IIS 설정에서 X-Forwarded-For 를 IP로 잡는 겁니다. 인터넷에서 F5XForwardedFor 로 검색하면 상세한 정보를 알 수 있습니다.


# 참조 —–

Dec 3, 2010 - vi 편집기 사용하기

vi는 리눅스를 비롯한 유닉스 계열 운영체제에서 많이 사용되는 텍스트 파일 편집 프로그램입니다.

‘#which vi’ 이라 명령어를 입력하면 vim 프로그램의 위치를 나타냅니다.
보통 vi 편집기는 alias 되어 있어 vi 명령어만 입력하면 텍스트 파일을 열어 편집할 수 있습니다.
vi 은 3가지 상태 모드가 있습니다.

  1. 명령 상태
    명령어를 입력하는 상태입니다. 내용을 검색하거나 이동할 때 사용하는 명령어 입력 상태입니다.
  2. 입력 상태
    텍스트 파일의 내용을 입력할 수 있는 상태입니다. 텍스트 파일을 수정할 수 있는 상태입니다.
  3. ex 상태
    파일 관련 처리 명령에 사용되며 명령 상태에서 ‘:’ 문자를 입력하면 ex 상태가 됩니다.

명령 상태는 vi 편집기를 실행하면 명령 상태로 실행됩니다. 어떤 상태이든 esc 버튼을 누르면 명령 상태로 돌아갑니다. 아래의 화면은 명령 상태로 vi 편집기가 실행된 화면입니다.

명령 상태의 키는 다음과 같습니다.

h,j,k,l : 왼쪽,아래쪽, 위쪽, 오른족으로 한 칸씩 이동합니다.
$ : 그 줄의 가장 마지막으로 이동합니다.
^ : 그 줄의 가장 처음으로 이동합니다.
H : 화면의 가장 위로 이동합니다.
L : 화면에 가장 아래로 이동합니다.
gg : 파일의 가장 처음으로 이동합니다.
G : 파일의 가장 마지막으로 이동합니다.
} : 다음 단락으로 이동합니다.
{ : 이전 단락으로 이동합니다.
:n : n 번째 줄로 이동합니다.  

명령 상태에서 텍스트 파일의 커서가 위치하는 곳에 텍스트 파일을 수정하기 위해서는 입력상태로 변경해야 합니다. 이 때 사용하는 키는 다음과 같습니다.

  • 입력 명령
i : 현재 커서가 위치한 곳부터 글자를 입력합니다.
I : 현재 작업 줄의 가장 처음에 글자를 입력합니다.
a: 현재 커서가 위치한 다음 칸부터 글자를 입력합니다.
A : 현재 작업 줄의 가장 마지막에 글자를 입력합니다.
  • 삭제 명령
x : 현재 커서가 위치한 곳에 글자 삭제
dw : 한 단어를 삭제
dd : 줄 전체를 삭제
d$ : 현재 커서가 위치한 곳부터 그 줄의 가장 마지막까지 삭제

  • 복제 및 붙이기 명령
yy : 현재 줄 전체를 메모리에 저장해 둡니다.
y0 : 현재 커서가 위치한 곳부터 그 줄의 가장 처음까지 메모리에 저장합니다.
y$ : 현재 커서가 위치한 곳부터 그 줄의 가장 마지막까지 메모리에 저장합니다.
p : 현재 커서가 위치한 곳에서 메모리의 내용을 붙여 넣습니다.
P : 현재 커서가 위치한 바로 다음 칸에 메모리의 내용을 붙여넣습니다.

참고로 v 키를 누른 후 이동 명령으로 커서를 이동하면 선택된 블록 영역이 반전된 색깔로 표시되며 영역이 선택됩니다.

dd 삭제 명령과 i G, gg 정도만 알면, 어느정도 vi 편집하는데 불편함은 업습니다.