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

XpressEngine에도 mod_disk_cache를 간단히 적용해보았습니다.

주의할 점

실제로 mod_disk_cache를 제대로 적용하기 위해서는 세션 쿠키 등등을 최소화하여 캐싱이 유리하도록 만들고, 익명 사용자에 대해서는 세션쿠키를 쓰지 말고 별도로 처리하면 캐싱이 유리하게 됩니다.

이 문서는 단순히 s-maxage=3으로 세팅하는 매우 간단한 패치이며, mod_disk_cache의 효과를 아파치벤치라는 간단한 벤치마크 툴로 테스트하는 결과를 보여주므로 실제로 사용자가 느낄 수 있는 성능 향상과는 괴리가 있을 수 있습니다.


XpressEngine에 적용하기

XE 버전 1.7.x에 대해서 작성했습니다. 패치로 만드는 대신에 다음과 같이 수동으로 고치는 방식을 설명합니다.

1) classes/display/DisplayHandler.class.php 파일에서 다음 함수를 찾아서 Expires, Cache-Control, Pragma 헤더 삭제.

        /**
         * print a HTTP HEADER for HTML, which is encoded in UTF-8
         * @return void
         */
        function _printHTMLHeader()
        {
                header("Content-Type: text/html; charset=UTF-8");
                #header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); # 제거
                header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
                #header("Cache-Control: no-store, no-cache, must-revalidate"); # 제거
                header("Cache-Control: s-maxage=3, max-age=0, must-revalidate");
                header("Cache-Control: post-check=0, pre-check=0", false);
                #header("Pragma: no-cache"); # 제거
        }


2) classes/context/Context.class.php 파일에서 session_start()를 찾아서 session_cache_limiter('') 추가

                session_cache_limiter(''); # 추가
                session_start();

이렇게 고치면 끝.

테스트 결과

아파치 벤치(ab -n 1000 -c 3 http://localhost/xe/)로 테스트해보니 다음과 같은 결과가 나왔습니다.

... Concurrency Level: 3 Time taken for tests: 0.433 seconds Complete requests: 1000 Failed requests: 0 Write errors: 0 Total transferred: 9072075 bytes HTML transferred: 8596000 bytes Requests per second: 2309.36 [#/sec] (mean) Time per request: 1.299 [ms] (mean) Time per request: 0.433 [ms] (mean, across all concurrent requests) Transfer rate: 20459.63 [Kbytes/sec] received


by dumpcookie 2013. 11. 9. 00:46

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 |