자바 기초 (03) Too many connection error & Singleton Pattern
JAVA Singleton Pattern
Too many connection error??
최근 sync 작업 Quartz작업을 수행도중 Too many connection 에러를 만나게 되었다.
too many connections 에러의 경우 mysql에 연결된 클라이언트의 수가 일정수치 이상인 경우 나타나는 에러메세지이다. 일반적인 해결 방법으로는 mysql 설정을 변경하면된다.
현재 mysql connection을 확인하는 방법중 하나는 윈도우 cmd에 아래 명령어를 입력하여
netstat -ano | findstr #{mysql포트}
아래 커맨드를 통하여 현재 mysql에 연결할수 있는 최대 클라이언트 갯수를 확인한다.
mysql> show variables like '%max_connect%';
그후 아래의 커맨드로 mysql 설정을 변경한다.
mysql> set global max_connections=500;
mysql> set wait_timeout=60;
일단은 위방법으로 당장의 문제는 잠시 해결할 순 있겠지만, 일정 시간마다 계속 동기화를 하는 내 프로젝트에선 확실한 문제를 찾고 해결할 수 밖에 없었다. 왜 계속해서 connect연결이 늘어날까를 확인하던 도중 어떤 service 객체내에서 Dao인스턴스를 생성자를 통해 계속 만들고 있는것을 확인하였다. 메모리 관리 측면에서 Singleton의 중요성은 들어봤지만, 난 조금 다른 이유로 이글을 쓴다.
싱글턴 패턴
싱글턴을 구현하는 방법은 여러가지가 있다. 자바의 싱글턴과 스프링의 싱글턴이 다르고, 조금씩 다르게 만들수도 있을것이다. (Eagger Initialization방식 Lazy Initialization with synchronized 방법등) 여기서는 java Singleton을 내가 사용하는 방법(Lazy Initialization with synchronized) 대로 적어보려한다.
일단 SIngleton Pattern을 사용하는 일반적인 이유에 대해 먼저 알아보자
- 고정된 메모리 영역을 사용하도록 단 한번 new연산자로 인스턴스를 얻어오기 때문에 메모리를 아낄수 있다.
- 전역변수로 선언되고 전역메서드로 호출하기 때문에 다른 클래스에서 사용하기가 쉽다.
- 공통된 객체를 사용해야 하는 코딩에서 매번 객체를 생성하지 않고 같은 객체를 사용하도록 하면 성능 면에서 좋아진다.
먼저 코드들을 먼저 적고 그다음 설명을 하도록 하겠다.
package singleton;
class Singleton
{
private static Singleton single_instance = null;
public String s;
private Singleton()
{
s = "Hello I am a string part of Singleton class";
}
public static Singleton getInstance()
{
if (single_instance == null)
single_instance = new Singleton();
return single_instance;
}
}
나는 보통 싱글턴을 통하여 인스턴스를 생성할때 ## Lazy Initialization with synchronized을 많이 사용한다. 이는 컴파일 시점에서 인스턴스를 생성하는것이 아닌, 인스턴스가 필요한 시점에 요청하여 동적 바인딩을 통해 인스턴스를 생성하는 방식을 말한다.
싱글턴 패턴에선 다른 class에서 new연산자로 객체를 만드는것을 방지하기위해 private 를 사용하여 선언한다.
private Singleton singleton = new Singleton(); // 이방법으론 호출할수 없다.
그러면 어떻게 Singleton Pattern을 사용할 수 있을까? 아래 Main class를 보자.
package singleton;
class NormalClass {
public Normal() {
System.out.println("Normal Instance Created..");
}
}
public class Main {
public static void main(String[] args) {
NormalClass normalClass1 = new NormalClass();
NormalClass normalClass2 = new NormalClass();
Singleton singleton1 = Singleton.getInstance();
Singleton singleton2 = Singleton.getInstance();
}
}
위와같이 인스턴스를 사용할수 있다. 그럼 SIngleton 으로 생성된 인스턴스와 일반적인 인스턴스의 차이를 알아보자.
== 메서드는 참조 주소를 확인한다고 배웠다. 이걸통해 각 인스턴스를 비교해보자
System.out.println(normalClass1 == normalClass2); //false
System.out.println(singleton1 == singleton2); //true
위 결과를 통하여 싱글톤 패턴을 사용하여 만든 객체는 서로 같다 라는것을 확인했다.
싱글턴 패턴에 대해 좀더 알고 싶다면 아래에서 포스트를 확인하길 바란다. 또한 Spring통한 Singleton 사용법은 다음 포스트에 바로 다뤄보도록 하겠다. + (스프링에서 위의 sql connect 설정을 변경하는 방법)