https://github.com/xpressengine/xe-core/pull/1598


XE는 느리다는 악평이 많은 편입니다. XE는 여러가지 현대적인 프레임워크 형태이면서 트리거, 애드온 위젯 등등의 여러 인터페이스를 통해서 확장이 가능한 형태이고, 이러한 확장성때문에 느리다고 하더라도 많은 불만이 있지는 않은 것 같습니다.

그러나 XE는 몇가지만 고치더라도 클라우드플레어나 varnish 캐서서버 혹은 nginx 리버스 프록시 캐시서버를 통해서 그 성능을 획기적으로 향상시킬 수 있습니다. 그것도 아주 간단한 패치를 하는 것 만으로 이러한 성능향상이 가능합니다.

그것은 다름아닌 캐시서버의 적중률을 방해하는 대표적인 요소인 Set-Cookie: 헤더를 최소화 하는 것입니다.

Set-Cookie:헤더는 세션이 시작되는 경우 및 쿠키를 설정하는 경우에 설정이 됩니다. 웹 서비스를 하게되면 대부분의 사용자는 로그인사용자가 아닌 익명의 사용자이고, 로봇등에 의해서 상당량의 접속이 있게됩니다. 이러한 상당수의 익명의 클라이언트의 경우 세션을 세팅하지 않거나 쿠키 헤더를 쓰지 않는것 만으로도 캐시서버의 적중률을 높일 수 있습니다.

XE의 경우에도  session_start()가 무조건적으로 호출되고 있습니다. 이 경우 Set-Cookie:PHPSESSID=... 쿠키가 설정이 되며 varnish 캐시서버가 효율적으로 작동하지 않게 됩니다. 아래는 varnish 캐서서버 + XE + nginix (php5-fpm) 설정을 한 서버에 XE를 설치한 후에 살펴본 헤더입니다.

$ curl -I  http://localhost/
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
X-Powered-By: PHP/5.5.9-1ubuntu4.9
Cache-Control: public, must-revalidate, post-check=0, pre-check=0
Set-Cookie: PHPSESSID=1g12hp22q8r0ojbjog7seaft26; path=/
Accept-Ranges: bytes
Date: Thu, 09 Jul 2015 00:54:35 GMT
X-Varnish: 1471733958
Age: 0
Via: 1.1 varnish
Connection: keep-alive
X-Backend-Server: nginx/1.4.x (Ubuntu)
Server: nginx/1.4.x (Ubuntu)
X-Cache-Hit: MISS

위에서 보는바와 같이 varnish 캐시서버에서 캐시가 미스가 되고 있습니다.

ab 벤치마크입니다. 1000회를, 동시에 3개 요청하는 경우입니다. 상당히 느리고 이것이 현재 XE를 nginx + varnish 캐시서버로 운용할때의 대략적 성능입니다. (혹은 단순히 nginx 혹은 아파치 웹서버만 운용하는 경우)

$ ab -n 1000 -c 3  http://localhost/
This is ApacheBench, Version 2.3 <$Revision: 1528965 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
....
Requests per second:    74.85 [#/sec] (mean)
Time per request:       40.079 [ms] (mean)
Time per request:       13.360 [ms] (mean, across all concurrent requests)
Transfer rate:          2533.88 [Kbytes/sec] received
...

그러면 이번에는 XE 성능을 100배 향상시키는 속도 패치를 적용한 후에 테스트를 해보겠습니다. 즉 session_start()가 기본적으로 호출이 안되고 Set-Cookie 헤더가 붙지 않게 되며, 캐시 적중률이 올라가게 됩니다.

$ curl -I  http://localhost/
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
X-Powered-By: PHP/5.5.9-1ubuntu4.9
Cache-Control: public, must-revalidate, post-check=0, pre-check=0
X-Backend-Status: normal
Date: Thu, 09 Jul 2015 00:59:14 GMT
X-Varnish: 1471735403 1471735392
Age: 6
Via: 1.1 varnish
Connection: keep-alive
X-Backend-Server: nginx/1.4.x (Ubuntu)
Server: nginx/1.4.x (Ubuntu)
X-Cache-Hit: HIT

(몇차례 curl -I를 실행하면 Cache-Hit가 HIT 상태임을 나타내고 있습니다.)

ab 벤치마크 측정

$ ab -n 1000 -c 3  http://localhost/
This is ApacheBench, Version 2.3 <$Revision: 1528965 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
....
Requests per second:    8018.35 [#/sec] (mean)
Time per request:       0.374 [ms] (mean)
Time per request:       0.125 [ms] (mean, across all concurrent requests)
Transfer rate:          269428.95 [Kbytes/sec] received
...

8000 RPS로 아파치 벤치값으로 비교하여 무려 ~100배가 향상되었습니다.

동시에 200개 요청을 하고 20000회 요청을 해면 다음과 같습니다.

$ ab -n 20000 -c 200  http://localhost/
...
Requests per second:    14025.98 [#/sec] (mean)
Time per request:       14.259 [ms] (mean)
Time per request:       0.071 [ms] (mean, across all concurrent requests)
Transfer rate:          473883.72 [Kbytes/sec] received

무려 14000 RPS나 나옵니다. 초당 470MB/s
동시에 500개 요청을 해도 결과는 비슷합니다. (ab -n 20000 -c 500)

더 놀라운 것은 시스템의 부하 상태입니다. (ab -n 20000 -c 500을 처리하고 난 이후)

$ w
 10:04:25 up xx days, 17:28,  x user,  load average: 0.25, 0.19, 0.18

그러면 nginx만의 성능은 어떨까요 ? ab -n 10000 -c 50 http://localhost:8000/ 1만회 50개 요청을 동시에 해보았습니다.

$ ab -n 10000 -c 50  http://localhost:8000/ (ngix가 8000 포트로 설정되어 있음)
This is ApacheBench, Version 2.3 <$Revision: 1528965 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
....
Requests per second:    106.64 [#/sec] (mean)
Time per request:       468.850 [ms] (mean)
Time per request:       9.377 [ms] (mean, across all concurrent requests)
Transfer rate:          3570.91 [Kbytes/sec] received
....

~100RPS 수준이고 3MB/s 밖에 안나옵니다.

그리고 시스템 부하상태입니다.

$ w
 10:09:01 up xx days, 17:33,  x user,  load average: 3.64, 1.45, 0.63

현재 이 패치는 https://github.com/xpressengine/xe-core/pull/1598 PR로 등록되어 있으며 반영되기를 기다리고 있습니다. 또한 XE 포럼에도 글을 등록하였습니다. https://www.xpressengine.com/forum/23040664

XE3 개발때문인지 그다지 반응이 시근둥한 편입니다만 많은 관심가져주시기 바랍니다~

참고로 현재 이 패치는 리그베다위키 BBS에 적용되어 운용중입니다.

by dumpcookie 2015. 7. 19. 04:00

세션($_SESSION쿠키)의 사용은 캐시 서버의 캐시 적중률에 방해를 일으켜서 캐시서버 성능을 저하시키는 원인이 됩니다.

https://github.com/gnuboard/gnuboard5/pull/15

이 패치는 그누보드에서 무조건적으로 session_start()가 호출되는 부분을 변경하여. session_start()가 선택적으로 호출되게 하여 캐시서버의 캐시 적중률을 높여줍니다.

이 패치를 적용하고 난 후에 다음과 같은 줄을 커맨트아웃시킨 후에 아파치벤치의 성능을 살펴보겠습니다.

// common.php의 다음 줄을 찾아서 커맨트아웃
// 방문자수의 접속을 남김
#include_once(G5_BBS_PATH.'/visit_insert.inc.php');

위 visit_insert.inc.php는 중복 접속이 카운팅되는 것을 막기위해 쿠키를 사용하고 있는데, 쿠키를 사용하는 부분때문에 캐시 적중률을 떨어뜨리고 있습니다. 이 부분은 다른 방식으로 고쳐야만 그누보드가 좀 더 캐시서버 친화적이 될 수 있습니다.

패치 적용하지 않은 경우

$ ab -n 1000 -c 30 "http://g4.xxxxx.xxx"

Requests per second:    1854.10 [#/sec] (mean)
Time per request:       16.180 [ms] (mean)
Time per request:       0.539 [ms] (mean, across all concurrent requests)
Transfer rate:          21510.47 [Kbytes/sec] received
...

~1800RPS 및 21MB/s가 나오고 있습니다.

패치 적용 후

이 패치를 적용한 후에 중복 접속 카운팅 부분을 커맨트아웃 시키고
varnish 캐시서버 + 그누보드5 + nginx (php4-fpm 세팅) 성능을 아파치벤치마크 성능이 다음과 같이 나옵니다.

$ ab -n 1000 -c 30 "http://g4.xxxxxx.xxxx/"
...
Requests per second:    12976.40 [#/sec] (mean)
Time per request:       2.312 [ms] (mean)
Time per request:       0.077 [ms] (mean, across all concurrent requests)
Transfer rate:          148354.17 [Kbytes/sec] received
...

~12000RPS 및 148MB/s 속도가 나오고 있습니다.

접속회수 1만회 동시접속을 300까지 늘려보면

$ ab -n 10000 -c 300 "http://g4.xxxxxx.xxxx/"
...
Requests per second:    17307.54 [#/sec] (mean)
Time per request:       17.333 [ms] (mean)
Time per request:       0.058 [ms] (mean, across all concurrent requests)
Transfer rate:          197871.10 [Kbytes/sec] received
...

서버 로드상태

$ w
 01:30:28 up xx days,  8:54,  x users,  load average: 0.13, 0.08, 0.11

단순히 아파치벤치 성능상으로 최대 ~8배의 성능 향상이 있음을 볼 수 있습니다.


이 패치는 현재 https://github.com/gnuboard/gnuboard5/pull/15 에 등록시켜 반영을 기다리고 있는 중입니다. (http://sir.co.kr/g5_tip/2964 글도 같이 올렸습니다.)

by dumpcookie 2015. 7. 19. 03:38

PHP 경험이 많은 분들이라면 한번정도는 PHP 확장 모듈을 만들어 보았을 것이다. 본인의 경우는 비로서 최근에 PHP 확장 모듈을 만들어 보았는데 다음의 내용이 게중에 가장 쉬웠다. 뚝딱 테스트 해보는데에 20분이면 충분했다.

http://devzone.zend.com/303/extension-writing-part-i-introduction-to-php-and-zend/

위 사이트에서 복사해서 붙이기만 하고 최초 작동 테스트 완료 하는데에 20분 걸렸으니, 더 간단하고 쉬운 문서를 만들면 좋겠다 싶어서 문서를 더 찾아보았다. 그래서 찾은 문서는 exman으로 유명한 박준철님이 작성하신 다음 문서이다. (박준철님의 사이트는 닫혀있었으나 문서는 다른 곳에서 찾을 수 있었다)

http://srctalk.imfree.co.kr/view.ife?seq=268


이 문서의 특징은 PHP로 확장모듈을 만드는 프로그래머가 실제로 확장 모듈을 만들게 될 상황에 맞춰서 구성되었다는 점이다.

그리고 또 찾은 문서는 다음과 같은데, 문서가 길지 않고 매우 짧고 쉬워서 그대로 따라하기 쉽다.

http://eddmann.com/posts/introduction-to-creating-a-basic-php-extension/


이정도 문서만 참고하더라도 10분안에 나만의 PHP 확장을 만들고 최소한의 테스트를 완료할 수 있을 것 같은데, 열거한 문서를 읽어본 사람이라면 다음의 내용을 따라해서 좀 더 빨리 확장 모듈을 만들어보고 테스트 할 수도 있다.


스크립트 실행 준비

먼저 원하는 디렉토리로 위치로 가서 새로 디렉토리를 만든다음 그곳에서 스크립트를 실행시킬 준비를 한다. 이때에 적절한 프로젝트 이름을 생각해둔다. 여기서는 그 이름을 foobar로 하겠다.

cd ~/home
mkdir php-foobar
cd php-foobar

스크립트 받기

디렉토리에 들어가서 (여기서는 php-foobar) 다음과 같이, 복사하고 붙이기를 최소화 하기 위하여 미리 만들어둔 쉘 스크립트를 다운로드 받아서 압축을 푼다.

php_ext.sh.gz


이 스크립트는 PHP 소스에 포함되어있는 ext_skel 스크립트와 하는 기능은 거의 같지만, 더 단순한 기능만 하고, 실행 즉시 곧바로 아무것도 건드리지 않고 phpize를 통해 컴파일 할 수 있다는 점이 다르며, skeleton 디렉토리에 의존하는 스크립트가 아니기때문에 아무데서나 사용할 수 있다.

스크립트 압축 풀기

스크립트의 압축을 푼다.

gunzip php_ext.sh.gz

스크립트 실행

디렉토리에 들어가서 (여기서는 php-foobar) 다음과 같이 스크립트를 실행시킨다.

sh php_ext.sh foobar

그러면 config.m4, foobar.c, php_foobar.h 세개의 파일이 생성된다.


컴파일하기

콘솔에서 phpize를 실행하면 각종 파일이 자동으로 생성되며, configure를 실행하고 난 후에 make 한다.

phpize
sh configure
make
...

테스트하기

콘솔에서 다음의 명령을 실행시켜보자

php -dextension=.libs/foobar.so -r "foobar_world('hello');"

화면에 "Hello hello"라고 뜨면 정상 작동한 것이다. 테스트 종료.


아마 이대로만 정확히 따라했다면 5분안에도 만들고 테스트 완료 했을 것이다. 그러나 원하는 기능을 만들기 위해서는 이제 몇십배 더 많은 시간을 투자해야 할지도 모른다!!

by dumpcookie 2015. 5. 2. 10:36

XE 게시판과 위키를 연동하는 경우

위키 링크라던지 위키에 관련된 기능이 게시판에도 필요한 경우가 종종 있습니다.

([[위키백과]]같은 위키 링크)


이 애드온은 위키의 링크를 손쉽게 연결시켜 주는 xe 게시판용 애드온입니다



이와 관련된 기능은 xe 사이트의 애드온을 찾아보면 이미 있습니다. (wikilink로 검색하면 몇 개 나옴)


여기서 소개하는 애드온은 위키네임을 링크시켜주는 기능 말고도 모니위키에서 지원하는 일부 기능인 URL을 고쳐주는 기능이 같이 들어있습니다.


예를 들어서 http://rigvedawiki.org/r1/wiki/FrontPage 같은 식으로 예전 링크가 있다면 이것을 rigvedawiki.net으로 고쳐서 자동으로 보여줍니다.


급조한 것이지만 xe 1.7에서 아무런 문제없이 동작하는 것을 확인하였습니다~

1.5에서도 문제없이 될 것으로 생각됩니다.


아직 urlmapping은 xe 사이트에 정식등록한 상태가 아닙니다.


urlmapping 애드온은 위키 관련된 링크를 고쳐주거나 하는 애드온이므로 이것과 관련된 기능 제안을 환영합니다~


TODO

- 인터위키 연결 지원 외


스크린샷 (관리자 메뉴)



다운로드


urlmapping-0.1.tar.gz


by dumpcookie 2013. 5. 10. 15:22
| 1 |