SlideShare a Scribd company logo
Intro
Lifestory:
Production monolith
migration to Swoole!
● What existing problems need to solve?
● Why choose Swoole?
● How solve it with Swoole?
● What unexpected troubles could happens?
● Show methods to avoid then (or not?)
● Talk about theory
● Examples in a context of a real project
Intro
Side Effects of
- PHP no dying (long-lived)
- Concurrency Async
- Shared Memory access
Intro
● ZF2 / Laminas / Mezzio / PSR-15 / ..
● PHP 5.6 -> … -> 7.4 --> 8.0 + swoole
● PostgreSQL / ElasticSearch Typesense / Redis / RabbitMQ / PubSub
● Docker / k8s / autoscale / Google Cloud
● Files: 2.5k, LOC: 200k, LLOC: 30k
Intro. About project
Intro. About project
Current AVG metrics:
- GA online users: ~3500
- API RPS: ~200
- DB transactions: ~3000/sec
- Products count: ~25kk
Consuming resources:
- PHP: 60 vCPU
- ElasticSearch: 40 vCPU
- PostgreSQL: 16 vCPU
- Others: 20 vCPU
● Not optimized resources usage.
● Hard tuning horizontal scale.
● Over-complicated infrastructure
● Not well performance (TTFB)
Why? Problems
Database
PHP PHP
PHP PHP
Elastic Elastic
Elastic
Other
4x times
● Not optimized resources usage.
● Hard tuning horizontal scale.
● Over-complicated infrastructure
● Not well performance (TTFB)
Why? Problems
PHP
4 vCPU
PHP
16 vCPU
VS
● Not optimized resources usage.
● Hard tuning horizontal scale.
● Over-complicated infrastructure
● Not well performance (TTFB)
Why? Problems
Docker, k8s, Terraform, Helm, GitHub
Actions, Envs: prod+stage+devs+local, Go,
Typescript
● Not optimized resources usage.
● Hard tuning horizontal scale.
● Over-complicated infrastructure
● Not well performance (TTFB)
Why? Problems
● ASYNC entire ecosystem
● Performance
● Easy to start
- Coroutine based concurrent asynchronous IO
- Event Loop
- Process management
- In-memory storage and management
- Async TCP/UDP/HTTP/WebSocket/HTTP2/FastCGI client
and servers
- Async Task API
- Channels, Locks, Timer, Scheduler
NO PECL: ext-pcntl, ext-pthreads, ext-event
Why Swoole?
Milestone 1: PHP no die
● Run HTTP Server
○ replace NGINX+FPM
○ simplify infrastructure (less DevOps, easy building & k8s configs)
○ change (unified) operations: CI / CD / local env
● Prepare bootstrap
● Implement best practices in shared memory usage to avoid side-effects
Plan
● Server Mode: SWOOLE_PROCESS / SWOOLE_BASE
● Dispatch Mode: 1-9 (Round-Robin, Fixed, Preemptive, etc)
● Worker Num: 1-1000 (CPU*2)
● Max Request: 0-XXX (0)
Other Options: Limits, Timeouts, Memory buffers...
php bin/http-server.php
Swoole HTTP Server
https://www.swoole.co.uk/docs/modules/swoole-server/configuration
MUST SEE:
<?php
$server = new SwooleHTTPServer("127.0.0.1", 9501);
$server->on('Request', function(Swoole/Server/Request $request, Swoole/Server/Response $response)
{
$response->end('<h1>Hello World!</h1>');
});
$server->start();
● Scan config files, env, run reflection, attributes, build DI, generate proxy, warm caches:
● NO NEED cache layer anymore
● NOW it before real start http server
(if no traffic: readiness probe=negative)
PSR-7 HTTP Messages
PSR-15 Middleware
PSR-11 Container
bootstrap in master
http request in worker process
Bootstrap app once
fork state
What are the problems?
- NO SUPER GLOBALS ($_SERVER, ...)
- No PHP Session (it is CLI SAPI)
- Stateful services that should mutate on each request
- DI containers - global state too.
Shared Memory
Any wrong example?
Shared Memory
https://github.com/chrisguitarguy/RequestIdBundle/blob/main/src/EventListener/RequestIdListener.php
public function onRequest(RequestEvent $event) : void
{
if (!$this->isMainRequest ($event)) {
return;
}
$req = $event->getRequest();
if ($this->trustRequest && ($id = $req->headers->get($this->requestHeader )))
{
$this->idStorage->setRequestId ($id);
return;
}
if ($id = $this->idStorage->getRequestId ()) {
$req->headers->set($this->requestHeader , $id);
return;
}
$id = $this->idGenerator ->generate();
$req->headers->set($this->requestHeader , $id);
$this->idStorage->setRequestId ($id);
}
Empty storage - no return
Generate NEW
Saving to storage
1
HTTP REQUEST:
Any wrong example?
Shared Memory
public function onRequest(RequestEvent $event) : void
{
if (!$this->isMainRequest ($event)) {
return;
}
$req = $event->getRequest();
if ($this->trustRequest && ($id = $req->headers->get($this->requestHeader )))
{
$this->idStorage->setRequestId ($id);
return;
}
if ($id = $this->idStorage->getRequestId ()) {
$req->headers->set($this->requestHeader , $id);
return;
}
$id = $this->idGenerator ->generate();
$req->headers->set($this->requestHeader , $id);
$this->idStorage->setRequestId ($id);
}
2
HTTP REQUEST:
Now has ID in storage
THE END
Dead code
https://github.com/chrisguitarguy/RequestIdBundle/blob/main/src/EventListener/RequestIdListener.php
Shared Memory
HTTP Server options:
Max Request: 100
What if...
Then…
In logs request ID is changed.
Best practices:
- Middlewares, Factories, Proxies, Delegators
Shared Memory
use PsrHttpMessageResponseInterface
;
use PsrHttpMessageServerRequestInterface
;
use PsrHttpServerRequestHandlerInterface
;
use PsrLogLoggerInterface
;
class SomeHandler implements RequestHandlerInterface
{
public function __construct(
private Closure $appServiceFactory
,
private LoggerInterface $logger
) {}
// Idempotent method!!!
public function handle(ServerRequestInterface $request) : ResponseInterface
{
$logger = clone $this->logger;
$logger->getProcessor(
'RequestID')->setRequestId(
$request->getAttribute(
'RequestID'));
$appService = ($this->appServiceFactory)(
$logger);
return new JsonResponse($appService->createBook())
;
}
}
Memory leaks
… in Doctrine ORM :(
Shared Memory
https://alejandrocelaya.blog/2019/11/04/how-to-properly-handle-a-doctrine-entity-manager-on-an-expressive-appli
cation-served-with-swoole/
use DoctrineORMDecoratorEntityManagerDecorator as
EMD;
class ReopeningEntityManager extends EMD
{
private $createEm;
public function __construct (callable $createEm)
{
parent::__construct($createEm());
$this->createEm = $createEm;
}
public function open(): void
{
if (! $this->wrapped->isOpen()) {
$this->wrapped = ($this->createEm)();
}
}
class CloseDbConnectionMiddleware implements
MiddlewareInterface
{
public function __construct(
private ReopeningEntityManager $em)
{}
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
) : ResponseInterface
{
$this->em->open() ;
try {
return $handler->handle($request);
} finally {
$this->em->getConnection()->close() ;
$this->em->clear() ;
}
}
}
Saved in DI
Shared Memory
Memory leaks
BUT WHERE???
abstract class EntityManagerDecorator extends
ObjectManagerDecorator
{
/** @var EntityManagerInterface */
protected $wrapped;
public function __construct (EntityManagerInterface $wrapped)
{
$this->wrapped = $wrapped;
}
public function getRepository ($className)
{
return $this->wrapped->getRepository ($className);
}
public function getRepository ($entityName )
{
return $this->repositoryFactory ->getRepository ($this,
$entityName );
}
Somewhere far far away
in EntityManager
PROBLEMS DUE TO: timeouts / lifecycles
Avoid: Stateful convert to stateless
Connections
$redis = $di->get(Redis::class); // FactoryRedis: $redis->connect(...);
$redis->get('KEY1');
$redisFactory = $di->get(RedisFactory::
class);
$redisFactory()->get(‘KEY1’); // + close connect in desctructor
Request Wrapper/Delegator:
new/refresh state on each request
OR
Milestone 2: ASYNC
● Async theory
● Using coroutines
● Non-blocked IO solutions
● Concurrency problems review
● Again memory leaks
● GET /some/action1/ SELECT sleep(1);
○ 1 worker = 1 req/sec
○ 2 worker = 2 req/sec
● GET /some/action2/ fibonacci(30);
○ 1 worker = 1 req/sec
○ 2 worker = depends on CPU cores
Why/What async?
Try benchmark this:
● GET /some/action1/ SELECT sleep(1);
○ 1 worker = 1 req/sec
○ 2 worker = 2 req/sec
● GET /some/action2/ fibonacci(30);
○ 1 worker = 1 req/sec
○ 2 worker = depends on CPU cores
MIX 50/50 = 1 req/sec
50% CPU
Why/What async?
Try benchmark this:
Now enable coroutines: http server options: .
'enable_coroutine' => true,
Why/What async?
● GET /some/action1/
○ 1 worker = 10000 req/sec
○ 2 worker = 10000 req/sec
● GET /some/action2/
○ 1 worker = 1 req/sec
○ 2 worker = depends on CPU cores
Now enable coroutines: http server options: .
'enable_coroutine' => true,
Why/What async?
● GET /some/action1/
○ 1 worker = 10000 req/sec
○ 2 worker = 10000 req/sec
● GET /some/action2/
○ 1 worker = 1 req/sec
○ 2 worker = depends on CPU cores
MIX 50/50 = 2 req/sec
100% CPU
go(function () { // FIRST CO
echo '1';
go(function () { // SECOND CO
echo '2';
co::sleep(3); // IO (in 2 CO), will return in 3 sec
echo '6';
go(function () { // THIRD CO
echo '7';
co::sleep(2); // IO
echo "9n";
}); // END THIRD
echo '8';
}); // END SECOND
echo '3';
co::sleep(1); // Again IO but in 1 CO
echo '5';
}); // END FIRST CO
echo '4';
Coroutines
1
2
3
4
5
Coroutines
https://www.swoole.co.uk/docs/modules/swoole-runtime-flags
Swoole Hooks
Coroutine Clients:
● TCP/UDP
● HTTP
● HTTP2
● Socket
● FastCGI
● Redis
● MySQL
● Postgresql
Runtime HOOKS:
● Coroutine support (any IO libraries based on php_stream):
○ Redis (phpredis) or (predis)
○ MySQL (mysqlnd) PDO and MySQLi
○ PHP SOAP
○ file_get_contents, fopen and many more file I/O operations
○ stream_socket_client functions
○ fsockopen
○ CURL with libcurl
● Libraries without coroutine support:
○ MySQL with libmysqlclient
○ MongoDB with mongo-c-client
○ pdo_pgsql, pdo_ori, pdo_odbc, pdo_firebird, php-amqp
VS
Non-blocked IO
$swooleServer->onRequest: go($this->requestHandler);
--------------------------------------------------------------------------
non-blocked: multiple requests in same time/code
Concurrency
function onRequest() {
$class = $di->get(stdClass:class);
if ($class->some === null) {
$class->some = 123;
}
sleep(2);
// && some logic
$class->some = null;
}
First request awaiting here
We expected clean in request end
http server options: .
'enable_coroutine' => true,
$swooleServer->onRequest: go($this->requestHandler);
--------------------------------------------------------------------------
non-blocked: multiple requests in same time/code
Concurrency
function onRequest() {
$class = $di->get(stdClass:class);
if ($class->some === null) {
$class->some = 123;
}
sleep(2);
// && some logic
$class->some = null;
}
First request awaiting here
We expected clean in request end
EPIC FAIL! in second request
http server options: .
'enable_coroutine' => true,
Request Wrapper/Delegator: new/refresh state on each request
Uncaught SwooleError: Socket# has already been
bound to another coroutine
Connections. Again?
$http = new SwooleHttpServer( '0.0.0.0', '80', SWOOLE_PROCESS) ;
$http->on('request', function (SwooleHttpRequest $request, SwooleHttpResponse $response)
{
if (empty($redis)) {
$redis = new Redis();
$redis->connect('127.0.0.1' , 6379);
$redis->select(1);
$redis->setOption(Redis::OPT_SERIALIZER , Redis::SERIALIZER_PHP) ;
}
try {
$redisJson = $redis->get('key');
} catch (Exception $e) {
// SWOOLE ERROR HERE !
}
$response->end('some response' );
});
https://www.swoole.co.uk/docs/modules/redis-connection-pool
Connections. Again?
POOL
Connections. Again?
use
DoctrineCommonCacheCacheProvider ;
use Redis;
use SwooleDatabaseRedisPool ;
class SwooleRedisCacheProvider extends
CacheProvider
{
public function __construct (
private RedisPool $pool,
) {
}
protected function doFetch($id, ?Redis $redis = null)
{
if (! $redis) {
return $this->run(fn (Redis $redis) : mixed =>
. $this->doFetch($id, $redis));
}
return $redis->get($id);
}
private function run(callable $procedure)
{
$redis = $this->pool->get();
$redis->setOption(Redis::SERIALIZER, $this->getSerializer ());
try {
$result = $procedure($redis);
} catch (Throwable $e) {
throw $e;
} finally {
$this->pool->put($redis);
}
return $result;
}
Memory Leaks. Again?
final class ReopeningEntityManager implements EntityManagerInterface
{
private Closure $entityManagerFactory ;
protected array $wrapped = [];
public function clear($object = null) : void
{
$this->getWrapped()->clear($object);
unset ($this->wrapped[Co::getCid()]); // does not help!
}
private function getWrapped() : EntityManagerInterface
{
if (! isset($this->wrapped[Co::getCid()])) {
$this->wrapped[Co::getCid()] =
($this->entityManagerFactory )();
}
return $this->wrapped[Co::getCid()];
}
public function getConnection ()
{
return $this->getWrapped()->getConnection ();
}
Memory Leaks. Again?
Using WeakMap &
defer in coroutines!
Restart workers?
You are coward!
Using PostgreSQL - no PDO hooks in Swoole
● Use Coroutine Postgresql Client:
extension=swoole_postgresql.so
● Write new Driver for Doctrine ORM
● Be ready to problems
Problem Again
Other miscellaneous:
Manage crons (by timers)
Manage message workers (process manager)
Manage Signals (soft termination)
Milestone 3: others
Cron jobs
- persist Deployment: run “crontab” process + list php CLI command
- CronJob (k8s) periodical run POD with “php bin/app cron:process”
- CronJob as Message (run as “bin/app messenger:consume transport.amqp”)
- + Swoole Timer async callback in PHP master process (instead linux crontab)
Prӕfectus
https://github.com/opsway/praefectus
Supervisor & Metrics server for Symfony Messenger
Prӕfectus
PraefectusListener
use SpiralGoridgeRelay
;
use SpiralGoridgeRPCRPC
;
use SpiralGoridgeRPCRPCInterface
;
/**
* @see SymfonyComponentMessengerWorker
*/
class PraefectusListener implements EventSubscriberInterface
{
private const IPC_SOCKET_PATH_TPL = '/tmp/praefectus_%d.sock'
;
// …
public function onMessageReceived (EventWorkerMessageReceivedEvent $event) : void
{
$this->getRpc()->call('PraefectusRPC.WorkerState' ,['pid'=>getmypid() ,'state'=>self::WORKER_BUSY]);
$this->getRpc()->call('PraefectusRPC.MessageState' , [
'id' => $messageIdStamp ->id(),
'name' => get_class( $event->getEnvelope ()->getMessage()),
'transport' => $event->getReceiverName (),
'bus' => $busName,
'state' => self::MESSAGE_STATE_PROCESSING,
]);
}
}
*not yet released on GitHub
● no compatibility in code:
○ run same code in FPM & build-in http server
○ work without swoole extension (PoC - write stubs?)
○ XDebug - goodbye (use PCOV for coverage)
○ Profiling - https://github.com/upscalesoftware
Results
● Doctrine + async = EVIL*
Results
* But is possible, if enough extra memory:
Each concurrency EntityManager = +100-150Mb
● Swoole Table for cache - must have!
Results
Doctrine (any) cache shared between workers.
Solved case: Deployment & migration process without
50x errors
● Benchmarks - good results!
Results
- empty handler (bootstrap) - TTFB before: 140 ms, after: 4 ms
SWOOLE
FPM
● Benchmarks - good results!
Results
- empty handler (bootstrap) - TTFB before: 140 ms, after: 4 ms
- AVG (all traffic) TTFB reduced on 40% - before: 250 ms, after: 150 ms
- 95 percentile - before: 1500 ms, after: 600 ms
P.S. Load by same API RPS: ~200
- Now: 20 (PHP) / 20 (Typesense) / 20 (other) / 16 (DB) vCPUs
- 6k$ --> 3.5k$ (per month)
Results
● Resources usage - (ETA) reduced!
Useful links:
- https://github.com/deminy/swoole-by-examples
- https://docs.mezzio.dev/mezzio/v3/why-mezzio/
- https://docs.mezzio.dev/mezzio-swoole/v3/considerations/
- https://www.swoole.co.uk/docs/modules/swoole-server/configuration
- https://github.com/swooletw/awesome-swoole
- https://github.com/k911/swoole-bundle
We looking: DevOps / Backend Developer / Frontend Developer / QA
manual+automation.
Any Questions?
BTW:

More Related Content

What's hot

Svelte
SvelteSvelte
OpenStack API's and WSGI
OpenStack API's and WSGIOpenStack API's and WSGI
OpenStack API's and WSGI
Mike Pittaro
 
파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 파이썬 플라스크 이해하기
파이썬 플라스크 이해하기
Yong Joon Moon
 
Reactive Programming In Java Using: Project Reactor
Reactive Programming In Java Using: Project ReactorReactive Programming In Java Using: Project Reactor
Reactive Programming In Java Using: Project Reactor
Knoldus Inc.
 
Introduction to Django REST Framework, an easy way to build REST framework in...
Introduction to Django REST Framework, an easy way to build REST framework in...Introduction to Django REST Framework, an easy way to build REST framework in...
Introduction to Django REST Framework, an easy way to build REST framework in...
Zhe Li
 
Support de cours angular
Support de cours angularSupport de cours angular
Support de cours angular
ENSET, Université Hassan II Casablanca
 
JPA Best Practices
JPA Best PracticesJPA Best Practices
JPA Best Practices
Carol McDonald
 
Nodejs functions & modules
Nodejs functions & modulesNodejs functions & modules
Nodejs functions & modules
monikadeshmane
 
PHP (Partie II) Par Mahdi Ben Alaya
PHP (Partie II) Par Mahdi Ben AlayaPHP (Partie II) Par Mahdi Ben Alaya
PHP (Partie II) Par Mahdi Ben Alaya
Mahdi Ben Alaya
 
Universal React apps in Next.js
Universal React apps in Next.jsUniversal React apps in Next.js
Universal React apps in Next.js
🐕 Łukasz Ostrowski
 
Django, 저는 이렇게 씁니다.
Django, 저는 이렇게 씁니다.Django, 저는 이렇게 씁니다.
Django, 저는 이렇게 씁니다.
Kyoung Up Jung
 
Techical Workflow for a Startup
Techical Workflow for a StartupTechical Workflow for a Startup
Techical Workflow for a Startup
Sébastien Saunier
 
Hexagonal Design in Django
Hexagonal Design in DjangoHexagonal Design in Django
Hexagonal Design in Django
mvschaik
 
Introduction to web application development with Vue (for absolute beginners)...
Introduction to web application development with Vue (for absolute beginners)...Introduction to web application development with Vue (for absolute beginners)...
Introduction to web application development with Vue (for absolute beginners)...
Lucas Jellema
 
Project Reactor By Example
Project Reactor By ExampleProject Reactor By Example
Project Reactor By Example
Denny Abraham Cheriyan
 
Understanding Monorepos
Understanding MonoreposUnderstanding Monorepos
Understanding Monorepos
Benjamin Cabanes
 
MySQL Audit 機制應用技術
MySQL Audit 機制應用技術MySQL Audit 機制應用技術
MySQL Audit 機制應用技術
Jamie Lee
 
Load Balancing with Nginx
Load Balancing with NginxLoad Balancing with Nginx
Load Balancing with Nginx
Marian Marinov
 
Advantages and disadvantages of a monorepo
Advantages and disadvantages of a monorepoAdvantages and disadvantages of a monorepo
Advantages and disadvantages of a monorepo
IanDavidson56
 
Spring Boot and REST API
Spring Boot and REST APISpring Boot and REST API
Spring Boot and REST API
07.pallav
 

What's hot (20)

Svelte
SvelteSvelte
Svelte
 
OpenStack API's and WSGI
OpenStack API's and WSGIOpenStack API's and WSGI
OpenStack API's and WSGI
 
파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 파이썬 플라스크 이해하기
파이썬 플라스크 이해하기
 
Reactive Programming In Java Using: Project Reactor
Reactive Programming In Java Using: Project ReactorReactive Programming In Java Using: Project Reactor
Reactive Programming In Java Using: Project Reactor
 
Introduction to Django REST Framework, an easy way to build REST framework in...
Introduction to Django REST Framework, an easy way to build REST framework in...Introduction to Django REST Framework, an easy way to build REST framework in...
Introduction to Django REST Framework, an easy way to build REST framework in...
 
Support de cours angular
Support de cours angularSupport de cours angular
Support de cours angular
 
JPA Best Practices
JPA Best PracticesJPA Best Practices
JPA Best Practices
 
Nodejs functions & modules
Nodejs functions & modulesNodejs functions & modules
Nodejs functions & modules
 
PHP (Partie II) Par Mahdi Ben Alaya
PHP (Partie II) Par Mahdi Ben AlayaPHP (Partie II) Par Mahdi Ben Alaya
PHP (Partie II) Par Mahdi Ben Alaya
 
Universal React apps in Next.js
Universal React apps in Next.jsUniversal React apps in Next.js
Universal React apps in Next.js
 
Django, 저는 이렇게 씁니다.
Django, 저는 이렇게 씁니다.Django, 저는 이렇게 씁니다.
Django, 저는 이렇게 씁니다.
 
Techical Workflow for a Startup
Techical Workflow for a StartupTechical Workflow for a Startup
Techical Workflow for a Startup
 
Hexagonal Design in Django
Hexagonal Design in DjangoHexagonal Design in Django
Hexagonal Design in Django
 
Introduction to web application development with Vue (for absolute beginners)...
Introduction to web application development with Vue (for absolute beginners)...Introduction to web application development with Vue (for absolute beginners)...
Introduction to web application development with Vue (for absolute beginners)...
 
Project Reactor By Example
Project Reactor By ExampleProject Reactor By Example
Project Reactor By Example
 
Understanding Monorepos
Understanding MonoreposUnderstanding Monorepos
Understanding Monorepos
 
MySQL Audit 機制應用技術
MySQL Audit 機制應用技術MySQL Audit 機制應用技術
MySQL Audit 機制應用技術
 
Load Balancing with Nginx
Load Balancing with NginxLoad Balancing with Nginx
Load Balancing with Nginx
 
Advantages and disadvantages of a monorepo
Advantages and disadvantages of a monorepoAdvantages and disadvantages of a monorepo
Advantages and disadvantages of a monorepo
 
Spring Boot and REST API
Spring Boot and REST APISpring Boot and REST API
Spring Boot and REST API
 

Similar to "Swoole: double troubles in c", Alexandr Vronskiy

DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...
DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...
DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...
Aman Kohli
 
Original slides from Ryan Dahl's NodeJs intro talk
Original slides from Ryan Dahl's NodeJs intro talkOriginal slides from Ryan Dahl's NodeJs intro talk
Original slides from Ryan Dahl's NodeJs intro talk
Aarti Parikh
 
ApacheConNA 2015: What's new in Apache httpd 2.4
ApacheConNA 2015: What's new in Apache httpd 2.4ApacheConNA 2015: What's new in Apache httpd 2.4
ApacheConNA 2015: What's new in Apache httpd 2.4
Jim Jagielski
 
php & performance
 php & performance php & performance
php & performance
simon8410
 
Building and Scaling Node.js Applications
Building and Scaling Node.js ApplicationsBuilding and Scaling Node.js Applications
Building and Scaling Node.js Applications
Ohad Kravchick
 
PHP & Performance
PHP & PerformancePHP & Performance
PHP & Performance
毅 吕
 
Haproxy - zastosowania
Haproxy - zastosowaniaHaproxy - zastosowania
Haproxy - zastosowania
Łukasz Jagiełło
 
Scalable Socket Server by Aryo
Scalable Socket Server by AryoScalable Socket Server by Aryo
Scalable Socket Server by Aryo
Agate Studio
 
Symfony Performance
Symfony PerformanceSymfony Performance
Symfony Performance
Paul Thrasher
 
PHP Sessions and Non-Sessions
PHP Sessions and Non-SessionsPHP Sessions and Non-Sessions
PHP Sessions and Non-Sessions
Sven Rautenberg
 
Socket programming, and openresty
Socket programming, and openrestySocket programming, and openresty
Socket programming, and openresty
Tavish Naruka
 
Redis
RedisRedis
202107 - Orion introduction - COSCUP
202107 - Orion introduction - COSCUP202107 - Orion introduction - COSCUP
202107 - Orion introduction - COSCUP
Ronald Hsu
 
MySQL HA Orchestrator Proxysql Consul.pdf
MySQL HA Orchestrator Proxysql Consul.pdfMySQL HA Orchestrator Proxysql Consul.pdf
MySQL HA Orchestrator Proxysql Consul.pdf
YunusShaikh49
 
NodeJS
NodeJSNodeJS
NodeJS
LinkMe Srl
 
Debugging: Rules & Tools
Debugging: Rules & ToolsDebugging: Rules & Tools
Debugging: Rules & Tools
Ian Barber
 
Php
PhpPhp
Presentation of OrientDB v2.2 - Webinar
Presentation of OrientDB v2.2 - WebinarPresentation of OrientDB v2.2 - Webinar
Presentation of OrientDB v2.2 - Webinar
Orient Technologies
 
Introduction to ZooKeeper - TriHUG May 22, 2012
Introduction to ZooKeeper - TriHUG May 22, 2012Introduction to ZooKeeper - TriHUG May 22, 2012
Introduction to ZooKeeper - TriHUG May 22, 2012
mumrah
 
Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015
Masahiro Nagano
 

Similar to "Swoole: double troubles in c", Alexandr Vronskiy (20)

DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...
DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...
DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...
 
Original slides from Ryan Dahl's NodeJs intro talk
Original slides from Ryan Dahl's NodeJs intro talkOriginal slides from Ryan Dahl's NodeJs intro talk
Original slides from Ryan Dahl's NodeJs intro talk
 
ApacheConNA 2015: What's new in Apache httpd 2.4
ApacheConNA 2015: What's new in Apache httpd 2.4ApacheConNA 2015: What's new in Apache httpd 2.4
ApacheConNA 2015: What's new in Apache httpd 2.4
 
php & performance
 php & performance php & performance
php & performance
 
Building and Scaling Node.js Applications
Building and Scaling Node.js ApplicationsBuilding and Scaling Node.js Applications
Building and Scaling Node.js Applications
 
PHP & Performance
PHP & PerformancePHP & Performance
PHP & Performance
 
Haproxy - zastosowania
Haproxy - zastosowaniaHaproxy - zastosowania
Haproxy - zastosowania
 
Scalable Socket Server by Aryo
Scalable Socket Server by AryoScalable Socket Server by Aryo
Scalable Socket Server by Aryo
 
Symfony Performance
Symfony PerformanceSymfony Performance
Symfony Performance
 
PHP Sessions and Non-Sessions
PHP Sessions and Non-SessionsPHP Sessions and Non-Sessions
PHP Sessions and Non-Sessions
 
Socket programming, and openresty
Socket programming, and openrestySocket programming, and openresty
Socket programming, and openresty
 
Redis
RedisRedis
Redis
 
202107 - Orion introduction - COSCUP
202107 - Orion introduction - COSCUP202107 - Orion introduction - COSCUP
202107 - Orion introduction - COSCUP
 
MySQL HA Orchestrator Proxysql Consul.pdf
MySQL HA Orchestrator Proxysql Consul.pdfMySQL HA Orchestrator Proxysql Consul.pdf
MySQL HA Orchestrator Proxysql Consul.pdf
 
NodeJS
NodeJSNodeJS
NodeJS
 
Debugging: Rules & Tools
Debugging: Rules & ToolsDebugging: Rules & Tools
Debugging: Rules & Tools
 
Php
PhpPhp
Php
 
Presentation of OrientDB v2.2 - Webinar
Presentation of OrientDB v2.2 - WebinarPresentation of OrientDB v2.2 - Webinar
Presentation of OrientDB v2.2 - Webinar
 
Introduction to ZooKeeper - TriHUG May 22, 2012
Introduction to ZooKeeper - TriHUG May 22, 2012Introduction to ZooKeeper - TriHUG May 22, 2012
Introduction to ZooKeeper - TriHUG May 22, 2012
 
Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015
 

More from Fwdays

"What I learned through reverse engineering", Yuri Artiukh
"What I learned through reverse engineering", Yuri Artiukh"What I learned through reverse engineering", Yuri Artiukh
"What I learned through reverse engineering", Yuri Artiukh
Fwdays
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
Fwdays
 
"Micro frontends: Unbelievably true life story", Dmytro Pavlov
"Micro frontends: Unbelievably true life story", Dmytro Pavlov"Micro frontends: Unbelievably true life story", Dmytro Pavlov
"Micro frontends: Unbelievably true life story", Dmytro Pavlov
Fwdays
 
"Objects validation and comparison using runtime types (io-ts)", Oleksandr Suhak
"Objects validation and comparison using runtime types (io-ts)", Oleksandr Suhak"Objects validation and comparison using runtime types (io-ts)", Oleksandr Suhak
"Objects validation and comparison using runtime types (io-ts)", Oleksandr Suhak
Fwdays
 
"JavaScript. Standard evolution, when nobody cares", Roman Savitskyi
"JavaScript. Standard evolution, when nobody cares", Roman Savitskyi"JavaScript. Standard evolution, when nobody cares", Roman Savitskyi
"JavaScript. Standard evolution, when nobody cares", Roman Savitskyi
Fwdays
 
"How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y...
"How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y..."How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y...
"How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y...
Fwdays
 
"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii
"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii
"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii
Fwdays
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
Fwdays
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
Fwdays
 
"What is a RAG system and how to build it",Dmytro Spodarets
"What is a RAG system and how to build it",Dmytro Spodarets"What is a RAG system and how to build it",Dmytro Spodarets
"What is a RAG system and how to build it",Dmytro Spodarets
Fwdays
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
Fwdays
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
Fwdays
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
Fwdays
 
"Distributed graphs and microservices in Prom.ua", Maksym Kindritskyi
"Distributed graphs and microservices in Prom.ua",  Maksym Kindritskyi"Distributed graphs and microservices in Prom.ua",  Maksym Kindritskyi
"Distributed graphs and microservices in Prom.ua", Maksym Kindritskyi
Fwdays
 
"Rethinking the existing data loading and processing process as an ETL exampl...
"Rethinking the existing data loading and processing process as an ETL exampl..."Rethinking the existing data loading and processing process as an ETL exampl...
"Rethinking the existing data loading and processing process as an ETL exampl...
Fwdays
 
"How Ukrainian IT specialist can go on vacation abroad without crossing the T...
"How Ukrainian IT specialist can go on vacation abroad without crossing the T..."How Ukrainian IT specialist can go on vacation abroad without crossing the T...
"How Ukrainian IT specialist can go on vacation abroad without crossing the T...
Fwdays
 
"The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ...
"The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ..."The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ...
"The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ...
Fwdays
 
"[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu...
"[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu..."[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu...
"[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu...
Fwdays
 
"[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care...
"[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care..."[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care...
"[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care...
Fwdays
 
"4 horsemen of the apocalypse of working relationships (+ antidotes to them)"...
"4 horsemen of the apocalypse of working relationships (+ antidotes to them)"..."4 horsemen of the apocalypse of working relationships (+ antidotes to them)"...
"4 horsemen of the apocalypse of working relationships (+ antidotes to them)"...
Fwdays
 

More from Fwdays (20)

"What I learned through reverse engineering", Yuri Artiukh
"What I learned through reverse engineering", Yuri Artiukh"What I learned through reverse engineering", Yuri Artiukh
"What I learned through reverse engineering", Yuri Artiukh
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
 
"Micro frontends: Unbelievably true life story", Dmytro Pavlov
"Micro frontends: Unbelievably true life story", Dmytro Pavlov"Micro frontends: Unbelievably true life story", Dmytro Pavlov
"Micro frontends: Unbelievably true life story", Dmytro Pavlov
 
"Objects validation and comparison using runtime types (io-ts)", Oleksandr Suhak
"Objects validation and comparison using runtime types (io-ts)", Oleksandr Suhak"Objects validation and comparison using runtime types (io-ts)", Oleksandr Suhak
"Objects validation and comparison using runtime types (io-ts)", Oleksandr Suhak
 
"JavaScript. Standard evolution, when nobody cares", Roman Savitskyi
"JavaScript. Standard evolution, when nobody cares", Roman Savitskyi"JavaScript. Standard evolution, when nobody cares", Roman Savitskyi
"JavaScript. Standard evolution, when nobody cares", Roman Savitskyi
 
"How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y...
"How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y..."How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y...
"How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y...
 
"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii
"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii
"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
"What is a RAG system and how to build it",Dmytro Spodarets
"What is a RAG system and how to build it",Dmytro Spodarets"What is a RAG system and how to build it",Dmytro Spodarets
"What is a RAG system and how to build it",Dmytro Spodarets
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
"Distributed graphs and microservices in Prom.ua", Maksym Kindritskyi
"Distributed graphs and microservices in Prom.ua",  Maksym Kindritskyi"Distributed graphs and microservices in Prom.ua",  Maksym Kindritskyi
"Distributed graphs and microservices in Prom.ua", Maksym Kindritskyi
 
"Rethinking the existing data loading and processing process as an ETL exampl...
"Rethinking the existing data loading and processing process as an ETL exampl..."Rethinking the existing data loading and processing process as an ETL exampl...
"Rethinking the existing data loading and processing process as an ETL exampl...
 
"How Ukrainian IT specialist can go on vacation abroad without crossing the T...
"How Ukrainian IT specialist can go on vacation abroad without crossing the T..."How Ukrainian IT specialist can go on vacation abroad without crossing the T...
"How Ukrainian IT specialist can go on vacation abroad without crossing the T...
 
"The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ...
"The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ..."The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ...
"The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ...
 
"[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu...
"[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu..."[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu...
"[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu...
 
"[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care...
"[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care..."[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care...
"[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care...
 
"4 horsemen of the apocalypse of working relationships (+ antidotes to them)"...
"4 horsemen of the apocalypse of working relationships (+ antidotes to them)"..."4 horsemen of the apocalypse of working relationships (+ antidotes to them)"...
"4 horsemen of the apocalypse of working relationships (+ antidotes to them)"...
 

Recently uploaded

UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6
DianaGray10
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-Universität
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
SOFTTECHHUB
 
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial IntelligenceAI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
IndexBug
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
Neo4j
 
Full-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalizationFull-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalization
Zilliz
 
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Speck&Tech
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Paige Cruz
 
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
Neo4j
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Safe Software
 
UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5
DianaGray10
 
GenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizationsGenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizations
kumardaparthi1024
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
Aftab Hussain
 
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
Edge AI and Vision Alliance
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
Adtran
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
名前 です男
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
Daiki Mogmet Ito
 
Infrastructure Challenges in Scaling RAG with Custom AI models
Infrastructure Challenges in Scaling RAG with Custom AI modelsInfrastructure Challenges in Scaling RAG with Custom AI models
Infrastructure Challenges in Scaling RAG with Custom AI models
Zilliz
 
Mariano G Tinti - Decoding SpaceX
Mariano G Tinti - Decoding SpaceXMariano G Tinti - Decoding SpaceX
Mariano G Tinti - Decoding SpaceX
Mariano Tinti
 

Recently uploaded (20)

UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
 
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial IntelligenceAI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
 
Full-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalizationFull-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalization
 
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
 
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
 
UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5
 
GenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizationsGenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizations
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
 
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
 
Infrastructure Challenges in Scaling RAG with Custom AI models
Infrastructure Challenges in Scaling RAG with Custom AI modelsInfrastructure Challenges in Scaling RAG with Custom AI models
Infrastructure Challenges in Scaling RAG with Custom AI models
 
Mariano G Tinti - Decoding SpaceX
Mariano G Tinti - Decoding SpaceXMariano G Tinti - Decoding SpaceX
Mariano G Tinti - Decoding SpaceX
 

"Swoole: double troubles in c", Alexandr Vronskiy

  • 1.
  • 3. ● What existing problems need to solve? ● Why choose Swoole? ● How solve it with Swoole? ● What unexpected troubles could happens? ● Show methods to avoid then (or not?) ● Talk about theory ● Examples in a context of a real project Intro
  • 4. Side Effects of - PHP no dying (long-lived) - Concurrency Async - Shared Memory access Intro
  • 5. ● ZF2 / Laminas / Mezzio / PSR-15 / .. ● PHP 5.6 -> … -> 7.4 --> 8.0 + swoole ● PostgreSQL / ElasticSearch Typesense / Redis / RabbitMQ / PubSub ● Docker / k8s / autoscale / Google Cloud ● Files: 2.5k, LOC: 200k, LLOC: 30k Intro. About project
  • 6. Intro. About project Current AVG metrics: - GA online users: ~3500 - API RPS: ~200 - DB transactions: ~3000/sec - Products count: ~25kk Consuming resources: - PHP: 60 vCPU - ElasticSearch: 40 vCPU - PostgreSQL: 16 vCPU - Others: 20 vCPU
  • 7. ● Not optimized resources usage. ● Hard tuning horizontal scale. ● Over-complicated infrastructure ● Not well performance (TTFB) Why? Problems Database PHP PHP PHP PHP Elastic Elastic Elastic Other 4x times
  • 8. ● Not optimized resources usage. ● Hard tuning horizontal scale. ● Over-complicated infrastructure ● Not well performance (TTFB) Why? Problems PHP 4 vCPU PHP 16 vCPU VS
  • 9. ● Not optimized resources usage. ● Hard tuning horizontal scale. ● Over-complicated infrastructure ● Not well performance (TTFB) Why? Problems Docker, k8s, Terraform, Helm, GitHub Actions, Envs: prod+stage+devs+local, Go, Typescript
  • 10. ● Not optimized resources usage. ● Hard tuning horizontal scale. ● Over-complicated infrastructure ● Not well performance (TTFB) Why? Problems
  • 11. ● ASYNC entire ecosystem ● Performance ● Easy to start - Coroutine based concurrent asynchronous IO - Event Loop - Process management - In-memory storage and management - Async TCP/UDP/HTTP/WebSocket/HTTP2/FastCGI client and servers - Async Task API - Channels, Locks, Timer, Scheduler NO PECL: ext-pcntl, ext-pthreads, ext-event Why Swoole?
  • 12. Milestone 1: PHP no die ● Run HTTP Server ○ replace NGINX+FPM ○ simplify infrastructure (less DevOps, easy building & k8s configs) ○ change (unified) operations: CI / CD / local env ● Prepare bootstrap ● Implement best practices in shared memory usage to avoid side-effects Plan
  • 13. ● Server Mode: SWOOLE_PROCESS / SWOOLE_BASE ● Dispatch Mode: 1-9 (Round-Robin, Fixed, Preemptive, etc) ● Worker Num: 1-1000 (CPU*2) ● Max Request: 0-XXX (0) Other Options: Limits, Timeouts, Memory buffers... php bin/http-server.php Swoole HTTP Server https://www.swoole.co.uk/docs/modules/swoole-server/configuration MUST SEE: <?php $server = new SwooleHTTPServer("127.0.0.1", 9501); $server->on('Request', function(Swoole/Server/Request $request, Swoole/Server/Response $response) { $response->end('<h1>Hello World!</h1>'); }); $server->start();
  • 14. ● Scan config files, env, run reflection, attributes, build DI, generate proxy, warm caches: ● NO NEED cache layer anymore ● NOW it before real start http server (if no traffic: readiness probe=negative) PSR-7 HTTP Messages PSR-15 Middleware PSR-11 Container bootstrap in master http request in worker process Bootstrap app once fork state
  • 15. What are the problems? - NO SUPER GLOBALS ($_SERVER, ...) - No PHP Session (it is CLI SAPI) - Stateful services that should mutate on each request - DI containers - global state too. Shared Memory
  • 16. Any wrong example? Shared Memory https://github.com/chrisguitarguy/RequestIdBundle/blob/main/src/EventListener/RequestIdListener.php public function onRequest(RequestEvent $event) : void { if (!$this->isMainRequest ($event)) { return; } $req = $event->getRequest(); if ($this->trustRequest && ($id = $req->headers->get($this->requestHeader ))) { $this->idStorage->setRequestId ($id); return; } if ($id = $this->idStorage->getRequestId ()) { $req->headers->set($this->requestHeader , $id); return; } $id = $this->idGenerator ->generate(); $req->headers->set($this->requestHeader , $id); $this->idStorage->setRequestId ($id); } Empty storage - no return Generate NEW Saving to storage 1 HTTP REQUEST:
  • 17. Any wrong example? Shared Memory public function onRequest(RequestEvent $event) : void { if (!$this->isMainRequest ($event)) { return; } $req = $event->getRequest(); if ($this->trustRequest && ($id = $req->headers->get($this->requestHeader ))) { $this->idStorage->setRequestId ($id); return; } if ($id = $this->idStorage->getRequestId ()) { $req->headers->set($this->requestHeader , $id); return; } $id = $this->idGenerator ->generate(); $req->headers->set($this->requestHeader , $id); $this->idStorage->setRequestId ($id); } 2 HTTP REQUEST: Now has ID in storage THE END Dead code https://github.com/chrisguitarguy/RequestIdBundle/blob/main/src/EventListener/RequestIdListener.php
  • 18. Shared Memory HTTP Server options: Max Request: 100 What if... Then… In logs request ID is changed.
  • 19. Best practices: - Middlewares, Factories, Proxies, Delegators Shared Memory use PsrHttpMessageResponseInterface ; use PsrHttpMessageServerRequestInterface ; use PsrHttpServerRequestHandlerInterface ; use PsrLogLoggerInterface ; class SomeHandler implements RequestHandlerInterface { public function __construct( private Closure $appServiceFactory , private LoggerInterface $logger ) {} // Idempotent method!!! public function handle(ServerRequestInterface $request) : ResponseInterface { $logger = clone $this->logger; $logger->getProcessor( 'RequestID')->setRequestId( $request->getAttribute( 'RequestID')); $appService = ($this->appServiceFactory)( $logger); return new JsonResponse($appService->createBook()) ; } }
  • 20. Memory leaks … in Doctrine ORM :( Shared Memory https://alejandrocelaya.blog/2019/11/04/how-to-properly-handle-a-doctrine-entity-manager-on-an-expressive-appli cation-served-with-swoole/ use DoctrineORMDecoratorEntityManagerDecorator as EMD; class ReopeningEntityManager extends EMD { private $createEm; public function __construct (callable $createEm) { parent::__construct($createEm()); $this->createEm = $createEm; } public function open(): void { if (! $this->wrapped->isOpen()) { $this->wrapped = ($this->createEm)(); } } class CloseDbConnectionMiddleware implements MiddlewareInterface { public function __construct( private ReopeningEntityManager $em) {} public function process( ServerRequestInterface $request, RequestHandlerInterface $handler ) : ResponseInterface { $this->em->open() ; try { return $handler->handle($request); } finally { $this->em->getConnection()->close() ; $this->em->clear() ; } } } Saved in DI
  • 21. Shared Memory Memory leaks BUT WHERE??? abstract class EntityManagerDecorator extends ObjectManagerDecorator { /** @var EntityManagerInterface */ protected $wrapped; public function __construct (EntityManagerInterface $wrapped) { $this->wrapped = $wrapped; } public function getRepository ($className) { return $this->wrapped->getRepository ($className); } public function getRepository ($entityName ) { return $this->repositoryFactory ->getRepository ($this, $entityName ); } Somewhere far far away in EntityManager
  • 22. PROBLEMS DUE TO: timeouts / lifecycles Avoid: Stateful convert to stateless Connections $redis = $di->get(Redis::class); // FactoryRedis: $redis->connect(...); $redis->get('KEY1'); $redisFactory = $di->get(RedisFactory:: class); $redisFactory()->get(‘KEY1’); // + close connect in desctructor Request Wrapper/Delegator: new/refresh state on each request OR
  • 23. Milestone 2: ASYNC ● Async theory ● Using coroutines ● Non-blocked IO solutions ● Concurrency problems review ● Again memory leaks
  • 24. ● GET /some/action1/ SELECT sleep(1); ○ 1 worker = 1 req/sec ○ 2 worker = 2 req/sec ● GET /some/action2/ fibonacci(30); ○ 1 worker = 1 req/sec ○ 2 worker = depends on CPU cores Why/What async? Try benchmark this:
  • 25. ● GET /some/action1/ SELECT sleep(1); ○ 1 worker = 1 req/sec ○ 2 worker = 2 req/sec ● GET /some/action2/ fibonacci(30); ○ 1 worker = 1 req/sec ○ 2 worker = depends on CPU cores MIX 50/50 = 1 req/sec 50% CPU Why/What async? Try benchmark this:
  • 26. Now enable coroutines: http server options: . 'enable_coroutine' => true, Why/What async? ● GET /some/action1/ ○ 1 worker = 10000 req/sec ○ 2 worker = 10000 req/sec ● GET /some/action2/ ○ 1 worker = 1 req/sec ○ 2 worker = depends on CPU cores
  • 27. Now enable coroutines: http server options: . 'enable_coroutine' => true, Why/What async? ● GET /some/action1/ ○ 1 worker = 10000 req/sec ○ 2 worker = 10000 req/sec ● GET /some/action2/ ○ 1 worker = 1 req/sec ○ 2 worker = depends on CPU cores MIX 50/50 = 2 req/sec 100% CPU
  • 28. go(function () { // FIRST CO echo '1'; go(function () { // SECOND CO echo '2'; co::sleep(3); // IO (in 2 CO), will return in 3 sec echo '6'; go(function () { // THIRD CO echo '7'; co::sleep(2); // IO echo "9n"; }); // END THIRD echo '8'; }); // END SECOND echo '3'; co::sleep(1); // Again IO but in 1 CO echo '5'; }); // END FIRST CO echo '4'; Coroutines 1 2 3 4 5
  • 30. https://www.swoole.co.uk/docs/modules/swoole-runtime-flags Swoole Hooks Coroutine Clients: ● TCP/UDP ● HTTP ● HTTP2 ● Socket ● FastCGI ● Redis ● MySQL ● Postgresql Runtime HOOKS: ● Coroutine support (any IO libraries based on php_stream): ○ Redis (phpredis) or (predis) ○ MySQL (mysqlnd) PDO and MySQLi ○ PHP SOAP ○ file_get_contents, fopen and many more file I/O operations ○ stream_socket_client functions ○ fsockopen ○ CURL with libcurl ● Libraries without coroutine support: ○ MySQL with libmysqlclient ○ MongoDB with mongo-c-client ○ pdo_pgsql, pdo_ori, pdo_odbc, pdo_firebird, php-amqp VS Non-blocked IO
  • 31. $swooleServer->onRequest: go($this->requestHandler); -------------------------------------------------------------------------- non-blocked: multiple requests in same time/code Concurrency function onRequest() { $class = $di->get(stdClass:class); if ($class->some === null) { $class->some = 123; } sleep(2); // && some logic $class->some = null; } First request awaiting here We expected clean in request end http server options: . 'enable_coroutine' => true,
  • 32. $swooleServer->onRequest: go($this->requestHandler); -------------------------------------------------------------------------- non-blocked: multiple requests in same time/code Concurrency function onRequest() { $class = $di->get(stdClass:class); if ($class->some === null) { $class->some = 123; } sleep(2); // && some logic $class->some = null; } First request awaiting here We expected clean in request end EPIC FAIL! in second request http server options: . 'enable_coroutine' => true,
  • 33. Request Wrapper/Delegator: new/refresh state on each request Uncaught SwooleError: Socket# has already been bound to another coroutine Connections. Again? $http = new SwooleHttpServer( '0.0.0.0', '80', SWOOLE_PROCESS) ; $http->on('request', function (SwooleHttpRequest $request, SwooleHttpResponse $response) { if (empty($redis)) { $redis = new Redis(); $redis->connect('127.0.0.1' , 6379); $redis->select(1); $redis->setOption(Redis::OPT_SERIALIZER , Redis::SERIALIZER_PHP) ; } try { $redisJson = $redis->get('key'); } catch (Exception $e) { // SWOOLE ERROR HERE ! } $response->end('some response' ); });
  • 35. Connections. Again? use DoctrineCommonCacheCacheProvider ; use Redis; use SwooleDatabaseRedisPool ; class SwooleRedisCacheProvider extends CacheProvider { public function __construct ( private RedisPool $pool, ) { } protected function doFetch($id, ?Redis $redis = null) { if (! $redis) { return $this->run(fn (Redis $redis) : mixed => . $this->doFetch($id, $redis)); } return $redis->get($id); } private function run(callable $procedure) { $redis = $this->pool->get(); $redis->setOption(Redis::SERIALIZER, $this->getSerializer ()); try { $result = $procedure($redis); } catch (Throwable $e) { throw $e; } finally { $this->pool->put($redis); } return $result; }
  • 36. Memory Leaks. Again? final class ReopeningEntityManager implements EntityManagerInterface { private Closure $entityManagerFactory ; protected array $wrapped = []; public function clear($object = null) : void { $this->getWrapped()->clear($object); unset ($this->wrapped[Co::getCid()]); // does not help! } private function getWrapped() : EntityManagerInterface { if (! isset($this->wrapped[Co::getCid()])) { $this->wrapped[Co::getCid()] = ($this->entityManagerFactory )(); } return $this->wrapped[Co::getCid()]; } public function getConnection () { return $this->getWrapped()->getConnection (); }
  • 37. Memory Leaks. Again? Using WeakMap & defer in coroutines! Restart workers? You are coward!
  • 38. Using PostgreSQL - no PDO hooks in Swoole ● Use Coroutine Postgresql Client: extension=swoole_postgresql.so ● Write new Driver for Doctrine ORM ● Be ready to problems Problem Again
  • 39. Other miscellaneous: Manage crons (by timers) Manage message workers (process manager) Manage Signals (soft termination) Milestone 3: others
  • 40. Cron jobs - persist Deployment: run “crontab” process + list php CLI command - CronJob (k8s) periodical run POD with “php bin/app cron:process” - CronJob as Message (run as “bin/app messenger:consume transport.amqp”) - + Swoole Timer async callback in PHP master process (instead linux crontab)
  • 42. Prӕfectus PraefectusListener use SpiralGoridgeRelay ; use SpiralGoridgeRPCRPC ; use SpiralGoridgeRPCRPCInterface ; /** * @see SymfonyComponentMessengerWorker */ class PraefectusListener implements EventSubscriberInterface { private const IPC_SOCKET_PATH_TPL = '/tmp/praefectus_%d.sock' ; // … public function onMessageReceived (EventWorkerMessageReceivedEvent $event) : void { $this->getRpc()->call('PraefectusRPC.WorkerState' ,['pid'=>getmypid() ,'state'=>self::WORKER_BUSY]); $this->getRpc()->call('PraefectusRPC.MessageState' , [ 'id' => $messageIdStamp ->id(), 'name' => get_class( $event->getEnvelope ()->getMessage()), 'transport' => $event->getReceiverName (), 'bus' => $busName, 'state' => self::MESSAGE_STATE_PROCESSING, ]); } } *not yet released on GitHub
  • 43. ● no compatibility in code: ○ run same code in FPM & build-in http server ○ work without swoole extension (PoC - write stubs?) ○ XDebug - goodbye (use PCOV for coverage) ○ Profiling - https://github.com/upscalesoftware Results
  • 44. ● Doctrine + async = EVIL* Results * But is possible, if enough extra memory: Each concurrency EntityManager = +100-150Mb
  • 45. ● Swoole Table for cache - must have! Results Doctrine (any) cache shared between workers. Solved case: Deployment & migration process without 50x errors
  • 46. ● Benchmarks - good results! Results - empty handler (bootstrap) - TTFB before: 140 ms, after: 4 ms SWOOLE FPM
  • 47. ● Benchmarks - good results! Results - empty handler (bootstrap) - TTFB before: 140 ms, after: 4 ms - AVG (all traffic) TTFB reduced on 40% - before: 250 ms, after: 150 ms - 95 percentile - before: 1500 ms, after: 600 ms P.S. Load by same API RPS: ~200
  • 48. - Now: 20 (PHP) / 20 (Typesense) / 20 (other) / 16 (DB) vCPUs - 6k$ --> 3.5k$ (per month) Results ● Resources usage - (ETA) reduced!
  • 49. Useful links: - https://github.com/deminy/swoole-by-examples - https://docs.mezzio.dev/mezzio/v3/why-mezzio/ - https://docs.mezzio.dev/mezzio-swoole/v3/considerations/ - https://www.swoole.co.uk/docs/modules/swoole-server/configuration - https://github.com/swooletw/awesome-swoole - https://github.com/k911/swoole-bundle We looking: DevOps / Backend Developer / Frontend Developer / QA manual+automation. Any Questions? BTW: