SlideShare uma empresa Scribd logo
1 de 70
Baixar para ler offline
A S Y N C H R O N O U S
D ATA
P R O C E S S I N G
A N D R E A G I U L I A N O
@bit_shark
# C A K E F E S T
T H E P R O B L E M
P R O D U C T C ATA L O G G E N E R AT O R
• 30k+ records in db representing products
• dispose records in pages (with a certain order)
• generate a 300+ pages PDF catalog
T H E P R O B L E M
H E AV Y
O P E R AT I O N S
T O D O H E R E
T H E P R O B L E M
U S E R S D O N ’ T WA N T T O WA I T
T H E P R O B L E M
U S E R S D O N ’ T WA N T T O WA I T
T H E P R O B L E M
A N D I F T H E Y H AV E T O
T H E Y D O N ’ T WA N T T O
G E T S T U C K !
T H E P R O B L E M
S Y N C H R O N Y
time
process A
process B
Request
Response
blocked
T H E N E E D S
P R E V E N T T I M E O U T
T H E N E E D S
E V E N T U A L LY D E L I V E RY
T H E N E E D S
“sooner or later your job will be processed.”
“ E V E R I T H I N G ’ S G O N N A B E A L R I G H T ”
N O T I F I C AT I O N
T H E N E E D S
T H E N E E D S
A S Y N C H R O N Y
time
process A
process B
Request
I N T E R O P E R A B I L I T Y
T H E N E E D S
A D VA N C E D M E S S A G E
Q U E U I N G P R O T O C O L
T H E S O L U T I O N
H O W D O E S I T W O R K
A M Q P
P R O D U C E R C O N S U M E R
Produce Consumes
B R O K E R
H O W D O E S I T W O R K
A M Q P
P R O D U C E R C O N S U M E R
Produce
Exchange
Consumes
B R O K E R
H O W D O E S I T W O R K
A M Q P
P R O D U C E R C O N S U M E R
Produce
Exchange
Routes
Consumes
B R O K E R
H O W D O E S I T W O R K
A M Q P
P R O D U C E R C O N S U M E R
Produce
Exchange Queue
Routes
Consumes
B R O K E R
T H R O U G H C O M P O S E R
I N S TA L L A M Q P L I B R A RY
{	
  
	
  	
  	
  	
  "require":	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  "videlalvaro/php-­‐amqplib":	
  "@stable",	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  ...	
  
	
  	
  	
  	
  }	
  
}	
  
$ composer.phar install
D I F F E R E N T S C E N A R I O S
P R O D U C E R / C O N S U M E R
S C E N A R I O
S C E N A R I O
P R O D U C E R / C O N S U M E R
P R O D U C E R C O N S U M E R
Q U E U E
S C E N A R I O
P R O D U C E R / C O N S U M E R
use	
  PhpAmqpLibConnectionAMQPConnection;	
  
use	
  PhpAmqpLibMessageAMQPMessage;	
  
	
  	
  
$connection	
  =	
  new	
  AMQPConnection(HOST,	
  PORT,	
  USER,	
  PASSWORD);	
  
$channel	
  =	
  $connection-­‐>channel();
S E T T I N G U P
C O N N E C T I O N
C R E AT E A C H A N N E L
S C E N A R I O
P R O D U C E R / C O N S U M E R
P R O D U C E R
Q U E U E
	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  passive	
  	
  durable	
  exclusive	
  auto-­‐delete	
  
$channel-­‐>queue_declare('catalog',	
  false,	
  	
  false,	
  	
  false,	
  	
  	
  	
  false);	
  
	
  	
  	
  
foreach	
  ($catalog-­‐>getPages()	
  as	
  $page)	
  {	
  
	
  	
  	
  	
  $message	
  =	
  new	
  AMQPMessage($page);	
  
	
  	
  	
  	
  $channel-­‐>basic_publish($message,	
  '',	
  'catalog');	
  
}	
  
	
  	
  
$channel-­‐>close();	
  
$connection-­‐>close();
S C E N A R I O
P R O D U C E R / C O N S U M E R
C O N S U M E R
Q U E U E
$connection	
  =	
  new	
  AMQPConnection(HOST,	
  PORT,	
  USER,	
  PASSWORD);	
  
$channel	
  =	
  $connection-­‐>channel();	
  
	
  	
  
$channel-­‐>queue_declare('catalog',	
  false,	
  false,	
  false,	
  false);	
  
	
  	
  
$callback	
  =	
  function($msg)	
  {	
  
	
  	
  	
  	
  $msg-­‐>body-­‐>generatePdf();	
  
};	
  
	
  	
  
$channel-­‐>basic_consume('catalog',	
  '',	
  false,	
  true,	
  false,	
  false,	
  $callback);	
  
	
  	
  
while(count($channel-­‐>callbacks))	
  {	
  
	
  	
  	
  	
  $channel-­‐>wait();	
  
}	
  
	
  	
  
$channel-­‐>close();	
  
$connection-­‐>close();	
  
S C E N A R I O
M U LT I P L E C O N S U M E R S
P R O D U C E R
C O N S U M E R
Q U E U E
C O N S U M E R
…
S C E N A R I O
M U LT I P L E C O N S U M E R S
P R O D U C E R
C O N S U M E R
Q U E U E
C O N S U M E R
…
parallelize work
easy scalability
C O N S U M E R S C A N D I E
M E S S A G E
A K N O W L E D G E M E N T
S A F E T Y
M E S S A G E A C K S
$callback	
  =	
  function($msg){	
  
	
  	
  	
  	
  $msg-­‐>body-­‐>generatePdf();	
  
	
  	
  	
  	
  $msg-­‐>delivery_info['channel']-­‐>basic_ack($msg-­‐>delivery_info['delivery_tag']);	
  
};	
  
!
$channel-­‐>basic_consume('catalog',	
  '',	
  false,	
  false,	
  false,	
  false,	
  $callback);
S W I T C H A C K O N
D O N ’ T F O R G E T
T O S E N D A C K S
T H E B R O K E R
C A N D I E
D U R A B I L I T Y
D U R A B I L I T Y
M A R K T H E Q U E U E A N D T H E C H A N N E L
$channel-­‐>queue_declare('catalog',	
  false,	
  true,	
  false,	
  false);
In order to achieve durability
$message	
  =	
  new	
  AMQPMessage($data,	
  
	
  	
  	
  	
  	
  	
  	
  #the	
  message	
  is	
  now	
  persistent	
  
	
  	
  	
  	
  	
  	
  	
  array('delivery_mode'	
  =>	
  2)	
  	
  
	
  	
  	
  	
  	
  	
  	
  );
the queue must be declared durable
the message must be marked as persistent
Q O S P O L I T I C S
Q O S P O L I T I C A
B E FA I R
C O N S U M E R
C O N S U M E R
for certain instances of the Round Robin dispatching
B R O K E R
#1
#3
#5
#2
#4
#6
Q O S P O L I T I C S
B E FA I R
$channel-­‐>basic_qos(null,	
  1,	
  null);
C O N S U M E R
C O N S U M E R
the broker sends messages only when it receives acks
B R O K E R
#1
#3
#3 #2#4
P U B L I S H / S U B S C R I B E
S C E N A R I O
S C E N A R I O
P U B L I S H / S U B S C R I B E
chatRoom
FA N O U T E X C H A N G E
$connection	
  =	
  new	
  AMQPConnection(HOST,	
  PORT,	
  USER,	
  PASSWORD);	
  
$channel	
  =	
  $connection-­‐>channel();	
  
	
  	
  
$channel-­‐>exchange_declare('chatRoom',	
  'fanout',	
  false,	
  false,	
  false);
Exchange
…
Setting up the connection and declare the fanout exchange
S C E N A R I O
P U B L I S H / S U B S C R I B E
chatRoom
Exchange
…
$data	
  =	
  getAMessageToSendInTheRoom();	
  
$msg	
  =	
  new	
  AMQPMessage($data);	
  
	
  	
  
$channel-­‐>basic_publish($msg,	
  'chatRoom');	
  
	
  	
  
$channel-­‐>close();	
  
$connection-­‐>close();	
  
P R O D U C E R
Produce
Publishing a message to the exchange
N O W I T ’ S T H E
S U B S C R I B E R ’ S T U R N
S C E N A R I O
P U B L I S H / S U B S C R I B E
chatRoom
Q U E U E B I N D I N G
Exchange
…
//connection	
  setted	
  up	
  
!
list($queue_name,	
  ,)	
  =	
  $channel-­‐>queue_declare("",	
  false,	
  false,	
  true,	
  false);	
  
	
  	
  
$channel-­‐>queue_bind($queue_name,	
  'chatRoom');
Bind the Queue on the Exchange
amq.gen-A7d
bind
bind
amq.gen-Sb4
S C E N A R I O
P U B L I S H / S U B S C R I B E
chatRoom
Exchange
…
amq.gen-A7d
$channel-­‐>basic_consume($queue_name,	
  	
  
	
   	
   	
   	
   	
   	
   	
   	
  '',	
  	
  
	
   	
   	
   	
   	
   	
   	
   	
  false,	
  	
  
	
   	
   	
   	
   	
   	
   	
   	
  true,	
  	
  
	
   	
   	
   	
   	
   	
   	
   	
  false,	
  	
  
	
   	
   	
   	
   	
   	
   	
   	
  false,	
  	
  
	
   	
   	
   	
   	
   	
   	
   	
  'readMessage');	
  
	
  	
  
$channel-­‐>close();	
  
$connection-­‐>close();	
  
C O N S U M E R
Consumes
amq.gen-Sb4
R O U T I N G
S C E N A R I O
S C E N A R I O
R O U T I N G
chatRoom
Exchange
type=direct
…
amq.gen-A7d
amq.gen-Sb4
Consumer1
ConsumerN
P R O D U C E R
Produce
routing_keys = friends
routing_keys = friends, colleagues
$channel-­‐>exchange_declare('chatRoom',	
  'direct',	
  false,	
  false,	
  false);
S C E N A R I O
R O U T I N G
chatRoom
Exchange
type=direct
P R O D U C E R
Produce
Producing messages
//connection	
  setted	
  up	
  
!
$channel-­‐>exchange_declare('chatRoom',	
  	
  
	
   	
   	
   	
   	
   	
   	
   	
   	
  'direct',	
  	
  
	
   	
   	
   	
   	
   	
   	
   	
   	
  false,	
  	
  
	
   	
   	
   	
   	
   	
   	
   	
   	
  false,	
  	
  
	
   	
   	
   	
   	
   	
   	
   	
   	
  false);	
  
	
  	
  	
  
$data	
  =	
  getAMessageToSendInTheRoom('friends');	
  
$msg	
  =	
  new	
  AMQPMessage($data);	
  
	
  	
  
$channel-­‐>basic_publish($msg,	
  'chatRoom',	
  'friends');	
  
	
  	
  
$channel-­‐>close();	
  
$connection-­‐>close();	
  
S C E N A R I O
R O U T I N G
//connection	
  setted	
  up	
  
//exchange	
  setted	
  up	
  
//$queue_name	
  is	
  a	
  system	
  generated	
  queue	
  name	
  
!
$rooms	
  =	
  array('friends',	
  'colleagues');	
  
	
  	
  
foreach($rooms	
  as	
  $room)	
  {	
  
	
  	
  	
  	
  $channel-­‐>queue_bind($queue_name,	
  'chatRoom',	
  $room);	
  
}	
  
	
  	
  
$channel-­‐>basic_consume($queue_name,	
  '',	
  false,	
  true,	
  false,	
  false,	
  'readMessage');	
  
	
  	
  
$channel-­‐>close();	
  
$connection-­‐>close();	
  
Bind a Consumer on different routing keys and consuming messages
chatRoom
amq.gen-Sb4
Consumer
routing_keys = friends, colleagues
T O P I C
S C E N A R I O
G O F U R T H E R
T O P I C
$channel-­‐>exchange_declare('vehicle',	
  'topic',	
  false,	
  false,	
  false);
vehicle
Exchange
type=topic
amq.gen-A7d
amq.gen-Sb4
Consumer1
Consumer2
P R O D U C E R
Produce
routing_keys = *.car.*
routing_keys = race.#
<type>.<vehicle>.<colour>
routing_keys = *.*.red
D O T S D E L I M I T E D R O U T I N G K E Y
A Y E L L O W S P O R T C A R
T O P I C
A Y E L L O W S P O R T C A R
vehicle
Exchange
type=topic
amq.gen-A7d
amq.gen-Sb4
Consumer1
Consumer2
P R O D U C E R
Produce
routing_keys = *.car.*
routing_keys = race.#
<sport>.<car>.<yellow>
routing_keys = *.*.red
D O T S D E L I M I T E D R O U T I N G K E Y
T O P I C
A Y E L L O W S P O R T C A R
vehicle
Exchange
type=topic
amq.gen-A7d
amq.gen-Sb4
Consumer1
Consumer2
P R O D U C E R
Produce
routing_keys = *.car.*
routing_keys = race.#
<sport>.<car>.<yellow>
routing_keys = *.*.red
D O T S D E L I M I T E D R O U T I N G K E Y
A R E D R A C E M O T O R B I K E
T O P I C
A R E D R A C E M O T O R B I K E
vehicle
Exchange
type=topic
amq.gen-A7d
amq.gen-Sb4
Consumer1
Consumer2
P R O D U C E R
Produce
routing_keys = *.car.*
routing_keys = race.#
<race>.<motorbike>.<red>
routing_keys = *.*.red
D O T S D E L I M I T E D R O U T I N G K E Y
T O P I C
A R E D R A C E M O T O R B I K E
vehicle
Exchange
type=topic
amq.gen-A7d
amq.gen-Sb4
Consumer1
Consumer2
P R O D U C E R
Produce
routing_keys = *.car.*
routing_keys = race.#
<race>.<motorbike>.<red>
routing_keys = *.*.red
D O T S D E L I M I T E D R O U T I N G K E Y
A R E D R A C E C A R
T O P I C
A R E D R A C E C A R
vehicle
Exchange
type=topic
amq.gen-A7d
amq.gen-Sb4
Consumer1
Consumer2
P R O D U C E R
Produce
routing_keys = *.car.*
routing_keys = race.#
<race>.<car>.<red>
routing_keys = *.*.red
D O T S D E L I M I T E D R O U T I N G K E Y
T O P I C
A R E D R A C E C A R
vehicle
Exchange
type=topic
amq.gen-A7d
amq.gen-Sb4
Consumer1
Consumer2
P R O D U C E R
Produce
routing_keys = *.car.*
routing_keys = race.#
<race>.<car>.<red>
routing_keys = *.*.red
D O T S D E L I M I T E D R O U T I N G K E Y
A B L U E C I T Y VA N
T O P I C
A B L U E C I T Y VA N
vehicle
Exchange
type=topic
amq.gen-A7d
amq.gen-Sb4
Consumer1
Consumer2
P R O D U C E R
Produce
routing_keys = *.car.*
routing_keys = race.#
<city>.<van>.<blue>
routing_keys = *.*.red
D O T S D E L I M I T E D R O U T I N G K E Y
D I S C A R D E D
R E M E M B E R
P R O C E S S I N G Y O U R D ATA
A S Y N C H R O N O U S LY C A N B E D O N E E A S I LY
E V E N I N P H P
C A N M A K E Y O U R
( D E V ) L I F E H A P P I E R
Y O U R A P P L I C AT I O N
S T R O N G E R
Andrea Giuliano
@bit_shark
andreagiuliano.it
joind.in/11608
Please rate the talk!
C R E D I T S
• https://www.flickr.com/photos/rayofsun/9401226342
• https://www.flickr.com/photos/thereeljames/11376085194
• https://www.flickr.com/photos/ollily/359817111
• https://www.flickr.com/photos/legofenris/4004170937
• https://www.flickr.com/photos/bsabarnowl/10993445723
• https://www.flickr.com/photos/jpott/2984914512
• https://www.flickr.com/photos/kalexanderson/6231391820
• https://www.flickr.com/photos/a2gemma/1448178195
• https://www.flickr.com/photos/dubpics/5619966355
• https://www.flickr.com/photos/umbertofistarol/5747425870
• https://www.flickr.com/photos/streetcarl/6888965017
• https://www.flickr.com/photos/infomastern/12407730413
• https://www.flickr.com/photos/giuseppemilo/11817936944
• https://www.flickr.com/photos/avardwoolaver/7137096221

Mais conteúdo relacionado

Mais procurados

Doctype html publi
Doctype html publiDoctype html publi
Doctype html publi
Eddy_TKJ
 

Mais procurados (20)

Climbing the Abstract Syntax Tree (Forum PHP 2017)
Climbing the Abstract Syntax Tree (Forum PHP 2017)Climbing the Abstract Syntax Tree (Forum PHP 2017)
Climbing the Abstract Syntax Tree (Forum PHP 2017)
 
Doctype html publi
Doctype html publiDoctype html publi
Doctype html publi
 
Meteor - not just for rockstars
Meteor - not just for rockstarsMeteor - not just for rockstars
Meteor - not just for rockstars
 
The solution manual of c by robin
The solution manual of c by robinThe solution manual of c by robin
The solution manual of c by robin
 
Climbing the Abstract Syntax Tree (Midwest PHP 2020)
Climbing the Abstract Syntax Tree (Midwest PHP 2020)Climbing the Abstract Syntax Tree (Midwest PHP 2020)
Climbing the Abstract Syntax Tree (Midwest PHP 2020)
 
Climbing the Abstract Syntax Tree (PHP Russia 2019)
Climbing the Abstract Syntax Tree (PHP Russia 2019)Climbing the Abstract Syntax Tree (PHP Russia 2019)
Climbing the Abstract Syntax Tree (PHP Russia 2019)
 
Writing (Meteor) Code With Style
Writing (Meteor) Code With StyleWriting (Meteor) Code With Style
Writing (Meteor) Code With Style
 
Climbing the Abstract Syntax Tree (Bulgaria PHP 2016)
Climbing the Abstract Syntax Tree (Bulgaria PHP 2016)Climbing the Abstract Syntax Tree (Bulgaria PHP 2016)
Climbing the Abstract Syntax Tree (Bulgaria PHP 2016)
 
Climbing the Abstract Syntax Tree (DPC 2017)
Climbing the Abstract Syntax Tree (DPC 2017)Climbing the Abstract Syntax Tree (DPC 2017)
Climbing the Abstract Syntax Tree (DPC 2017)
 
Climbing the Abstract Syntax Tree (CodeiD PHP Odessa 2017)
Climbing the Abstract Syntax Tree (CodeiD PHP Odessa 2017)Climbing the Abstract Syntax Tree (CodeiD PHP Odessa 2017)
Climbing the Abstract Syntax Tree (CodeiD PHP Odessa 2017)
 
Climbing the Abstract Syntax Tree (PHP UK 2018)
Climbing the Abstract Syntax Tree (PHP UK 2018)Climbing the Abstract Syntax Tree (PHP UK 2018)
Climbing the Abstract Syntax Tree (PHP UK 2018)
 
Climbing the Abstract Syntax Tree (Southeast PHP 2018)
Climbing the Abstract Syntax Tree (Southeast PHP 2018)Climbing the Abstract Syntax Tree (Southeast PHP 2018)
Climbing the Abstract Syntax Tree (Southeast PHP 2018)
 
Climbing the Abstract Syntax Tree (IPC Fall 2017)
Climbing the Abstract Syntax Tree (IPC Fall 2017)Climbing the Abstract Syntax Tree (IPC Fall 2017)
Climbing the Abstract Syntax Tree (IPC Fall 2017)
 
Climbing the Abstract Syntax Tree (ScotlandPHP 2018)
Climbing the Abstract Syntax Tree (ScotlandPHP 2018)Climbing the Abstract Syntax Tree (ScotlandPHP 2018)
Climbing the Abstract Syntax Tree (ScotlandPHP 2018)
 
Interpret this... (PHPem 2016)
Interpret this... (PHPem 2016)Interpret this... (PHPem 2016)
Interpret this... (PHPem 2016)
 
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 2 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 2 of 5 by...Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 2 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 2 of 5 by...
 
Profiling Web Archives IIPC GA 2015
Profiling Web Archives IIPC GA 2015Profiling Web Archives IIPC GA 2015
Profiling Web Archives IIPC GA 2015
 
Climbing the Abstract Syntax Tree (PHP Developer Days Dresden 2018)
Climbing the Abstract Syntax Tree (PHP Developer Days Dresden 2018)Climbing the Abstract Syntax Tree (PHP Developer Days Dresden 2018)
Climbing the Abstract Syntax Tree (PHP Developer Days Dresden 2018)
 
Let's build a parser!
Let's build a parser!Let's build a parser!
Let's build a parser!
 
Program For Parsing2
Program For Parsing2Program For Parsing2
Program For Parsing2
 

Semelhante a Asynchronous data processing

Refactoring to symfony components
Refactoring to symfony componentsRefactoring to symfony components
Refactoring to symfony components
Michael Peacock
 
201412 seccon2014 オンライン予選(英語) write-up
201412 seccon2014 オンライン予選(英語) write-up201412 seccon2014 オンライン予選(英語) write-up
201412 seccon2014 オンライン予選(英語) write-up
恵寿 東
 
R57php 1231677414471772-2
R57php 1231677414471772-2R57php 1231677414471772-2
R57php 1231677414471772-2
ady36
 

Semelhante a Asynchronous data processing (20)

Fast api
Fast apiFast api
Fast api
 
PyLadies Talk: Learn to love the command line!
PyLadies Talk: Learn to love the command line!PyLadies Talk: Learn to love the command line!
PyLadies Talk: Learn to love the command line!
 
php[world] 2016 - You Don’t Need Node.js - Async Programming in PHP
php[world] 2016 - You Don’t Need Node.js - Async Programming in PHPphp[world] 2016 - You Don’t Need Node.js - Async Programming in PHP
php[world] 2016 - You Don’t Need Node.js - Async Programming in PHP
 
Refactoring to symfony components
Refactoring to symfony componentsRefactoring to symfony components
Refactoring to symfony components
 
PyData Barcelona - weather and climate data
PyData Barcelona - weather and climate dataPyData Barcelona - weather and climate data
PyData Barcelona - weather and climate data
 
Controlling Technical Debt with Continuous Delivery
Controlling Technical Debt with Continuous DeliveryControlling Technical Debt with Continuous Delivery
Controlling Technical Debt with Continuous Delivery
 
Serverless Functions and Vue.js
Serverless Functions and Vue.jsServerless Functions and Vue.js
Serverless Functions and Vue.js
 
Zend con 2016 - Asynchronous Prorgamming in PHP
Zend con 2016 - Asynchronous Prorgamming in PHPZend con 2016 - Asynchronous Prorgamming in PHP
Zend con 2016 - Asynchronous Prorgamming in PHP
 
OSDC 2017 - Sebastian Saemann - Developing a saa s platform based on open sou...
OSDC 2017 - Sebastian Saemann - Developing a saa s platform based on open sou...OSDC 2017 - Sebastian Saemann - Developing a saa s platform based on open sou...
OSDC 2017 - Sebastian Saemann - Developing a saa s platform based on open sou...
 
OSDC 2017 | Developing a SaaS platform based on Open Source Software by Sebas...
OSDC 2017 | Developing a SaaS platform based on Open Source Software by Sebas...OSDC 2017 | Developing a SaaS platform based on Open Source Software by Sebas...
OSDC 2017 | Developing a SaaS platform based on Open Source Software by Sebas...
 
201412 seccon2014 オンライン予選(英語) write-up
201412 seccon2014 オンライン予選(英語) write-up201412 seccon2014 オンライン予選(英語) write-up
201412 seccon2014 オンライン予選(英語) write-up
 
Evolving the Android Core with Aspects
Evolving the Android Core with AspectsEvolving the Android Core with Aspects
Evolving the Android Core with Aspects
 
Form validation server side
Form validation server side Form validation server side
Form validation server side
 
R57php 1231677414471772-2
R57php 1231677414471772-2R57php 1231677414471772-2
R57php 1231677414471772-2
 
Dr Strangler and Mr Hype - Strangler pattern w praktyce
Dr Strangler and Mr Hype - Strangler pattern w praktyceDr Strangler and Mr Hype - Strangler pattern w praktyce
Dr Strangler and Mr Hype - Strangler pattern w praktyce
 
Strangler Pattern in practice @PHPers Day 2019
Strangler Pattern in practice @PHPers Day 2019Strangler Pattern in practice @PHPers Day 2019
Strangler Pattern in practice @PHPers Day 2019
 
PyParis - weather and climate data
PyParis - weather and climate dataPyParis - weather and climate data
PyParis - weather and climate data
 
Pane'ramik - Effective Marketing with Video
Pane'ramik - Effective Marketing with VideoPane'ramik - Effective Marketing with Video
Pane'ramik - Effective Marketing with Video
 
Sap snc configuration
Sap snc configurationSap snc configuration
Sap snc configuration
 
Testing TYPO3 Applications
Testing TYPO3 ApplicationsTesting TYPO3 Applications
Testing TYPO3 Applications
 

Mais de Andrea Giuliano

Mais de Andrea Giuliano (10)

CQRS, ReactJS, Docker in a nutshell
CQRS, ReactJS, Docker in a nutshellCQRS, ReactJS, Docker in a nutshell
CQRS, ReactJS, Docker in a nutshell
 
Go fast in a graph world
Go fast in a graph worldGo fast in a graph world
Go fast in a graph world
 
Concurrent test frameworks
Concurrent test frameworksConcurrent test frameworks
Concurrent test frameworks
 
Index management in depth
Index management in depthIndex management in depth
Index management in depth
 
Consistency, Availability, Partition: Make Your Choice
Consistency, Availability, Partition: Make Your ChoiceConsistency, Availability, Partition: Make Your Choice
Consistency, Availability, Partition: Make Your Choice
 
Think horizontally @Codemotion
Think horizontally @CodemotionThink horizontally @Codemotion
Think horizontally @Codemotion
 
Index management in shallow depth
Index management in shallow depthIndex management in shallow depth
Index management in shallow depth
 
Everything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to askEverything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to ask
 
Stub you!
Stub you!Stub you!
Stub you!
 
Let's test!
Let's test!Let's test!
Let's test!
 

Último

Chintamani Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore ...
Chintamani Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore ...Chintamani Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore ...
Chintamani Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore ...
amitlee9823
 
Call Girls Bannerghatta Road Just Call 👗 7737669865 👗 Top Class Call Girl Ser...
Call Girls Bannerghatta Road Just Call 👗 7737669865 👗 Top Class Call Girl Ser...Call Girls Bannerghatta Road Just Call 👗 7737669865 👗 Top Class Call Girl Ser...
Call Girls Bannerghatta Road Just Call 👗 7737669865 👗 Top Class Call Girl Ser...
amitlee9823
 
CHEAP Call Girls in Saket (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Saket (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Saket (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Saket (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
Call Girls Jalahalli Just Call 👗 7737669865 👗 Top Class Call Girl Service Ban...
Call Girls Jalahalli Just Call 👗 7737669865 👗 Top Class Call Girl Service Ban...Call Girls Jalahalli Just Call 👗 7737669865 👗 Top Class Call Girl Service Ban...
Call Girls Jalahalli Just Call 👗 7737669865 👗 Top Class Call Girl Service Ban...
amitlee9823
 
Call Girls In Shalimar Bagh ( Delhi) 9953330565 Escorts Service
Call Girls In Shalimar Bagh ( Delhi) 9953330565 Escorts ServiceCall Girls In Shalimar Bagh ( Delhi) 9953330565 Escorts Service
Call Girls In Shalimar Bagh ( Delhi) 9953330565 Escorts Service
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
FESE Capital Markets Fact Sheet 2024 Q1.pdf
FESE Capital Markets Fact Sheet 2024 Q1.pdfFESE Capital Markets Fact Sheet 2024 Q1.pdf
FESE Capital Markets Fact Sheet 2024 Q1.pdf
MarinCaroMartnezBerg
 
Call Girls Hsr Layout Just Call 👗 7737669865 👗 Top Class Call Girl Service Ba...
Call Girls Hsr Layout Just Call 👗 7737669865 👗 Top Class Call Girl Service Ba...Call Girls Hsr Layout Just Call 👗 7737669865 👗 Top Class Call Girl Service Ba...
Call Girls Hsr Layout Just Call 👗 7737669865 👗 Top Class Call Girl Service Ba...
amitlee9823
 
Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...
Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...
Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...
amitlee9823
 
Call Girls In Bellandur ☎ 7737669865 🥵 Book Your One night Stand
Call Girls In Bellandur ☎ 7737669865 🥵 Book Your One night StandCall Girls In Bellandur ☎ 7737669865 🥵 Book Your One night Stand
Call Girls In Bellandur ☎ 7737669865 🥵 Book Your One night Stand
amitlee9823
 

Último (20)

Sampling (random) method and Non random.ppt
Sampling (random) method and Non random.pptSampling (random) method and Non random.ppt
Sampling (random) method and Non random.ppt
 
Chintamani Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore ...
Chintamani Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore ...Chintamani Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore ...
Chintamani Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore ...
 
(NEHA) Call Girls Katra Call Now 8617697112 Katra Escorts 24x7
(NEHA) Call Girls Katra Call Now 8617697112 Katra Escorts 24x7(NEHA) Call Girls Katra Call Now 8617697112 Katra Escorts 24x7
(NEHA) Call Girls Katra Call Now 8617697112 Katra Escorts 24x7
 
Call Girls Bannerghatta Road Just Call 👗 7737669865 👗 Top Class Call Girl Ser...
Call Girls Bannerghatta Road Just Call 👗 7737669865 👗 Top Class Call Girl Ser...Call Girls Bannerghatta Road Just Call 👗 7737669865 👗 Top Class Call Girl Ser...
Call Girls Bannerghatta Road Just Call 👗 7737669865 👗 Top Class Call Girl Ser...
 
BDSM⚡Call Girls in Mandawali Delhi >༒8448380779 Escort Service
BDSM⚡Call Girls in Mandawali Delhi >༒8448380779 Escort ServiceBDSM⚡Call Girls in Mandawali Delhi >༒8448380779 Escort Service
BDSM⚡Call Girls in Mandawali Delhi >༒8448380779 Escort Service
 
Digital Advertising Lecture for Advanced Digital & Social Media Strategy at U...
Digital Advertising Lecture for Advanced Digital & Social Media Strategy at U...Digital Advertising Lecture for Advanced Digital & Social Media Strategy at U...
Digital Advertising Lecture for Advanced Digital & Social Media Strategy at U...
 
CHEAP Call Girls in Saket (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Saket (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Saket (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Saket (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Call Girls Jalahalli Just Call 👗 7737669865 👗 Top Class Call Girl Service Ban...
Call Girls Jalahalli Just Call 👗 7737669865 👗 Top Class Call Girl Service Ban...Call Girls Jalahalli Just Call 👗 7737669865 👗 Top Class Call Girl Service Ban...
Call Girls Jalahalli Just Call 👗 7737669865 👗 Top Class Call Girl Service Ban...
 
Accredited-Transport-Cooperatives-Jan-2021-Web.pdf
Accredited-Transport-Cooperatives-Jan-2021-Web.pdfAccredited-Transport-Cooperatives-Jan-2021-Web.pdf
Accredited-Transport-Cooperatives-Jan-2021-Web.pdf
 
Call Girls In Shalimar Bagh ( Delhi) 9953330565 Escorts Service
Call Girls In Shalimar Bagh ( Delhi) 9953330565 Escorts ServiceCall Girls In Shalimar Bagh ( Delhi) 9953330565 Escorts Service
Call Girls In Shalimar Bagh ( Delhi) 9953330565 Escorts Service
 
April 2024 - Crypto Market Report's Analysis
April 2024 - Crypto Market Report's AnalysisApril 2024 - Crypto Market Report's Analysis
April 2024 - Crypto Market Report's Analysis
 
FESE Capital Markets Fact Sheet 2024 Q1.pdf
FESE Capital Markets Fact Sheet 2024 Q1.pdfFESE Capital Markets Fact Sheet 2024 Q1.pdf
FESE Capital Markets Fact Sheet 2024 Q1.pdf
 
Generative AI on Enterprise Cloud with NiFi and Milvus
Generative AI on Enterprise Cloud with NiFi and MilvusGenerative AI on Enterprise Cloud with NiFi and Milvus
Generative AI on Enterprise Cloud with NiFi and Milvus
 
Carero dropshipping via API with DroFx.pptx
Carero dropshipping via API with DroFx.pptxCarero dropshipping via API with DroFx.pptx
Carero dropshipping via API with DroFx.pptx
 
Call Girls Hsr Layout Just Call 👗 7737669865 👗 Top Class Call Girl Service Ba...
Call Girls Hsr Layout Just Call 👗 7737669865 👗 Top Class Call Girl Service Ba...Call Girls Hsr Layout Just Call 👗 7737669865 👗 Top Class Call Girl Service Ba...
Call Girls Hsr Layout Just Call 👗 7737669865 👗 Top Class Call Girl Service Ba...
 
Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...
Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...
Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...
 
Capstone Project on IBM Data Analytics Program
Capstone Project on IBM Data Analytics ProgramCapstone Project on IBM Data Analytics Program
Capstone Project on IBM Data Analytics Program
 
Call Girls In Bellandur ☎ 7737669865 🥵 Book Your One night Stand
Call Girls In Bellandur ☎ 7737669865 🥵 Book Your One night StandCall Girls In Bellandur ☎ 7737669865 🥵 Book Your One night Stand
Call Girls In Bellandur ☎ 7737669865 🥵 Book Your One night Stand
 
Predicting Loan Approval: A Data Science Project
Predicting Loan Approval: A Data Science ProjectPredicting Loan Approval: A Data Science Project
Predicting Loan Approval: A Data Science Project
 
ALSO dropshipping via API with DroFx.pptx
ALSO dropshipping via API with DroFx.pptxALSO dropshipping via API with DroFx.pptx
ALSO dropshipping via API with DroFx.pptx
 

Asynchronous data processing

  • 1. A S Y N C H R O N O U S D ATA P R O C E S S I N G A N D R E A G I U L I A N O @bit_shark # C A K E F E S T
  • 2. T H E P R O B L E M
  • 3. P R O D U C T C ATA L O G G E N E R AT O R • 30k+ records in db representing products • dispose records in pages (with a certain order) • generate a 300+ pages PDF catalog T H E P R O B L E M
  • 4. H E AV Y O P E R AT I O N S T O D O H E R E T H E P R O B L E M
  • 5. U S E R S D O N ’ T WA N T T O WA I T T H E P R O B L E M
  • 6. U S E R S D O N ’ T WA N T T O WA I T T H E P R O B L E M A N D I F T H E Y H AV E T O T H E Y D O N ’ T WA N T T O G E T S T U C K !
  • 7. T H E P R O B L E M S Y N C H R O N Y time process A process B Request Response blocked
  • 8. T H E N E E D S
  • 9. P R E V E N T T I M E O U T T H E N E E D S
  • 10. E V E N T U A L LY D E L I V E RY T H E N E E D S “sooner or later your job will be processed.”
  • 11. “ E V E R I T H I N G ’ S G O N N A B E A L R I G H T ” N O T I F I C AT I O N T H E N E E D S
  • 12. T H E N E E D S A S Y N C H R O N Y time process A process B Request
  • 13. I N T E R O P E R A B I L I T Y T H E N E E D S
  • 14. A D VA N C E D M E S S A G E Q U E U I N G P R O T O C O L T H E S O L U T I O N
  • 15. H O W D O E S I T W O R K A M Q P P R O D U C E R C O N S U M E R Produce Consumes B R O K E R
  • 16. H O W D O E S I T W O R K A M Q P P R O D U C E R C O N S U M E R Produce Exchange Consumes B R O K E R
  • 17. H O W D O E S I T W O R K A M Q P P R O D U C E R C O N S U M E R Produce Exchange Routes Consumes B R O K E R
  • 18. H O W D O E S I T W O R K A M Q P P R O D U C E R C O N S U M E R Produce Exchange Queue Routes Consumes B R O K E R
  • 19. T H R O U G H C O M P O S E R I N S TA L L A M Q P L I B R A RY {          "require":  {                  "videlalvaro/php-­‐amqplib":  "@stable",                    ...          }   }   $ composer.phar install
  • 20. D I F F E R E N T S C E N A R I O S
  • 21. P R O D U C E R / C O N S U M E R S C E N A R I O
  • 22. S C E N A R I O P R O D U C E R / C O N S U M E R P R O D U C E R C O N S U M E R Q U E U E
  • 23. S C E N A R I O P R O D U C E R / C O N S U M E R use  PhpAmqpLibConnectionAMQPConnection;   use  PhpAmqpLibMessageAMQPMessage;       $connection  =  new  AMQPConnection(HOST,  PORT,  USER,  PASSWORD);   $channel  =  $connection-­‐>channel(); S E T T I N G U P C O N N E C T I O N C R E AT E A C H A N N E L
  • 24. S C E N A R I O P R O D U C E R / C O N S U M E R P R O D U C E R Q U E U E                                                                        passive    durable  exclusive  auto-­‐delete   $channel-­‐>queue_declare('catalog',  false,    false,    false,        false);         foreach  ($catalog-­‐>getPages()  as  $page)  {          $message  =  new  AMQPMessage($page);          $channel-­‐>basic_publish($message,  '',  'catalog');   }       $channel-­‐>close();   $connection-­‐>close();
  • 25. S C E N A R I O P R O D U C E R / C O N S U M E R C O N S U M E R Q U E U E $connection  =  new  AMQPConnection(HOST,  PORT,  USER,  PASSWORD);   $channel  =  $connection-­‐>channel();       $channel-­‐>queue_declare('catalog',  false,  false,  false,  false);       $callback  =  function($msg)  {          $msg-­‐>body-­‐>generatePdf();   };       $channel-­‐>basic_consume('catalog',  '',  false,  true,  false,  false,  $callback);       while(count($channel-­‐>callbacks))  {          $channel-­‐>wait();   }       $channel-­‐>close();   $connection-­‐>close();  
  • 26. S C E N A R I O M U LT I P L E C O N S U M E R S P R O D U C E R C O N S U M E R Q U E U E C O N S U M E R …
  • 27. S C E N A R I O M U LT I P L E C O N S U M E R S P R O D U C E R C O N S U M E R Q U E U E C O N S U M E R … parallelize work easy scalability
  • 28. C O N S U M E R S C A N D I E
  • 29. M E S S A G E A K N O W L E D G E M E N T
  • 30. S A F E T Y M E S S A G E A C K S $callback  =  function($msg){          $msg-­‐>body-­‐>generatePdf();          $msg-­‐>delivery_info['channel']-­‐>basic_ack($msg-­‐>delivery_info['delivery_tag']);   };   ! $channel-­‐>basic_consume('catalog',  '',  false,  false,  false,  false,  $callback); S W I T C H A C K O N
  • 31. D O N ’ T F O R G E T T O S E N D A C K S
  • 32. T H E B R O K E R C A N D I E
  • 33. D U R A B I L I T Y
  • 34. D U R A B I L I T Y M A R K T H E Q U E U E A N D T H E C H A N N E L $channel-­‐>queue_declare('catalog',  false,  true,  false,  false); In order to achieve durability $message  =  new  AMQPMessage($data,                #the  message  is  now  persistent                array('delivery_mode'  =>  2)                  ); the queue must be declared durable the message must be marked as persistent
  • 35. Q O S P O L I T I C S
  • 36. Q O S P O L I T I C A B E FA I R C O N S U M E R C O N S U M E R for certain instances of the Round Robin dispatching B R O K E R #1 #3 #5 #2 #4 #6
  • 37. Q O S P O L I T I C S B E FA I R $channel-­‐>basic_qos(null,  1,  null); C O N S U M E R C O N S U M E R the broker sends messages only when it receives acks B R O K E R #1 #3 #3 #2#4
  • 38. P U B L I S H / S U B S C R I B E S C E N A R I O
  • 39. S C E N A R I O P U B L I S H / S U B S C R I B E chatRoom FA N O U T E X C H A N G E $connection  =  new  AMQPConnection(HOST,  PORT,  USER,  PASSWORD);   $channel  =  $connection-­‐>channel();       $channel-­‐>exchange_declare('chatRoom',  'fanout',  false,  false,  false); Exchange … Setting up the connection and declare the fanout exchange
  • 40. S C E N A R I O P U B L I S H / S U B S C R I B E chatRoom Exchange … $data  =  getAMessageToSendInTheRoom();   $msg  =  new  AMQPMessage($data);       $channel-­‐>basic_publish($msg,  'chatRoom');       $channel-­‐>close();   $connection-­‐>close();   P R O D U C E R Produce Publishing a message to the exchange
  • 41. N O W I T ’ S T H E S U B S C R I B E R ’ S T U R N
  • 42. S C E N A R I O P U B L I S H / S U B S C R I B E chatRoom Q U E U E B I N D I N G Exchange … //connection  setted  up   ! list($queue_name,  ,)  =  $channel-­‐>queue_declare("",  false,  false,  true,  false);       $channel-­‐>queue_bind($queue_name,  'chatRoom'); Bind the Queue on the Exchange amq.gen-A7d bind bind amq.gen-Sb4
  • 43. S C E N A R I O P U B L I S H / S U B S C R I B E chatRoom Exchange … amq.gen-A7d $channel-­‐>basic_consume($queue_name,                    '',                    false,                    true,                    false,                    false,                    'readMessage');       $channel-­‐>close();   $connection-­‐>close();   C O N S U M E R Consumes amq.gen-Sb4
  • 44. R O U T I N G S C E N A R I O
  • 45. S C E N A R I O R O U T I N G chatRoom Exchange type=direct … amq.gen-A7d amq.gen-Sb4 Consumer1 ConsumerN P R O D U C E R Produce routing_keys = friends routing_keys = friends, colleagues $channel-­‐>exchange_declare('chatRoom',  'direct',  false,  false,  false);
  • 46. S C E N A R I O R O U T I N G chatRoom Exchange type=direct P R O D U C E R Produce Producing messages //connection  setted  up   ! $channel-­‐>exchange_declare('chatRoom',                      'direct',                      false,                      false,                      false);         $data  =  getAMessageToSendInTheRoom('friends');   $msg  =  new  AMQPMessage($data);       $channel-­‐>basic_publish($msg,  'chatRoom',  'friends');       $channel-­‐>close();   $connection-­‐>close();  
  • 47. S C E N A R I O R O U T I N G //connection  setted  up   //exchange  setted  up   //$queue_name  is  a  system  generated  queue  name   ! $rooms  =  array('friends',  'colleagues');       foreach($rooms  as  $room)  {          $channel-­‐>queue_bind($queue_name,  'chatRoom',  $room);   }       $channel-­‐>basic_consume($queue_name,  '',  false,  true,  false,  false,  'readMessage');       $channel-­‐>close();   $connection-­‐>close();   Bind a Consumer on different routing keys and consuming messages chatRoom amq.gen-Sb4 Consumer routing_keys = friends, colleagues
  • 48. T O P I C S C E N A R I O
  • 49. G O F U R T H E R T O P I C $channel-­‐>exchange_declare('vehicle',  'topic',  false,  false,  false); vehicle Exchange type=topic amq.gen-A7d amq.gen-Sb4 Consumer1 Consumer2 P R O D U C E R Produce routing_keys = *.car.* routing_keys = race.# <type>.<vehicle>.<colour> routing_keys = *.*.red D O T S D E L I M I T E D R O U T I N G K E Y
  • 50. A Y E L L O W S P O R T C A R
  • 51. T O P I C A Y E L L O W S P O R T C A R vehicle Exchange type=topic amq.gen-A7d amq.gen-Sb4 Consumer1 Consumer2 P R O D U C E R Produce routing_keys = *.car.* routing_keys = race.# <sport>.<car>.<yellow> routing_keys = *.*.red D O T S D E L I M I T E D R O U T I N G K E Y
  • 52. T O P I C A Y E L L O W S P O R T C A R vehicle Exchange type=topic amq.gen-A7d amq.gen-Sb4 Consumer1 Consumer2 P R O D U C E R Produce routing_keys = *.car.* routing_keys = race.# <sport>.<car>.<yellow> routing_keys = *.*.red D O T S D E L I M I T E D R O U T I N G K E Y
  • 53. A R E D R A C E M O T O R B I K E
  • 54. T O P I C A R E D R A C E M O T O R B I K E vehicle Exchange type=topic amq.gen-A7d amq.gen-Sb4 Consumer1 Consumer2 P R O D U C E R Produce routing_keys = *.car.* routing_keys = race.# <race>.<motorbike>.<red> routing_keys = *.*.red D O T S D E L I M I T E D R O U T I N G K E Y
  • 55. T O P I C A R E D R A C E M O T O R B I K E vehicle Exchange type=topic amq.gen-A7d amq.gen-Sb4 Consumer1 Consumer2 P R O D U C E R Produce routing_keys = *.car.* routing_keys = race.# <race>.<motorbike>.<red> routing_keys = *.*.red D O T S D E L I M I T E D R O U T I N G K E Y
  • 56. A R E D R A C E C A R
  • 57. T O P I C A R E D R A C E C A R vehicle Exchange type=topic amq.gen-A7d amq.gen-Sb4 Consumer1 Consumer2 P R O D U C E R Produce routing_keys = *.car.* routing_keys = race.# <race>.<car>.<red> routing_keys = *.*.red D O T S D E L I M I T E D R O U T I N G K E Y
  • 58. T O P I C A R E D R A C E C A R vehicle Exchange type=topic amq.gen-A7d amq.gen-Sb4 Consumer1 Consumer2 P R O D U C E R Produce routing_keys = *.car.* routing_keys = race.# <race>.<car>.<red> routing_keys = *.*.red D O T S D E L I M I T E D R O U T I N G K E Y
  • 59. A B L U E C I T Y VA N
  • 60. T O P I C A B L U E C I T Y VA N vehicle Exchange type=topic amq.gen-A7d amq.gen-Sb4 Consumer1 Consumer2 P R O D U C E R Produce routing_keys = *.car.* routing_keys = race.# <city>.<van>.<blue> routing_keys = *.*.red D O T S D E L I M I T E D R O U T I N G K E Y
  • 61. D I S C A R D E D
  • 62.
  • 63. R E M E M B E R
  • 64. P R O C E S S I N G Y O U R D ATA A S Y N C H R O N O U S LY C A N B E D O N E E A S I LY
  • 65. E V E N I N P H P
  • 66. C A N M A K E Y O U R ( D E V ) L I F E H A P P I E R
  • 67. Y O U R A P P L I C AT I O N S T R O N G E R
  • 70. C R E D I T S • https://www.flickr.com/photos/rayofsun/9401226342 • https://www.flickr.com/photos/thereeljames/11376085194 • https://www.flickr.com/photos/ollily/359817111 • https://www.flickr.com/photos/legofenris/4004170937 • https://www.flickr.com/photos/bsabarnowl/10993445723 • https://www.flickr.com/photos/jpott/2984914512 • https://www.flickr.com/photos/kalexanderson/6231391820 • https://www.flickr.com/photos/a2gemma/1448178195 • https://www.flickr.com/photos/dubpics/5619966355 • https://www.flickr.com/photos/umbertofistarol/5747425870 • https://www.flickr.com/photos/streetcarl/6888965017 • https://www.flickr.com/photos/infomastern/12407730413 • https://www.flickr.com/photos/giuseppemilo/11817936944 • https://www.flickr.com/photos/avardwoolaver/7137096221