86
Concurrent PHP in the Etsy API Matthew Graham @lapsu @EtsyAPI Lead #phpday 2014 April

Concurrent PHP in the Etsy API

Embed Size (px)

DESCRIPTION

How we at Etsy are adding concurrent data access to our PHP API. From PHP Day 2014

Citation preview

Page 1: Concurrent PHP in the Etsy API

Concurrent PHPin the Etsy API

Matthew Graham@lapsu

@EtsyAPI Lead#phpday2014 April

Page 2: Concurrent PHP in the Etsy API

@lapsu@EtsyAPI

Page 3: Concurrent PHP in the Etsy API

@lapsu@EtsyAPI

$1.3 BillionThings That Matter

Page 4: Concurrent PHP in the Etsy API

@lapsu@EtsyAPI

Page 5: Concurrent PHP in the Etsy API

@lapsu

Etsy's PHP

www api adminqueues cron

@EtsyAPI

Page 6: Concurrent PHP in the Etsy API

@lapsu

~200 engineers

30+ deploys / day

@EtsyAPI

Page 7: Concurrent PHP in the Etsy API

Also, Rasmus

@lapsu@EtsyAPI

Page 8: Concurrent PHP in the Etsy API

Spoilers

@lapsu

Mobile Clients Are Special

1 Thread != No Concurrency

@EtsyAPI

Page 9: Concurrent PHP in the Etsy API

@lapsu

<motivation>

@EtsyAPI

Page 10: Concurrent PHP in the Etsy API

Premise:

@lapsu

The Future is Mobile

@EtsyAPI

Page 11: Concurrent PHP in the Etsy API

@lapsu

Past The Future is Mobile

November 2013

@EtsyAPI

Page 12: Concurrent PHP in the Etsy API

@lapsu@EtsyAPI

Page 13: Concurrent PHP in the Etsy API

@EtsyAPI

Mobile Networks Suck

@lapsu

<

Page 14: Concurrent PHP in the Etsy API

@EtsyAPI

Not Mobile

@lapsu

www.etsy.com/shop/AVintageWanderer

Page 15: Concurrent PHP in the Etsy API

@EtsyAPI

Network Performance

@lapsu

3G < 4G

Page 16: Concurrent PHP in the Etsy API

@EtsyAPI

Network Coverage

@lapsu

3G > 4G

Page 17: Concurrent PHP in the Etsy API

@EtsyAPI

Mobile Requests

@lapsu

More != Better

Page 18: Concurrent PHP in the Etsy API

@lapsu@EtsyAPI

Page 19: Concurrent PHP in the Etsy API

@lapsu

1000ms Time To Glass

@EtsyAPI

Page 20: Concurrent PHP in the Etsy API

@lapsu

1000ms- 900ms

-------------100ms

Network/Client------------------------ Server

@EtsyAPI

Page 21: Concurrent PHP in the Etsy API

@lapsu

100ms = Bespoke + Concurrent

@EtsyAPI

Page 22: Concurrent PHP in the Etsy API

@lapsu

Single Threads

@EtsyAPI

Page 23: Concurrent PHP in the Etsy API

Concurrency

@lapsu@EtsyAPI

Main “Thread”

Child “Thread” Child “Thread”

Page 24: Concurrent PHP in the Etsy API

@lapsu

</motivation><interface>

@EtsyAPI

Page 25: Concurrent PHP in the Etsy API

Paul goes to Netflix

@lapsu@EtsyAPI

Page 26: Concurrent PHP in the Etsy API

1 View : 1 Bespoke

@lapsu@EtsyAPI

ClientView

Bespoke

View View

Bespoke BespokeAPI

Page 27: Concurrent PHP in the Etsy API

Multiple Clients

@lapsu@EtsyAPI

ClientsView

Bespoke

View View

Bespoke BespokeAPI

Page 28: Concurrent PHP in the Etsy API

Bespoke : Components

@lapsu@EtsyAPI

Bespoke Bespoke BespokeAPI

Item User Shop Favs Tx

Page 29: Concurrent PHP in the Etsy API

Components as REST

@lapsu@EtsyAPI

Bespoke BespokeAPI

Item User Shop Favs Tx

Page 30: Concurrent PHP in the Etsy API

@lapsu

?includes=User

@EtsyAPI

Page 31: Concurrent PHP in the Etsy API

Android User View

@lapsu

function handle($cli, $inp) { $shop = $cli->shop($inp->user_id); $favs = $cli->favs($inp->user_id); $items = $cli->items($shop->shop_id);

Curl_Orchestrator::run( [$shop,$favs,$items]); return [$favs,$items];}

@EtsyAPI

Page 32: Concurrent PHP in the Etsy API

Concurrent Client

@lapsu

function handle($cli, $inp) { $shop = $cli->shop($inp->user_id); $favs = $cli->favs($inp->user_id); $items = $cli->items($shop->shop_id);

Curl_Orchestrator::run( [$shop,$favs,$items]); return [$favs,$items];}

@EtsyAPI

Page 33: Concurrent PHP in the Etsy API

Making Requests

@lapsu

function handle($cli, $inp) { $shop = $cli->shop($inp->user_id); $favs = $cli->favs($inp->user_id); $items = $cli->items($shop->shop_id);

Curl_Orchestrator::run( [$shop,$favs,$items]); return [$favs,$items];}

@EtsyAPI

Page 34: Concurrent PHP in the Etsy API

@lapsu@EtsyAPI

shop

favs

t0 t1

Page 35: Concurrent PHP in the Etsy API

Inputs

@lapsu

function handle($cli, $inp) { $shop = $cli->shop($inp->user_id); $favs = $cli->favs($inp->user_id); $items = $cli->items($shop->shop_id);

Curl_Orchestrator::run( [$shop,$favs,$items]); return [$favs,$items];}

@EtsyAPI

Page 36: Concurrent PHP in the Etsy API

Future Parameters

@lapsu

function handle($cli, $inp) { $shop = $cli->shop($inp->user_id); $favs = $cli->favs($inp->user_id); $items = $cli->items($shop->shop_id);

Curl_Orchestrator::run( [$shop,$favs,$items]); return [$favs,$items];}

@EtsyAPI

Page 37: Concurrent PHP in the Etsy API

@lapsu@EtsyAPI

shop

favs

items

t0 t1 t2 t3 t4

Page 38: Concurrent PHP in the Etsy API

~6 Lines

@lapsu

function handle($cli, $inp) { $shop = $cli->shop($inp->user_id); $favs = $cli->favs($inp->user_id); $items = $cli->items($shop->shop_id);

Curl_Orchestrator::run( [$shop,$favs,$items]); return [$favs,$items];}

@EtsyAPI

Page 39: Concurrent PHP in the Etsy API

@lapsu

</interface><performance>

@EtsyAPI

Page 40: Concurrent PHP in the Etsy API

@lapsu

Web Pages Are Clients Too

@EtsyAPI

Page 41: Concurrent PHP in the Etsy API

Web First

@lapsu@EtsyAPI

Page 42: Concurrent PHP in the Etsy API

API First

@lapsu@EtsyAPI

Page 43: Concurrent PHP in the Etsy API

Android User View

@lapsu

function handle($cli, $inp) { $shop = $cli->shop($inp->user_id); $favs = $cli->favs($inp->user_id); $items = $cli->items($shop->shop_id);

Curl_Orchestrator::run( [$shop,$favs,$items]); return [$favs,$items];}

@EtsyAPI

Page 44: Concurrent PHP in the Etsy API

Desktop Web User View

@lapsu

function handle($cli, $inp) { $shop = $cli->shop($inp->user_id); $favs = $cli->favs($inp->user_id); $items = $cli->items($shop->shop_id); $teams = $cli->teams($inp->user_id);

Curl_Orchestrator::run( [$shop,$favs,$items,$teams]); return [$favs,$items,$teams];}

@EtsyAPI

Page 45: Concurrent PHP in the Etsy API

@lapsu

Activity Feed

@EtsyAPI

Page 46: Concurrent PHP in the Etsy API

@lapsu

Activity FeedPage

@EtsyAPI

HomePage

Page 47: Concurrent PHP in the Etsy API

30s of HTTP Time

@lapsu@EtsyAPI

Page 48: Concurrent PHP in the Etsy API

30s of HTTP Time

@lapsu

880ms Real Time

@EtsyAPI

Page 49: Concurrent PHP in the Etsy API

Components

@lapsu@EtsyAPI

Bespoke Bespoke Bespoke

API

Item User Shop Favs Tx

Page 50: Concurrent PHP in the Etsy API

Components Cache

@lapsu@EtsyAPI

Bespoke Bespoke Bespoke

CacheAPI

Item User Shop Favs Tx

Page 51: Concurrent PHP in the Etsy API

Local Call

@lapsu@EtsyAPI

Me

Page 52: Concurrent PHP in the Etsy API

Long Distance Call

@lapsu@EtsyAPI

AtlanticOcean User

Page 53: Concurrent PHP in the Etsy API

Long Distance Call

@lapsu@EtsyAPI

AtlanticOcean

API

Templates

User

Page 54: Concurrent PHP in the Etsy API

@lapsu

</performance><internals>

@EtsyAPI

Page 55: Concurrent PHP in the Etsy API

@lapsu

curl_multi_*

@EtsyAPI

Page 56: Concurrent PHP in the Etsy API

@lapsu@EtsyAPI

curl?

Page 57: Concurrent PHP in the Etsy API

General Sequence

@lapsu@EtsyAPI

curl_multi_init();curl_multi_add();curl_multi_exec();

while (!$done) { curl_multi_select(); curl_multi_exec(); curl_multi_info_read();}

Page 58: Concurrent PHP in the Etsy API

curl_multi_init

@lapsu@EtsyAPI

$mh = curl_multi_init();

Page 59: Concurrent PHP in the Etsy API

curl_multi_add_handle

@lapsu@EtsyAPI

$mh = curl_multi_init();$ch = curl_init($url);curl_setopt_array($ch, $options);curl_multi_add_handle($mh, $ch);

Page 60: Concurrent PHP in the Etsy API

@lapsu@EtsyAPI

multi handle

handle handle handle

Page 61: Concurrent PHP in the Etsy API

curl_multi_exec

@lapsu@EtsyAPI

do { $code = curl_multi_exec($mh, $r);} while ($code == CURLM_CALL_MULTI_PERFORM);

Page 62: Concurrent PHP in the Etsy API

curl_multi_select

@lapsu@EtsyAPI

$cnt = curl_multi_select($mh, $tmout);

Page 63: Concurrent PHP in the Etsy API

curl_multi_info_read

@lapsu@EtsyAPI

$info = curl_multi_info_read($mh);$ch = $info['handle'];$content = curl_multi_getcontent($ch);

Page 64: Concurrent PHP in the Etsy API

@lapsu@EtsyAPI

Page 65: Concurrent PHP in the Etsy API

localhost: Expected

@lapsu@EtsyAPI

R1

R2

R3

t0

Page 66: Concurrent PHP in the Etsy API

Network: Actual

@lapsu@EtsyAPI

R2

R3

t0 t1

R1

Page 67: Concurrent PHP in the Etsy API

curl Protocols

@lapsu@EtsyAPI

HTTP LDAP

Gopher POP3 IMAP

TELNET TFTP

Page 68: Concurrent PHP in the Etsy API

curl_get_multi_handle_state

@lapsu@EtsyAPI

$state = CURLM_STATE_FIRST;curl_multi_get_handle_state( $mh, $ch, $state);$sent = $state > CURLM_STATE_FIRST && $state < CURLM_STATE_PERFORM;

Page 69: Concurrent PHP in the Etsy API

Expected, Actual

@lapsu@EtsyAPI

R1

R2

R3

t0

Page 70: Concurrent PHP in the Etsy API

Revised Sequence

@lapsu@EtsyAPI

curl_multi_init();curl_multi_add();while (!$sent) { curl_multi_exec(); curl_multi_get_handle_state();}

while (!$done) { curl_multi_select(); curl_multi_exec(); curl_multi_info_read();}

Page 71: Concurrent PHP in the Etsy API

Still Headed Upstream

@lapsu@EtsyAPI

Page 72: Concurrent PHP in the Etsy API

Patch URL

@lapsu

bit.ly/etsy_curl_multi_patch

@EtsyAPI

Page 73: Concurrent PHP in the Etsy API

Recursion?

@lapsu@EtsyAPI

Page 74: Concurrent PHP in the Etsy API

Recursion?

@lapsu

No.

@EtsyAPI

Page 75: Concurrent PHP in the Etsy API

Recursion?

@lapsu

No?Not yet.

@EtsyAPI

Page 76: Concurrent PHP in the Etsy API

Visibility

@lapsu@EtsyAPI

Page 77: Concurrent PHP in the Etsy API

@lapsu

PHP Coroutines

@EtsyAPI

Page 78: Concurrent PHP in the Etsy API

More Code

@lapsu

Available Upon Request

@EtsyAPI

Page 79: Concurrent PHP in the Etsy API

@lapsu

codeascraft.etsy.com

@EtsyAPI

Page 80: Concurrent PHP in the Etsy API

@lapsu

</internals><wrap/>

@EtsyAPI

Page 81: Concurrent PHP in the Etsy API

@lapsu

Address Mobile Challenges

@EtsyAPI

Page 82: Concurrent PHP in the Etsy API

@lapsu

PHP Does Concurrency

@EtsyAPI

Page 83: Concurrent PHP in the Etsy API

PHP Abides

@lapsu@EtsyAPI

Page 84: Concurrent PHP in the Etsy API

Concurrent PHP

in the Etsy APIMatthew Graham

@lapsu@EtsyAPI Lead

#phpday2014 April

Thank You

Page 85: Concurrent PHP in the Etsy API

Reminder:

@lapsu

Repeat the questions

@EtsyAPI

Page 86: Concurrent PHP in the Etsy API

@lapsu

SPDY / HTTP 2.0

@EtsyAPI