RSS구독하기:SUBSCRIBE TO RSS FEED
즐겨찾기추가:ADD FAVORITE
글쓰기:POST
관리자:ADMINISTRATOR

셋방살이 중인 서버의 대 격변(?) 에 발 맞춰서
기존의 Apache + mod_php 와 낮은 버전의 MySQL 로 인하여 이래저레 못해왔던 것들을 던져 버리고

신흥 문물(?) 들을 받아들여 보고자 하였는데.

설치 환경은 아래와 같다.

  • CentOS 6.x ( x86_64 )
    • MySQL 5.5.x
    • PHP 5.3.x
      • APC
      • PHP-FPM
    • Nginx 1.4.x
    • Memcached 1.4.x

오랜 숙원 사업이였던 탈 i686 의 꿈을 이루고 이것저것 삽질을 시작 하였는데.

여기서 설치와 관련된 내용은 모두 Yum 을 이용하여 설치를 하였다.
다음 Yum repository 를 추가 해주면 간단히 해결 됨.

이때 각 Yum Repository 마다 동일한 패키지 명의 중복으로 피곤해지는 일들이 발생 된다면
yum-plugin-priorities 을 설치하시면 Repo 별로 우선순위를 지정해서 처리가 가능하니 깔끔하게 해결!


이렇게 모든 패키지가 설치가 완료가 된다면.

PHP-FPM + Nginx 가 원활하게 구동 할 수 있도록 설정을 해줘야 하는데.

/etc/nginx/nginx.conf

location ~ \.php$
{
    fastcgi_send_timeout  5m;
    fastcgi_read_timeout 5m;
    fastcgi_connect_timeout 5m;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}


여기에 Textcube 를 위한 URL redirection 을 추가 한다.
( c.f /documents/setup_nginx.txt 을 참조하시길 바란다 )

location /tc/  {
    set $rewrite_base '/tc';
    if (!-f $request_filename) {
            rewrite ^(thumbnail)/([0-9]+/.+)$ cache/$1/$2;
    }
    if ($request_filename ~* ^(cache)+/+(.+[^/])\.(cache|xml|txt|log)$) {
            return 403;
    }
    if (-d $request_filename) {
            rewrite ^(.+[^/])$ $1/;
    }
    rewrite  ^(.*)$ $rewrite_base/rewrite.php last;
}


/etc/php-fpm.d/www.conf

[www]

listen = 127.0.0.1:9000

listen.backlog = -1
listen.allowed_clients = 127.0.0.1

user = nginx
group = nginx

pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
request_terminate_timeout = 120s
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/www-slow.log
security.limit_extensions = .php .php3 .php4 .php5 .html
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on

/etc/php.d/memcache.ini
extension=memcache.so
memcache.default_port=11211

memcache.hash_function=crc32
memcache.hash_strategy=consistent
memcache.protocol=ascii
session.save_handler=memcache

session.save_path="tcp://127.0.0.1:11211?persistent=1&weight=1&timeout=1&retry_interval=15"



일단은 여기까지 설정을 마치고 PHP 가 정상적으로 구동되는지 확인을 한다.

정상적으로 동작을 한다면

Textcube 안정버전인 1.8.6 을 다운로드 받아서 설치를 하게 되는데
MySQL 5.5+ 에서의 호환 성을 위해 설치 전 미리 몇 가지 손을 좀 봐야 할 필요가 있다.

setup.php 의 1132 line. 의 TALBE 생성 시 'TYPE' 을 'ENGINE' 으로 바꿔 줘야 한다.
- $charset = 'TYPE=MyISAM DEFAULT CHARSET=utf8';
+ $charset = 'ENGINE=InnoDB DEFAULT CHARSET=utf8';


그리고 Textcube 를 설치를 진행 한다.

이때 Rewrite 관련 설정에 에러가 나는데 옵션을 끄고 진행 하더라도 무방하다.

여기까지는 Textcube 에서 제공하는 setup_nginx.txt 를 참조 하시면 좀 더 친절하게 안내 받을 수 있다.

여기서 한가지 고비가 오는데
Textcube 1.8.6 에서 PHP-APC 가 활성화 된 환경에서 Login 이 불가능하고 502 Error 를 뱉고
진행이 불가한 상황이 벌어지는데

PHP::Session class 와 session_write_close() 사이에 어떤 문제가 APC 모듈과 비 정상적인 동작을
일으켜서 생기는 문제라고 하는데

이때 PHP-APC 를 삭제 하거나 disable 하시면 되지만
왠지 아깝지 않은가? Textcube 때문에 APC 를 쓸 수가 없다니!!!!

이럴때 Texcube 가 설치된 디렉토리 아래의
./library/preprocessor.php 의 152번 째 줄 즈음에 다음 코드를 추가 한다.

+ register_shutdown_function("session_write_close");


이후엔 정상적으로 로그인이 가능해질 것이다.

Textcube 에 로그인 후 Memcache 를 활성화 시키기 위해서
"텍스트 큐브 관리" 메뉴로 이동한 뒤 "서비스 관리 > 서버" 메뉴에 진입을 한 뒤
"Memcached 사용" 메뉴에 Checkbox 에 Check 한 뒤 저장을 하게 된다면

보다 빠릿빠릿한 블로그를 이용 할 수 있게 된다.
2013/08/04 18:07 2013/08/04 18:07
이 글에는 트랙백을 보낼 수 없습니다
[로그인][오픈아이디란?]
오픈아이디로만 댓글을 남길 수 있습니다
항상 Root 권한을 가지고 있다가...
막상 없을려니까 뭐 하나 설치하려면 이래저레 귀찮이즘을 겪게된다....

Node.js 삽질을 다시 할려고 하니 ...
설치 해놓은게 0.62...3개월이면 강산도 변한다는 세상인데
v0.81 이 릴리즈 된 이 시점에 살포시 업글 및 npm 을 쓰기 위해서 .... 삽질을 시작.

설치는 아래 링크를 참조하라!

Node.js HOWTO: Install Node+NPM as user (not root) under Unix OSes

http://tnovelli.net/blog/blog.2011-08-27.node-npm-user-install.html


간략하게 요약하자면.
임의의 디렉토리(예제에선 $HOME/.local/ 이 되겠다 ) 에 Node.js 를 설치하고
.npmrc 에 root/binroot/manroot 의 PATH 를 잡아준다.

root =    /home/YOUR-USERNAME/.local/lib/node_modules
binroot = /home/YOUR-USERNAME/.local/bin
manroot = /home/YOUR-USERNAME/.local/share/man

그다음 Node.js 소스 코드를 받아서(Node.js) 빌드를 하는데
--prefix 옵션을 $HOME/.local 로 지정하여 빌드 시작.

wget http://www.nodejs.org/download/node-v0.8..
tar xf node......
cd node........
./configure --prefix=~/.local


그리고
make && make install


그리고 마지막으로 PATH 에
$HOME/.local/bin 을 추가 하는 것으로 마무리

export PATH=$HOME/.local/bin:$PATH



이처럼 링크의 글 순서대로 진행 하면 된다.
(만약 당신이 Ubuntu 사용자라면 말이다...)




하.지.만.
당신이 지금 CentOS 5 이하 버전을 사용하고 있다면 결코 .....
결단코!!!


절대 알흠답게 에러 없이 설치 될 수가 없다!

여기에 약간의 삽질이 필요하게 된다.
최초 다운로드 받고 환경설정 잡는 것은 문제가 안되지만.
소스코드를 받아서 빌드하는 과정에서 몇몇 문제가 발생하게 된다.

# configure 시 에러 (error)
File “./configure”, line 360
1 if options.unsafe_optimizations else 0)
^
SyntaxError: invalid syntax


# make 시 에러 ( error )
Traceback (most recent call last):
  File "tools/gyp_node", line 11, in ?
    import gyp
  File "./tools/gyp/pylib/gyp/__init__.py", line 8, in ?
    import gyp.input
  File "./tools/gyp/pylib/gyp/input.py", line 14, in ?
    import gyp.common
  File "./tools/gyp/pylib/gyp/common.py", line 373
    with open(source_path) as source_file:
            ^
SyntaxError: invalid syntax

이것은  Node.js 가 python 2.6+ 을 필요로 하기 때문이다.
configure
Makefile
install.py
안에 /usr/bin/env python 을 참조하는 부분을 모두 새로 python 2.6+ 버전으로 지정을 해줘야 한다.

more..


이제 npm 과 nodejs 가 정상적으로 실행 되는지 확인하고 삽질을 시작하면 된다.
2013/02/01 23:53 2013/02/01 23:53
이 글에는 트랙백을 보낼 수 없습니다
peecky  | 2013/02/04 15:58
잡섭도 파이썬 버전 업 좀 ㅋㅋ
Dot  | 2013/02/08 08:33
짭섭은 OS 부터 갈아야 ( --)...
i686 에서 x86_64 로 갈아타야 하지 않것습니까?
[로그인][오픈아이디란?]
오픈아이디로만 댓글을 남길 수 있습니다

MySQL 성능을 죽이는 15가지 방법이라는 아주 재미있는 내용의 프리젠테이션...

MySQL 을 기반으로 한 다양한 웹 서비스들을 만들어가고 또 운영되는데 있어서
항상 MySQL 이라서 느려...MySQL 이니까 이 정도도 감지덕지... 라고 하지 말고
제대로 알고 제대로 쓸 수 있도록 해보자.
원문 : Jay Pipes@MySQL, Inc
http://www.slideshare.net/techdude/how-to-kill-mysql-performance


#1. Thinking too small
시작은 미미했으나... 그 끝도 미미 하리라는 생각은 버려라.

분명 시스템은 처음에는 매우 단순한 구조로 이루어지겠지만
커져가면서 결코 한 군데에 다 때려박아서 커버하기가 불가능해진다.

다수의 웹 서버들과 어플리케이션 서버 , DNS 서버 등의 여러 서버(혹은 서비스)들이 존재하게 된다.

이러한 서비스들에서 오는 모든 요청들로 인한 부하들이 집중되면 아무리 짱짱한 시스템이 들어와도 이를 감당해내기 힘들어진다.
그래서 부하들을 매 단계별로 Proxies 과 Caching 을 해서 최종적으로 넘어오는 부하의 양을 최소화 해야 할 필요가 있다.

특히 Caching 을 적극적으로 활용하지 않는 대형 웹 사이트를 존립시킬 수 없다.

그리고 각 서비스 컴포넌트 나 어플리케이션을 적극적으로 분리를 하고
무리하게 집중시키지 마라...
Scale-Up 을 통해서 성능향상을 바라는 것은 금방 한계점에 달하고 비용도 매우 많이 소요된다.
그보다 효율적으로 분산해서 처리하는 것이 더 현명한 선택이 될 것이다.

그리고 닥치기 전에 복제(replication) 나 분할(Partitioning) 에 대한 계획을 미리 수립하는 것이 좋다.
세션데이터는 최소화 하여 관리한다.

하지만 너무 허황될 만큼 크게 생각하진 말길.

성능이 반드시 확장성을 가져오는 것은 아니다.

#2. Not using EXPLAIN
EXPLAIN 은 입력된 SQL 문장을 해석하여 옵티마이져의 실행 계획을 보여주는 명령어 이다.
입력된 SQL 을 해석한 뒤 테이블의 데이터/인덱스 등을 판단하여 어떻게 실행 할지 보여주게 되는데.

Extra 컬럼에 "Using Index" 라고 나온다면 제대로 돌아 가고 있다 라고 봐도 거~~의~~ 무방하다.

특히 MySQL 5.0 이전 버전에서는 단 하나의 Index 만을 이용 할 수 있었는데.
MySQL 5.0+ 버전에서는 Index Merge optimization 을 통해서 좀더 향상된 속도를 얻을 수 있다.
이는 곧 인덱스 수립 계획에도 큰 도움이 된다. ( 슬라이드 Page 13 참조 )


#3. Choosing the wrong date types
Index ( 혹은 데이터) 는 가급적이면 단일블럭(Single Block) 안에 들어갈 수 있게 하는 것이 좋다.
기본적으로 DBMS 는 데이터가 늘어가면서 I/O 가 많이 일어나고 그리고 성능에 매우 민감하게 영향을 미치게 된다.
특히 디스크 처럼 매우 느린장치(CPU 연산 과정에서 보자면  HDD 는 아직 한참 멀었다.)에 접근 횟수를 줄일 수 있다면 당연히 느려진다는 것이다.

반대로 말하자면 데이터를 가져올때 횟수를 최소화 할 수 있다면 곧 속도향상을 얻을 수 있다라는 이야기.

그렇기 때문에 Index (혹은 데이터) 를 저장함에 있어서 가급적이면 최소한의 컬럼을 유지하는 것이 I/O 횟수를 줄이는데 유리하다.
슬라이드에서는 IP 정보를 저장할때 Varchar 형을 사용하거나 UNSIGNED INT 형을 사용 하는 2가지 경우를 가지고 이야기를 한다.

일반적으로 Varchar 형을 이용하여 저장하는 경우가 많은데. INET_ATON()/INET_NTOA() 함수를 이용하여 변환하여 INT 형에 저장 할 수 있게 되는데.
저장하는 데이터 크기도 줄이고 또한 Index range scan 을 통한 성능 향상도 꾀 할 수 있다는 장점이 있다.

슬라이드에서는 설명하고 있지 않지만 굳이 음수형으로 데이터를 저장할 필요가 없다면 UNSIGNED INT 와 같이 선언을 하게 되면 SIGNED INT로 선언했을 때 보다 약 2배 가량 속도 향상을 얻을 수도 있다고 한다.
그러니 *반드시* 필요한 데이터형의 크기를 잘 정해서 설계하는 것이 중요하다.

#4. Using persistent connection in PHP
MySQL 연결 시간(Connection Time) 을 줄이기 위해 영구적인 연결(Persistent Connection) 을 이용하는 경우가 있다.

하지만 영구적인 연결(Persistent Connection) 인 경우 자원을 공유하지 않은 구조로 인하여
Apache 프로세서가 Zombie 상태에 빠지게 되면 그대로 자원을 낭비하게 된다.

애초에 MySQL 은 수명이 짧고 경량형 으로 디자인 되어있어서 Connection Time 은 Oracle 이나 PostgreSQL 에 비해서 10~100배 가량 빠르다고 하니 pconnon_* 계열 에 목 매지 맙시다.

#5. Using a heavy DB abstraction layer
이식성(Portability) 때문에  ADODB , MDB2  혹은 PearDB 같은 무거운(Heavy) 추상화 라이브러리(abstraction Library) 를 쓰는데
그것 보단 PDO 같은 경량형 라이브러리를 이용하는 것이 좋다.  거기에 Scale-out 을 위한 부분도 추가해주 면 좋다.

#6. Not understanding storage engines
MySQL 에서는 매우 다양한 DB Engine 을 가지고 있는데 각 Engine 의 특성에 따라서
장 단점이 있는데 이에 대한 이해를 통해 적절한 Storage Engine 을 활용하면 보다 나은 성능을 발 휘 할 수 있다.

반대로 그러한 이해가 없이 사용하면 오히려 성능저하의 원인이 되기도 한다.

예를 들어 웹 로그 기록 같이 한번 입력하면 변경은 이루어지지 않고 고속의 INSERT 성능이 필요한 경우엔 Archive Engine 을 쓰는 것이 낫다 더욱이 압축 효율 또한 우수하여 ( MyISAM 대비 6~8배 ) 디스크 관리에도 유리하다.

반대로 주간 베스트 와 같이 크지는 않지만 빠른 입출력이 필요한 경우 Memory Engine 을 사용하면 Disk based Engine 에 비하여
획기적으로 빠른 성능을 제공 할 수 있다.

이처럼 적절한 Engine 을 활용 하는 것이 보다 나은 성능을 보장해준다.
다시 한번 말하지만 InnoDB 는 어디에도 붙일 수 있지만 성능을 보장해주는 것은 아니다.


#7. Not understanding index layouts
INDEX 선정과 Storage Engine 을 선탁하는데 매우 중요한 부분이다.
모든 Engine 들 은 Data 와 Index 를 메모리(Memory) 와 디스크 ( Disk ) 에 저장 한다.

Clustered 방식은 Primary Key 를 기준으로 정렬된 Data 묶음 단위로 디스크에 저장을 하고
Non-Clustered 는 그렇지 않다.

Non-Clustered 의 경우에는 큰 영향은 없지만.
Clustered 의 경우 데이터를 검색 할 경우 Primary key 를 보고 실제 데이터로 이동하여 데이터를 검색 하기 때문에
데이터 조회시 가급적 PK 를 이용하여 데이터를 검색하는 것이 좋다.

그리고 Clustered  방식에서 생성되는 모든 Second Index 는 PK 를 참조하여 만드므로 PK 는 최대한 작게 만들어주는 것이 좋다.

#8. Not understanding how the query cache works
사용하는 Application 의 Read/Write 비율을 이해한 상황에서
CPU 사용율과 읽기 성능을 적절하게 조율해야 한다.

Query Cache 를 늘린다고 성능이 무작정 증가하지도 않는다.

Cache 검증하는데 매우 투박한 검증방식 을 채용했는데
이유는 Cache 된 데이터를 찾아서 저장하는데 너무 많은 CPU 자원을 사용을 방지 하기 위해서 이다.

이는 SELECT 할 때 Table 에 어떠한 변화가 생긴 경우 모든 Cache 정보들은 유효하지 않게 된다는 것이다.
결국 Table 에 매번 변화가 생길 경우 매번 Cache 갱신을 하게 되고
Query Cache 의 효율이 떨어지게 되는 것이다.

그래서 자주 업데이트 되는 컬럼들을 분리 할 필요가 있다.

#9. Using stored procedures improperly
모든 RDBMS 는 Connection thread 별로 컴파일(Compiled)된 Stored Procedure 의 실행 계획을 유지하게 되는데

이것은 PHP 로 만든 페이지에서 요청을 보내서 SP 를 이용하여 데이터를 가져온다면
매번 컴파일을 거친다는 것이고 이것은 매우 큰 낭비라는 것이다(7~8% 정도)

특별히 매우 복잡하고 요쳥 빈도수가 많지 않은 작업이거나...
한번에 매우 많은 횟수의 Query 를 요청하는 경우가 아니라면....말이다.

그냥 Prepared Statements 를 써라...

#10. Operating on an indexed column with a function
Index Column 을 펑션으로 변환해서 사용하게 되면 Index 를 사용할 수 없게 된다.
그러니 있는 그대로 Index Column 을 사용 할 수 있도록 하는 것이 중요하다.

#11. Having missing or useless indexes
Index 는 SELECT 할때 검색 속도 향상에 매우 도움이 크다.

하지만 사용하지 않는(혹은 빈도 수가 매우 적은) Index 는 INSERT/UPDATE/DELETE 할때 매우 부담이 된다.
필요 없는 Index 는 반드시 삭제해주는 것이 좋다.

혹시 대량의 데이터를 입력이 필요 할 경우 경우에 따라서는 INDEX 를 삭제한 뒤
입력을 완료하고 인덱스를 생성하는 것이 나을 것이다.

#12. Not being a join-fu master
최대한 단순하게
복잡한 SQL 문을 쪼개서 데이터 묶음(Sets)으로 생각하라.

반복된 작업(Subquery,loop) 가 아닌 데이터 묶음(Join)으로 생각 해야 한다.
데이터의 묶음으로 처리하기 때문에 보다 나은 성능을 얻을 수 있다.

( 46~48p 를 반드시 참조하라!)

#13. Not accounting for deep scans
정렬된 데이터(ordered set)에서 매우 깊숙한(Deep scan) 곳에 데이터의 일부를 가져오는 것은 비용이 매우 많이 든다.

보통 게시판의 Paging 을 하면서 LIMIT 를 이용하게 되는데

페이지 넘버가 커지면 커질 수록 느려지는 경험을 해봤을 것이다.

이유는  LIMIT 를 이용하여 목록을 가져 오는 경우
1. 데이터를 정렬하고
2. 검색에 필요한 위치(offset) 을 지정해서 목록을 가져 온다.

여기서 데이터를 가져오는 위치(offset) 이 크면 클 수록 그 만큼 scan 을 하는 비용이

Full scan 비용에 근접하게 된다.
이를 피하기 위해선 해당 정렬된 데이터(Ordered set)의 크기를 줄여서 가져오는 것이 보다 나은 성능을 보장 할 수 있다.

#14. Doing SELECT COUNT(*) without WHERE on an InnoDB table
InnoDB 는 SELECT count(*) 로 Table 전체 Row 개 수를 가져오는 작업은 매우 퍼포먼스가 느린 작업이다.


InnoDB 내부적으로 매우 복잡(?) 한 구조로 인하여 생긴 문제인데 ( MyISAM 에서는....괜찮았다...)

필요하다면 별도의 테이블을 생성하여 Table 마다 Trigger 를 작성하여 Table Row count 를 관리하도록 하는 것도 방법이 되겠다.

#15. Not profiling or benchmarking
시스템 성능의 Bottleneck 을 항상 관찰하고(Profiling)
어플리케이션의 성능이 어느정도 까지 버틸 수 있는지 얼만큼의 부하를 견딜 수 있는지 테스트(Benchmark) 해볼 필요가 있다.

(54~56p 참조)

#16. Not using AUTO_INCREMENT
MySQL 에서 AUTO_INCREMENT 는 매우 PK 에 최적화 되어있다.

복합적으로 진행 되는 매우 많은 INSERT 에도 고성능으로 처리가 가능하다.
(Lockless reading and appending)

#17. Not using ON DUPLICATE KEY UPDATE
Application 에서 해당 Row 가 존재하는지 보고 Update or INSERT 를 결정하는 경우가 있는데
DB Connection 을 오가면서 소모되는 비용을 줄 일 수 있다. ( 약 5~6% 정도 )
물론 많은 양의 데이터가 와도 가능하다.

http://joinfu.com/presentations/kill-mysql-performance/kill-mysql-performance.pdf
http://ppassa.wordpress.com/2011/05/15/mysql-optimization-with-indexing/
2012/02/14 00:36 2012/02/14 00:36
이 글에는 트랙백을 보낼 수 없습니다
[로그인][오픈아이디란?]
오픈아이디로만 댓글을 남길 수 있습니다
주절거림  2010/12/04 18:42
그동안 테터툴즈 1.1.3 을 굴리고 있었는데
나온지 한 3~4년 쯤 되가나?

에디터는 최신 브라우저에서 지원하지 않고.
이래저레 한계점에 이른듯 해서 결국 갈아 탔음.

역시 신세계가 열리는거 같다는...
2010/12/04 18:42 2010/12/04 18:42
이 글에는 트랙백을 보낼 수 없습니다
[로그인][오픈아이디란?]
오픈아이디로만 댓글을 남길 수 있습니다
게시물 정리 ...

뭐 같은 법안이 통과...

이제 다 죽어보자 ...

나라는 20년 아니 40년 전으로 후퇴중...
2009/07/22 22:21 2009/07/22 22:21
이 글에는 트랙백을 보낼 수 없습니다
[로그인][오픈아이디란?]
오픈아이디로만 댓글을 남길 수 있습니다
Dot:Where is ......
byDot
Where is ......
전체 (177)
주절거림 (60)
윈도우벽지 (2)
Shoveling.. (9)
주워들은것들.. (48)
요집이 괜찮더라!! (0)
찍사놀이 (7)
관심꺼리~ (4)
«   2024/11   »
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
  1. 내 맘대로 보는 세상  2009
    맘에 안드는 Internet Explorer 업데이트 방침!
  2. 시리니  2008
    브라우저 업데이트, 작지만 큰 실천입니다.
  3. Dinosur와 KM의 Blog  2007
    저도 보통 사람
  1. 2019/02 (1)
  2. 2018/07 (1)
  3. 2018/01 (11)
  4. 2017/12 (10)
  5. 2017/10 (1)