[Linux] Proxy 서버 설정하기

Published on: 2013. 11. 25. 19:20 by louis.dev

서버중 외부로 나가는 트래픽이 막혀있는 서버가 있다면 프록시를 통해 외부로 나가는 요청을 할수가 있습니다.


1. 로그인 세션 동안만 유지되는 방법

텔넷이나 ssh에 로그인 되어있는동안만 프록시를 사용하고 있다면 다음과 같이 사용하면 됩니다.

# 프록시 서버 설정
$ export http_proxy=http://www.yourproxyserver.com:port
$ export https_proxy=http://www.yourproxyserver.com:port
#프록시서버 해제
$ unset http_proxy
$ unset https_proxy

2. 로그인 세션이 종료된 후에도 프록시를 유지시키는 방법

# 여기서는 .bashrc에 작업했지만 .profile, .bash_profile, .bashrc_profile 어디에 설정해도 동일합니다.
$ vi ~/.bashrc

#아래내용 추가
export http_proxy=http://www.yourproxyserver.com:port
export https_proxy=http://www.yourproxyserver.com:port
# 저장후

$source ~/.bashrc

이후 wget이나 curl로 외부로 요청이 되었을때 데이터를 제대로 가져오면 프록시 설정이 제대로 된것입니다.

$ wget www.daum.net
#혹은
$ curl -0 www.daum.net

[Redis-Jedis] Pipeline을 이용한 다량의 데이터 Insert하기

Published on: 2013. 11. 19. 21:10 by louis.dev

대량의 데이터를 레디스에 저장해야 할때는 Pipeline을 이용하면 단순히 set command보다 월등한 성능을 보장받을 수 있습니다.


사용은 간단합니다.

@Autowired protected ShardedJedisPool redisPool;
public void setByPipeline(Map<string, string> map) {
	ShardedJedis jedis = null;
	try {
		jedis = redisPool.getResource();
		ShardedJedisPipeline pipeline =  jedis.pipelined();
		
		for(String key : map.keySet()) {
			
			pipeline.set(key, map.get(key));
		}
		pipeline.sync();
	} catch (JedisConnectionException e) {
		if (jedis != null) redisPool.returnBrokenResource(jedis); // 접속이 끊긴 리소스 반환
	} finally {
		if (jedis != null) redisPool.returnResource(jedis);
	}
}

pipeline에 삽입하고자 하는 데이터를 set을 먼저해줍니다. 이때 set커맨드는 실제로 데이터를 서버로 전송하지 않고 12번째 줄인 pipeline.sync()를 콜한후에 실제 데이터를 서버로 전송하여 저장하게 됩니다.


파이프라인 방식은 명령어 자체를 파일로 쓴후 해당 파일을 레디스 서버로 전송하여 대용량 삽입을 빠르게 할수 있게 합니다.


테스트 결과 단순 데이터 5000건을 set 해봤더니 약 200ms 정도 걸리네요~

[Redis-Jedis] Spring을 이용한 샤드(Shard) 설정

Published on: 2013. 11. 19. 20:55 by louis.dev

업무에 Redis를 이용할 기회가 있어서 설정 내용을 포스팅해봅니다. Redis의 Java 라이브러리인 Jedis와 Spring FrameWork를 통해서 세팅해보겠습니다.


Spring에서는 spring-data라는 프로젝트를 통해 각종 Database, NoSQL의 사용을 스프링프레임워크를 기반으로한 프로젝트에서 쉽게 사용할수있도록 라이브러리를 제공하고 있습니다.


물론 Redis도 spring-data-redis라는 이름으로 제공하고 있습니다. 그런데 spring-data-redis 프로젝트가 시작된지 얼마 안되서 그런지(현재 안정화 버전은 1.1.0) 샤딩을 지원하고 있지 않습니다.


여기서 샤딩이란 간단하게 말하자면 여러대의 레디스 서버에 데이터를 분산하여 저장하는 것을 의미합니다. 

Redis는 데이터를 메모리에 올려놓는 In Memory 방식이기 때문에 SSD나 HDD에 저장하는 기존의 DB들 보다 저장공간이 부족합니다(하드디스크는 테라단위로 설치하긴 쉽지만 램은 하드디스크 보다 용량 확장이 쉽지 않기 때문입니다).

따라서 레디스 서버 한대로 서비스를 시작한 후에 데이터량이 점점 증가하여 메모리 용량이 모자르게 되면 서버를 추가하여 데이터를 해당 서버 수만큼 쪼개어 저장할수 있는데 이것을 샤딩이라고 합니다.


아무튼 spring-data-redis는 Sharding을 지원해 주지 않기 때문에 Jedis를 이용하여 직접 샤드 설정을 해야합니다.


샤드 설정은 생각보다 간단합니다.


1. Jedis를 다운받은 후 프로젝트에 라이브러리를 추가합니다.

2. xml에 다음과 같이 bean을 등록합니다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:c="http://www.springframework.org/schema/c"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
    
	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig" p:maxActive="500" p:maxIdle="300" p:maxWait="10000" p:testOnBorrow="true" />
	<util:list id="jedisShardInfos">
		<bean class="redis.clients.jedis.JedisShardInfo" c:host="${redis1.host.name}" c:port="${redis.port}" c:timeout="10000" c:weight="1" />
		<bean class="redis.clients.jedis.JedisShardInfo" c:host="${redis2.host.name}" c:port="${redis.port}" c:timeout="10000" c:weight="1" />
	</util:list>
	<!-- 해쉬 알고리즘 MURMUR와 MD5가 있음 -->
	<util:constant id="jedisAlgo" static-field="redis.clients.util.Hashing.MURMUR_HASH" />
	<util:constant id="jedisKeyTagPattern" static-field="redis.clients.util.Sharded.DEFAULT_KEY_TAG_PATTERN" />
	<bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool" c:poolConfig-ref="jedisPoolConfig" c:shards-ref="jedisShardInfos" c:algo-ref="jedisAlgo" c:keyTagPattern-ref="jedisKeyTagPattern" destroy-method="destroy" />	
</beans>

3. Jedis를 이용해 실제 Redis Command를 수행할 Template Class를 생성합니다.

package net.krespo.template;

import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPipeline;
import redis.clients.jedis.ShardedJedisPool;
import redis.clients.jedis.exceptions.JedisConnectionException;

@Component
public class RedisCacheTemplate {
	
	@Autowired protected ShardedJedisPool redisPool;
	public void set(String key, String value) {
		ShardedJedis jedis = null;
		try {
		    jedis = redisPool.getResource();
		    jedis.set(key,value)
		} catch (JedisConnectionException e) {
			if (jedis != null) redisPool.returnBrokenResource(jedis); // 접속이 끊긴 리소스 반환
		} finally {
		    if (jedis != null) redisPool.returnResource(jedis);
		}
	}
}

위의 코드에서 눈여겨 볼부분은 24번째 줄입니다. 

JedisConnectionException이 발생하면 redisPool의 returnBrokenResource를 호출하고 있는데요. 

샤딩을 구성하는 여러대의 서버중 한대가 장애가 발생하면, 커넥션 풀에는 장애나기 전 서버와의 커넥션이 그대로 존재하게 됩니다. 따라서 어플리케이션에서 커넥션풀에서 커넥션을 꺼내올것을 요청했을때(redisPool.getResource) 장애가 발생한 서버의 커넥션을 리턴해주고, 해당커넥션으로 레디스 커맨드를 실행하려고 하면 JedisConnectionException이 발생하게 됩니다. 따라서 해당 익셉션 발생시 풀에서 해당 커넥션을 제거해주는 작업을 해주기 위함입니다.


RedisCacheTemplate 클래스는 간단하게 jedis를 이용한 set메소드를 구현하였습니다. 위와 같이 Template 클래스를 만든 이유는 레디스 커맨드를 사용하기 전에 항상

  1. 커넥션 풀에서 커넥션 획득
  2. 커맨드 실행후 해당 커넥션 반환

의 작업을 항상 해주어야 하는데요. 이 번거러운 작업을 미리 작업해 두고 다른 persistance 레이어의 클래스에서는 해당 Template 클래스를 주입시켜 사용만 하면 되기 때문입니다.

ShardedJedis jedis = null;
try {
	jedis = redisPool.getResource();
	//레디스 커맨드 실행
} catch (JedisConnectionException e) {
	if (jedis != null) redisPool.returnBrokenResource(jedis); // 접속이 끊긴 리소스 반환
} finally {
	if (jedis != null) redisPool.returnResource(jedis);
}

위의 예제에서는 set메소드만 구현하였지만 상황에 따라 필요한 메소드를 구현하면 됩니다. 

그리고 redisPool.getResource와 redisPool.returnResource 같은 부분이 계속나와 신경쓰이신다면 AOP로 빼서 한꺼번에 적용하셔도 좋을것 같네요~


이상 스프링기반의 프로젝트에서 Jedis를 이용한 샤딩 설정을 마치겠습니다

[Mac] Mountain Lion에 webdav 설정하기

Published on: 2013. 11. 14. 16:37 by louis.dev
맥미니에 저장되어있는 파일을 공유하는 방법은 여러가지가 있으나 그중에 http를 통해서 파일을 다운로드 하거나, 넷드라이브로 인식하여 쉽게 읽고 쓰기가 가능하도록 하는 기능인 webdav 설정방법에 대해서 알아보도록 하겠습니다. webdav의 설정은 크게
  1. 보안이 적용되지 않은 가장 단순한 형태의 webdav
  2. 보안이 적용된 webdav
로 나눌수 있는데, 첫번째 방식인 경우 설정하기는 쉽지만 패킷캡쳐에 따른 내용분석이 가능하다는 점이 단점이고, 두번째 방법은 강력한 보안을 제공하지만 설정하기 까다롭다는 단점이 있습니다. 이번 포스팅에서는 두가지 모두를 세팅하는 방법을 다루어 보도록 하겠습니다.  

0. 공통작업

아파치 설정파일인 httpd.conf에 주석처리되었던 부분을 주석해제 합니다.
$ sudo vi /etc/apache2/httpd.conf

#해당부분을 주석해제
Include /private/etc/apache2/extra/httpd-dav.conf

# 저장후 쉘로 나온 뒤

## DavLock파일은 여러 사용자가 한파일을 읽고 쓰기를 동시에 하지 못하도록 관리하는 파일
$ sudo mkdir /usr/var
$ sudo chmod 777 /usr/var
$ sudo touch /usr/var/DavLock
# /usr/var 디렉토리의 소유자를 아파치의 사용자:그룹(httpd.conf 파일에 User, Group으로 명시되어 있는 사용자 그룹) 으로 설정함
# /usr/var 하위에 DavLock 파일 뿐만 아니라 다른 파일도 자동으로 생성되기 때문에 /usr/var 디렉토리의 사용자:그룹을 변경해야함
$ sudo chown -R ${apache User}:${apache Group} /usr/var

1. 보안이 적용되지 않은 가장 단순한 형태의 webdav 설정

$ sudo vi /etc/apache2/extra/httpd-dav.conf

## 아래 내용을 httpd-dav.conf에 추가

DavLockDB "/usr/var/DavLock"

# 공유하고자 하는 디렉토리 명, 접근은 http://your.domain.com/webdav 로 접근 가능
Alias /webdav "/your/directory/name"

#위의 Alias 부분의 디렉토리 위치와 동일해야 함
<Directory "/your/directory/name">
    Dav On
    Order allow,deny
    Allow from all
    AuthType Basic      #가장 기본적인 형태의 인증
    AuthName DAV      #webdav 인증 창에 나타날 메세지
    AuthUserFile /etc/apache2/mydavuser.passwd     #로그인을 허용할 사용자를 저장하고 있는 파일, 아직 생성하지 않았음
    <Limit GET PUT POST DELETE PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK>
        require user ${mydavuser.passwd에 추가한 사용자 명}
    </Limit>
    Options FollowSymLinks Indexes
</Directory>

# 기본적으로 설정된 부분
BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully
BrowserMatch "MS FrontPage" redirect-carefully
BrowserMatch "^WebDrive" redirect-carefully
BrowserMatch "^WebDAVFS/1.[0123]" redirect-carefully
BrowserMatch "^gnome-vfs/1.0" redirect-carefully
BrowserMatch "^XML Spy" redirect-carefully
BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully

# httpd-dav.conf 파일을 저장하고 나옴

# webdav에 접근 가능한 사용자 리스트를 저장할 파일로 만든다.
# 아래에서 입력한 사용자명은 위의 httpd-dav.conf 에 require user 뒷부분에 들어갈 유저명이다
# -c 옵션은 파일을 새로 생성하는 옵션이다. 만약 존재하는 파일에 사용자를 추가하려면 이 -c 옵션을 제거 하고 하면 사용자를 추가할수 있다.
$ sudo htpasswd -c /etc/apache2/mydavuser.passwd ${로그인할 사용자 명}
New password:
Re-type new password:
Adding password for user ${로그인할 사용자 명}

## 아파치 설정이 이상없는지 확인한 뒤 아파치를 재시작 한다.
$ sudo apachectl -t
#위의 명령이 문제 없으면
$ sudo apachectl graceful
이제 브라우저로 http://your.ipORdomain.com/webdav로 접근하여 로그인이 되는지를 확인합니다. 위의 방법은 설정이 간단하다는 장점이 있지만 Windows 시스템에서 보안설정이 되어있지 않은 방식으로는 바로 네트워크 드라이브로 설정할 수가 없습니다. 따라서 위와 같이 설정한다음 windows에서도 네트워크 드라이브로 잡으려면 이 포스팅을 확인하시면 됩니다.  

2. 보안이 적용된 webdav 설정

ssl을 적용한 webdav는 여기에서 확인 할 수 있습니다

[Mac]mod_jk를 이용하여 apache와 tomcat 연결하기

Published on: 2013. 11. 14. 16:37 by louis.dev
tomcat을 실행시키기 위해서는 JRE(Java Runtime Environment)가 필요합니다. JRE를 설치하는 방법은 Oracle에서 JRE를 다운받아 설치하는 방법도 있지만 맥에서는 쉽게 다운로드 받아 설치할수 있습니다.

1. JRE설치

먼저 터미널을 실행시킨 후
$ java -version
을 실행시켰을 경우 현재 JRE가 설치되어 있다면
java version "1.6.0_51"
Java(TM) SE Runtime Environment (build 1.6.0_51-b11-457-11M4509)
Java HotSpot(TM) 64-Bit Server VM (build 20.51-b01-457, mixed mode)
위와 같이 현재 맥에 설치된 JRE의 버전이 출력될것입니다. 만약 자바가 설치되어 있지 않으면 이렇게 얼럿창이 뜨면서 JRE를 설치하도록 유도하고 있습니다. 여기서 설치를 누르면 손쉽게 JRE를 설치할 수 있습니다.  

2. Tomcat 설치

Tomcat은 따로 설치할 필요가 없습니다. 여기에서 tomcat의 압축파일을 다운로드 받은 후 적당한 곳에 압축을 풀어 놓음으로서 설치는 끝나게 됩니다. 혹은 아래 명령어를 터미널에 입력함으로서 쉽게 다운로드 받을 수 있습니다.
$ curl -O http://mirror.apache-kr.org/tomcat/tomcat-7/v7.0.42/bin/apache-tomcat-7.0.42.tar.gz
$ tar xzvf apache-tomcat-7.0.42.tar.gz
$ mv apache-tomcat-7.0.42 ${적당한디렉토리}
#톰켓 실행방법
$ 톰켓설치디렉토리/bin/startup.sh
#톰켓 종료방법
$ 톰켓설치디렉토리/bin/shutdown.sh

3. JK Connector 컴파일 설치

톰켓 홈페이지에서 JK Connector Source 압축파일을 다운로드 하거나 여기를 눌러 직접 다운로드 하시면 됩니다.
$  curl -O http://apache.mirror.cdnetworks.com//tomcat/tomcat-connectors/jk/tomcat-connectors-1.2.37-src.tar.gz
$ tar zxf tomcat-connectors-1.2.37-src.tar.gz
$ cd ./tomcat-connectors-1.2.37-src/native
$  ./configure --with-apxs=/usr/sbin/apxs

#설치시 
# checking for gcc... /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.8.xctoolchain/usr/bin/cc
# checking for C compiler default output file name... configure: error: C compiler cannot create executables
# See `config.log' for more details.
# 라는 에러가 발생하면 아래의 명령어를 입력합니다.
$ sudo ln -s /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.8.xctoolchain

$ make
$ sudo make install
위와 같은 명령어로 컴파일을 완료하면 /usr/libexec/apache2/mod_jk.so가 생성됩니다. 생성된 모듈을 활성화 하고 설정을 합니다.
$ sudo vi /etc/apache2/httpd.conf

# httpd.conf에 아래내용 추가
LoadModule jk_module libexec/apache2/mod_jk.so

<IfModule jk_module>
    JkWorkersFile /etc/apache2/workers.properties
    JkLogFile     ${로그파일위치}/mod_jk.log
    JkLogLevel    info
    JkMountFile   /etc/apache2/uriworkermap.properties
</IfModule>

$ sudo vi /etc/apache2/workers.properties

worker.list=worker1
worker.worker1.port=8009
worker.worker1.host=localhost
worker.worker1.type=ajp13
worker.worker1.lbfactor=1

$ sudo vi /etc/apache2/uriworkermap.properties
/*.jsp=worker1
/*.krespo=worker1

#만약 context로 설정을 하고자 한다면 /contextName/*=worker1 으로 설정합니다.

$ sudo apachectl -t   #설정파일 테스트
$ sudo apachectl graceful #graceful로 아파치 재시작

4. tomcat 설정 및 테스트용 context 설정

$ vi ${톰켓 홈 디렉토리}/conf/server.xml
# &lt;Connector&gt; 태그의 속성으로 URIEncoding=&quot;UTF-8&quot;을 추가합니다.
# 이렇게 설정해야지 parameter로 한글을 전송할때 파라미터가 깨지지 않습니다.
<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
               URIEncoding="UTF-8"/>

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8" />

$ vi ${톰켓 홈 디렉토리}/conf/Catalina/localhost/ROOT.xml

# path = localhost:8080/test
# docBase = 아파치의 documentRoot
<Context path="/" docBase="/data/service/tomcat" reloadable="false" privileged="true" antiResourceLocking="false" antiJARLocking="false"  allowLinking="true">
</Context>

# 저장후 서버 재시작
이상으로 mod_jk 설정을 완료하였습니다.