最近メールフォームかいてないメールフォーマーによる、ちょっとだけ変わった一応PHPのメールフォーム(?)のお話 〜副題 最近swooleがたのしいです〜

271fad8d53cd1f12f2b4b6d38e3d7bd3?s=47 uzulla
June 15, 2018

最近メールフォームかいてないメールフォーマーによる、ちょっとだけ変わった一応PHPのメールフォーム(?)のお話 〜副題 最近swooleがたのしいです〜

at 全然野菜(PHPCon Fukuoka 2018 非公式 前々夜祭)
20min talk
https://pepabo.connpass.com/event/85144/

271fad8d53cd1f12f2b4b6d38e3d7bd3?s=128

uzulla

June 15, 2018
Tweet

Transcript

  1. 17.
  2. 22.

    php (ڞ௨ɺ΄΅aptͰ͍Εͨ··) • PHP 7.2.6 • opcache • xdebugͳͲ͸ແ͠ •

    swoole֦ு͸swooleςετ࣌ͷΈ • (cliʹͷΈ֦ுΛϩʔυʣ
  3. 23.

    nginx (ڞ௨ɺ΄΅aptͰ͍Εͨ··) • worker_processes auto; • worker_connections 768; • gzip

    on; • tcp_nopush on; • tcp_nodelay on; • keepalive_timeout 65;
  4. 24.

    php-fpmʢൺֱ༻ʣ • FW͸ slim 3 • fpmઃఆ • pm =

    static • pm.max_children = 8 • fastcgi unix socket઀ଓ
  5. 26.
  6. 27.

    ϕϯν̍ • / (ϑΥʔϜ)Λճ͢ɺrpsΛܭଌ • wrk -c {N} -t 8

    -d 10s -R 100000 http:/ /{host}/ • ಉ࣌઀ଓ਺ΛมԽ͍ͤͯ͘͞(c͕1ͷ࣌ͷΈɺt΋1) • ̎ճճͯ͠ߴ͍ํΛ࠾༻ • Τϥʔ͕ͰͨΒ0ѻ͍
  7. 28.

    root@ubu:~/wrk2# ./wrk -c 1 -t 1 -d 10s -R 100000

    http://127.0.0.1/ Running 10s test @ http://127.0.0.1/ 1 threads and 1 connections Thread Stats Avg Stdev Max +/- Stdev Latency 5.13s 2.83s 9.95s 58.97% Req/Sec -nan -nan 0.00 0.00% 4022 requests in 10.00s, 2.14MB read Requests/sec: 402.19 Transfer/sec: 218.75KB
  8. 29.

    N php-fpm swoole 1 402 2530 50 946 5782 100

    931 5429 150 Τϥʔ 5335 200 - 5994 500 - 6612 1000 - Τϥʔ
  9. 30.
  10. 31.

    ϕϯν̎ • /post (อଘ)Λճ͢ɺrpsΛܭଌ • ab -c {N} -n 1000

    -p postdata -m POST -T "application/x-www- form-urlencoded" http:/ /{host}/post • ಉ࣌઀ଓ਺ΛมԽ͍ͤͯ͘͞ • ̎ճճͯ͠ߴ͍ํΛ࠾༻ • Τϥʔ͕ͰͨΒ0ѻ͍ • (͕ࠩϠό͗͢ΔͷͰDNS໰͍߹ΘͤΛൈ͍ͯ͋Γ·͢)
  11. 32.

    N php-fpm swoole 1 110 303 10 412 477 100

    408 514 150 Τϥʔ 537 200 520 400 540
  12. 33.
  13. 35.

    ࢀߟه࿥ helloworldϕϯν • wrk -c {N} -t 8 -d 10s

    -R 100000 http:/ /{host}/hello • ୯ʹʮhelloʯ͚ͩΛฦ͢ɺయܕతͳʮϕϯν൪௕ʯίʔυ • ͸͖ͬΓݴͬͯҙຯ͸ͳ͍͆
  14. 36.

    N php-fpm swoole 1 948 3187 50 1984 5935 100

    1909 7303 150 Τϥʔ 6649 200 7649 500 8915
  15. 37.
  16. 45.
  17. 46.

    ᐽՍಛੑ EasySwoole ੋҰ׺جဋSwoole Server 䇖ؿ֥ӈሁଽթ྘֥ٳ҃ൔ PHPᐽՍɼህູAPIࣕੜɼϥຂԮ๤PHPᄎྛଆൔᄝࣉӱߒఏބ໓ࡱ ࡆᄛഈջট֥ྟି෥ാbEasySwoole ߴ౓෧૷ྃ Swoole Server

    ࣕ ґچົӻ Swoole Server ݪ༗ಛੑɼࢧ࣋ಉൈࠁކࡓ๐HTTPɺࣗఆ ၬTCPɺUDPླྀၰđಞषؿᆀၛቋ֥֮࿐༝ӮЧބࣚ৯щཿԛ؟ࣉ ӱđॖၳ҄đۚॖႨ֥ႋႨڛༀb
  18. 54.
  19. 60.

    ॏཁͳϑΝΠϧ project App Root dir !"App App Class # !"HttpController

    # # $"Index.php ίϯτϩʔϥ !"Config.php ઃఆ !"EasySwooleEvent.php Πϕϯτ !"easyswoole easyswoole ίϚϯυ • ͜ΕΒ͸composer create-projectͰੜ੒Ͱ͖Δ • ॻ͔ͳ͖Ό͍͚ͳ͍ͷ͸࠷௿ݶIndex.phpͷΈʢޙड़ʣ
  20. 63.
  21. 64.

    • ʮΊͬͪΌΧϥϑϧͳதࠃޠ…͚ͩͲ·͋ɺͳΜͱͳ͘Θ͔ Δɺ͍͚Δ͍͚Δʂʯ • ͨͱ͑͹… • --d -> ͚ͭΔͱσʔϞϯԽ •

    --workerNum-1 -> ϫʔΧʔ਺ • (--workerNum 1 Ͱ͸ͳ͍…) • --user-nobody -> nobodyϢʔβʔͰ࣮ߦ • (--user nobodyͰ͸ͳ͍…ʣ
  22. 69.

    server { root /path/to/htdocs/; location / { proxy_http_version 1.1; proxy_set_header

    Connection "keep-alive"; proxy_set_header X-Real-IP $remote_addr; if (!-e $request_filename) { proxy_pass http://127.0.0.1:9501; } } }
  23. 70.
  24. 74.

    ඪ४ͷίϯτϩʔϥʔ • /{Ϋϥε໊}/{ϝιου໊} Έ͍ͨͳελΠϧͰϚοϓɺઃఆϑΝ Πϧ͸ແ͍ • /Auth/Login -> \App\HttpController\Auth::login() •

    / -> \App\HttpController\Index::index() • /HelloWorld -> \App\HttpController \HelloWorld::index() or \App\HttpController \Index::HelloWorld()
  25. 75.

    • REST͸ͮ͠Β͍ • HTTP Method੾Γ෼͚͸ແ͍ɺURL಺ύϥϝλ΋ύʔε͠ͳ͍ • ʮผʹRESTͳͯ͘΋ࢮͳͳ͍͠…ʯʮࢮ͵ਓ΋͍Δʯ • ͦ͏͍͏ਓ͸΋͏ҰͭͷΧελϜϧʔλΛ͔͓ͭ͏ •

    γϯϓϧͩ͠ɺઃఆ͍Βͳ͍͠ɺURL͕៉ྷͰͳͯ͘΋͍͍͠… ͱ͍͏͜ͱͰݸਓతʹ͸ͪ͜Β͕… • ʢGET ?id=1͘Β͍ͳΒڐͤΔ͠ɺෳࡶͳύϥϝλ͸JSONΛ POST͢Ε͹͍͍ͱࢥ͍ͬͯΔݹ͍ਓؒͷൃ૝Ͱ͢ʣ
  26. 81.
  27. 82.

    ΋͏Ұͭͷख๏ɺΧελϜϧʔλʔ • nikic/FastRoute ͦͷ΋ͷɻͳͷͰলུ • https:/ /www.easyswoole.com/Manual/2.x/En/_book/Http/ router.html • ΞΫγϣϯͷ࡞Γ͸ඪ४ͷίϯτϩʔϥʔͱ͸͜ͱͳΓɺҾ਺

    ʹreq/resΛ͍ΕΔPSR-7ରԠFWʹΑ͋͘ΔܗʹͳΓ·͢ $routeCollector->get( '/user/{id:\d+}',function (Request $request ,Response $response,$id){ $response->write("this is router user ,your id is {$id}"); $response->end(); });
  28. 95.

    public static function mainServerCreate(/* ... */): void { // timerͰ1ඵຖʹΠϯλʔόϧ࣮ߦ

    $register->add($register::onWorkerStart, function ($server, $workerId) { if ($workerId == 0) { Timer::loop(1000, function () { echo 'TICK!'; }); } }); }
  29. 100.

    function lookupCo() {// ίϧʔνϯ൛ for($i=0; $i<100; $i++) { $ip =

    \Swoole\Coroutine::gethostbyname("dns.google.com"); } } function lookupNormal() {//ී௨൛ for($i=0; $i<100; $i++) { $ip = gethostbyname("dns.google.com"); } } function hello() { $this->response()->write('hello'); }
  30. 102.

    • lookupCoʹෛՙΛ͔͚ͭͭɺhelloʹෛՙΛ͔͚Δࢼݧ • lookupCo: 1.64 rps / / ͜͜͸େ͖͘มΘΒͳ͍ •

    hello: 147.36 rps / / 100ഒʹ • lookup͕໰͍߹ΘͤதʹଞͷॲཧΛਐΊΔͷͰϒϩοΫͮ͠ Β͘ɺhello͕଎͘ͳͬͨ
  31. 107.

    protected function isProbablyExistsMailServer($host) { $goog_dns = "dns.google.com"; $dns_ip = static::getHostByNameWithCache($goog_dns);

    $cli = new \Swoole\Coroutine\Http\Client($dns_ip, 443, true); $cli->setHeaders([ 'Host' => $goog_dns, "User-Agent" => 'php', 'Accept' => 'application/json', 'Accept-Encoding' => 'gzip', ]); $encoded_host = urlencode($host);
  32. 108.

    $cli->get("/resolve?name={$encoded_host}&type=MX"); $mx_records = json_decode($cli->body, true); $cli->get("/resolve?name={$encoded_host}&type=A"); $a_records = json_decode($cli->body, true);

    $cli->close(); return isset($mx_records['Answer']) || isset($a_records['Answer']); } function some() { $res = $this->isProbablyExistsMailServer('example.jp') ? "found":"notfound"; }
  33. 111.
  34. 115.
  35. 116.

    λεΫͷొ࿥ class Index extends Controller { function index() // ͱ͋Δίϯτϩʔϥʔ

    { // ... $this->response()->write('Ϩεϙϯε'); $some = 'data'; TaskManager::async(function () use ($some) { $log = new Log; $log->set($some); // ॏ͍ॲཧͳͲ }); // ผʹλεΫొ࿥͸࠷ޙͰͳͯ͘΋Α͍ } }
  36. 120.

    public static function frameInitialize(): void { // ॳظԽ Cache::init(new Files([

    'expire' => 0, // ߏթݖ௹ൈࡗ 'cache_subdir' => true, // 䇖ఓሰଢ੣թ٢ 'prefix' => '', // ߏթ໓ࡱުሗ଀ 'path' => __DIR__.'/cache', // อଘDIR 'hash_type' => 'md5', // จ໊݅తᄒرํࣜ 'data_compress' => false, // ఓႨߏթଽಸ࿢෪ 'thread_safe' => false, // ϑΝΠϧϩοΫ͢Δ͔ 'lock_timeout' => 3000, // จ݅࠷Ӊ෭קൈࡗ(ms) ]));
  37. 121.

    Cache::get('name', 'औಘͰ͖ͳ͔ͬͨΒ'); Cache::set('name', 1, $ttl); Cache::has('name'); Cache::delete('name'); Cache::clear(); Cache::set('name', 1);

    Cache::inc('name');// +1 Cache::dec('name', 10);// -10 Cache::pull('name', 'औಘͰ͖ͳ͔ͬͨΒ');// pop Cache::remember('name', 'value'); // ͳ͚Ε͹set
  38. 122.

    protected function getHostByNameWithCache($host){ $val = Cache::get($host, null); if(!is_null($val)){ return $val;

    } $ip = \Swoole\Coroutine::gethostbyname("dns.google.com"); Cache::set($host, $ip, 3600); return $ip }
  39. 124.

    easy-swoole঺հ·ͱΊ • ϝʔϧϑΥʔϜΛߴ଎Խ͢Δʹ͋ͨͬͯ • ϑΥʔϜΛදࣔ -> ूܭσʔλΛද͓ࣔͯ͘͠ • ֬ೝը໘ ->

    ϝΞυଘࡏ֬ೝͷDNS໰͍߹Θͤ͸ඇಉظͰ • อଘ -> λεΫԽͯ͠ͱʹ͔͘ฦ͢ • ͱ͍ͬͨࣄ͕easy swooleͰϥΫϥΫͰ͖Δ
  40. 130.

    $ cat bot_log |grep swoole| wc -l 25 $ cat

    bot_log |grep laravel| wc -l 333 $ cat bot_log |grep slim| wc -l 15 $ cat bot_log |grep cakephp| wc -l 22 $ cat bot_log |grep zend| wc -l 8
  41. 135.
  42. 140.
  43. 143.
  44. 145.
  45. 147.
  46. 149.
  47. 151.
  48. 153.
  49. 154.

    Πϯετʔϧํ๏͸ʁ • swoole͸ී௨ͷ֦ுͱಉ͡ $ git clone https://github.com/swoole/swoole-src.git $ cd swoole-src/

    $ phpize $ ./configure --enable-openssl $ make all $ make install $ echo "extension=swoole" >> /etc/php/7.2/cli/conf.d/30-swoole.ini
  50. 157.

    ։ൃαϙʔτ • 䎔ဋIDEॿख(ิ׬༻ϔϧύ) • composer require easyswoole/swoole-ide-helper • https:/ /www.easyswoole.com/Manual/2.x/Cn/_book/Introduction/

    install.html • (Swoole͸C֦ுͳͷͰɺϔϧύΛ͍Εͳ͍ͱิ׬Ͱ͖ͳ͍Օ ॴ΋ʣ • ʢrequire-devͰeasy-swooleΛ͍ΕͨΒೖΔʣ
  51. 159.
  52. 161.

    [Unit] Description=swoole service After=network.target [Service] Type=simple LimitNOFILE=65535 WorkingDirectory=/path/to/easyswoole-sample/ ExecStart=/usr/bin/php /path/to/easyswoole-sample/easyswoole

    start --pid-/path/to/easyswoole-sample/Log/pid.pid ExecReload=/bin/sh -c "/bin/kill -USR1 `cat /path/to/easyswoole-sample/Log/pid.pid`" ExecStop=/usr/bin/php /path/to/easyswoole-sample/easyswoole stop --pid-/path/to/easyswoole-sample/Log/pid.pid Restart=always User=www-data [Install] WantedBy=multi-user.target
  53. 165.

    server { listen 80; root /path/to/htdocs; server_name _; location /

    { proxy_http_version 1.1; proxy_set_header Connection "keep-alive"; proxy_set_header X-Real-IP $remote_addr; # proxy_pass http://127.0.0.1:9501; proxy_pass http://unix:/tmp/swoole.sock:; } }
  54. 168.

    EOL