<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ronie Neubauer</title>
    <description>The latest articles on DEV Community by Ronie Neubauer (@ronieneubauer).</description>
    <link>https://dev.to/ronieneubauer</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F274585%2F04090a42-6a2c-4b06-ab49-d8c6f53cda27.jpeg</url>
      <title>DEV Community: Ronie Neubauer</title>
      <link>https://dev.to/ronieneubauer</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ronieneubauer"/>
    <language>en</language>
    <item>
      <title>Websocket em PHP? Sim! É possível!</title>
      <dc:creator>Ronie Neubauer</dc:creator>
      <pubDate>Sun, 15 Mar 2020 23:28:24 +0000</pubDate>
      <link>https://dev.to/ronieneubauer/websocket-em-php-sim-e-possivel-9gm</link>
      <guid>https://dev.to/ronieneubauer/websocket-em-php-sim-e-possivel-9gm</guid>
      <description>&lt;p&gt;Vou contar um pouco sobre o que é o PHP Swoole e como foi utiliza-lo para desenvolver um microserviço de websocket escalável e totalmente integrado com os serviços da Amazon Web Services (AWS).&lt;/p&gt;

&lt;h1&gt;
  
  
  Por que Websocket em PHP?
&lt;/h1&gt;

&lt;p&gt;Escutei este pergunta em diversos momentos, até mesmo pela própria equipe onde trabalho. Já haviamos desenvolvido um websocket uitilizando Ratchet, mas era um escopo muito menor e ficou claro alguns problemas que teríamos em um escopo maior. Neste novo desafio precisavamos de uma biblioteca muito mais robusta, escalável e com mais ferramentas a disposição.&lt;/p&gt;

&lt;p&gt;Na fase de planejamento do projeto testei diversos websockets em diferentes linguagens, mas acabei escolhendo o PHP Swoole, pois ele fornecia coroutine, velocidade, escalabilidade e mais um pouco.&lt;/p&gt;

&lt;p&gt;A confiança em utilizar o Websocket em PHP, algo que dificilmente a comunidade recomendaria, foram os testes de carga, o conhecimento da linguagem na empresa e a facilidade de outras pessoas assumirem ou fornecerem suporte ao projeto. &lt;/p&gt;

&lt;h1&gt;
  
  
  Benchmark
&lt;/h1&gt;

&lt;p&gt;No final do artigo &lt;a href="https://www.treinaweb.com.br/blog/introducao-ao-swoole-framework-php-assincrono-baseado-em-corrotinas/" rel="noopener noreferrer"&gt;Introdução ao swoole&lt;/a&gt;, podemos ver um benchmark por números de requisições entre os seguintes cenários: PHP puro, NodeJs, Go e PHP Swoole.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PHP Puro&lt;/strong&gt; (882 requisições por segundo)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="nc"&gt;Running&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;://&lt;/span&gt;&lt;span class="mf"&gt;127.0.0.1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8101&lt;/span&gt;
  &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="n"&gt;threads&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="n"&gt;connections&lt;/span&gt;
  &lt;span class="nc"&gt;Thread&lt;/span&gt; &lt;span class="nc"&gt;Stats&lt;/span&gt;   &lt;span class="nc"&gt;Avg&lt;/span&gt;      &lt;span class="nc"&gt;Stdev&lt;/span&gt;     &lt;span class="nc"&gt;Max&lt;/span&gt;   &lt;span class="o"&gt;+/-&lt;/span&gt; &lt;span class="nc"&gt;Stdev&lt;/span&gt;
    &lt;span class="nc"&gt;Latency&lt;/span&gt;     &lt;span class="mf"&gt;3.46&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;    &lt;span class="mf"&gt;9.56&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt; &lt;span class="mf"&gt;141.27&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;   &lt;span class="mf"&gt;98.92&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;
    &lt;span class="nc"&gt;Req&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nc"&gt;Sec&lt;/span&gt;     &lt;span class="mf"&gt;1.41&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;     &lt;span class="mf"&gt;1.70&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;    &lt;span class="mf"&gt;9.47&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;    &lt;span class="mf"&gt;85.45&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;
  &lt;span class="mi"&gt;8871&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="mf"&gt;10.05&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.47&lt;/span&gt;&lt;span class="no"&gt;MB&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt;
  &lt;span class="nc"&gt;Socket&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;connect&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="mi"&gt;9275&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;write&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="nc"&gt;Requests&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="mf"&gt;882.46&lt;/span&gt;
&lt;span class="nc"&gt;Transfer&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="mf"&gt;149.95&lt;/span&gt;&lt;span class="no"&gt;KB&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;NodeJS&lt;/strong&gt; (49.720 requisições por segundo)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="nc"&gt;Running&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;://&lt;/span&gt;&lt;span class="mf"&gt;127.0.0.1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8101&lt;/span&gt;
  &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="n"&gt;threads&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="n"&gt;connections&lt;/span&gt;
  &lt;span class="nc"&gt;Thread&lt;/span&gt; &lt;span class="nc"&gt;Stats&lt;/span&gt;   &lt;span class="nc"&gt;Avg&lt;/span&gt;      &lt;span class="nc"&gt;Stdev&lt;/span&gt;     &lt;span class="nc"&gt;Max&lt;/span&gt;   &lt;span class="o"&gt;+/-&lt;/span&gt; &lt;span class="nc"&gt;Stdev&lt;/span&gt;
    &lt;span class="nc"&gt;Latency&lt;/span&gt;     &lt;span class="mf"&gt;4.05&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;    &lt;span class="mf"&gt;1.09&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;  &lt;span class="mf"&gt;43.57&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;   &lt;span class="mf"&gt;98.31&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;
    &lt;span class="nc"&gt;Req&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nc"&gt;Sec&lt;/span&gt;    &lt;span class="mf"&gt;12.49&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;     &lt;span class="mf"&gt;1.46&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;   &lt;span class="mf"&gt;13.49&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;    &lt;span class="mf"&gt;97.03&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;
  &lt;span class="mi"&gt;502227&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="mf"&gt;10.10&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;53.16&lt;/span&gt;&lt;span class="no"&gt;MB&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt;
  &lt;span class="nc"&gt;Socket&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;connect&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="mi"&gt;110&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;write&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="nc"&gt;Requests&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="mf"&gt;49720.54&lt;/span&gt;
&lt;span class="nc"&gt;Transfer&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="mf"&gt;5.26&lt;/span&gt;&lt;span class="no"&gt;MB&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;GO&lt;/strong&gt; (187.280 requisições por segundo)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="nc"&gt;Running&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;://&lt;/span&gt;&lt;span class="mf"&gt;127.0.0.1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8101&lt;/span&gt;
  &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="n"&gt;threads&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="n"&gt;connections&lt;/span&gt;
  &lt;span class="nc"&gt;Thread&lt;/span&gt; &lt;span class="nc"&gt;Stats&lt;/span&gt;   &lt;span class="nc"&gt;Avg&lt;/span&gt;      &lt;span class="nc"&gt;Stdev&lt;/span&gt;     &lt;span class="nc"&gt;Max&lt;/span&gt;   &lt;span class="o"&gt;+/-&lt;/span&gt; &lt;span class="nc"&gt;Stdev&lt;/span&gt;
    &lt;span class="nc"&gt;Latency&lt;/span&gt;     &lt;span class="mf"&gt;1.05&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;  &lt;span class="mf"&gt;624.03&lt;/span&gt;&lt;span class="n"&gt;us&lt;/span&gt;  &lt;span class="mf"&gt;42.09&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;   &lt;span class="mf"&gt;92.46&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;
    &lt;span class="nc"&gt;Req&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nc"&gt;Sec&lt;/span&gt;    &lt;span class="mf"&gt;47.05&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;     &lt;span class="mf"&gt;2.31&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;   &lt;span class="mf"&gt;50.59&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;    &lt;span class="mf"&gt;95.50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;
  &lt;span class="mi"&gt;1873010&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="mf"&gt;10.00&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;228.64&lt;/span&gt;&lt;span class="no"&gt;MB&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt;
  &lt;span class="nc"&gt;Socket&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;connect&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;write&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="nc"&gt;Requests&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;187280.40&lt;/span&gt;
&lt;span class="nc"&gt;Transfer&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="mf"&gt;22.86&lt;/span&gt;&lt;span class="no"&gt;MB&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;PHP Swoole&lt;/strong&gt; (193.149 requisições por segundo)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="nc"&gt;Running&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;://&lt;/span&gt;&lt;span class="mf"&gt;127.0.0.1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8101&lt;/span&gt;
  &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="n"&gt;threads&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="n"&gt;connections&lt;/span&gt;
  &lt;span class="nc"&gt;Thread&lt;/span&gt; &lt;span class="nc"&gt;Stats&lt;/span&gt;   &lt;span class="nc"&gt;Avg&lt;/span&gt;      &lt;span class="nc"&gt;Stdev&lt;/span&gt;     &lt;span class="nc"&gt;Max&lt;/span&gt;   &lt;span class="o"&gt;+/-&lt;/span&gt; &lt;span class="nc"&gt;Stdev&lt;/span&gt;
    &lt;span class="nc"&gt;Latency&lt;/span&gt;     &lt;span class="mf"&gt;0.87&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;  &lt;span class="mf"&gt;660.42&lt;/span&gt;&lt;span class="n"&gt;us&lt;/span&gt;  &lt;span class="mf"&gt;42.95&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;   &lt;span class="mf"&gt;98.60&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;
    &lt;span class="nc"&gt;Req&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nc"&gt;Sec&lt;/span&gt;    &lt;span class="mf"&gt;48.55&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;     &lt;span class="mf"&gt;3.12&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;   &lt;span class="mf"&gt;53.67&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;    &lt;span class="mf"&gt;88.75&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;
  &lt;span class="mi"&gt;1933132&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="mf"&gt;10.01&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;304.19&lt;/span&gt;&lt;span class="no"&gt;MB&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt;
  &lt;span class="nc"&gt;Socket&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;connect&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;write&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="nc"&gt;Requests&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;193149.91&lt;/span&gt;
&lt;span class="nc"&gt;Transfer&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="mf"&gt;30.39&lt;/span&gt;&lt;span class="no"&gt;MB&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  Mas o que é o PHP Swoole
&lt;/h1&gt;

&lt;p&gt;O Swoole é um Event-Driven, assíncrono e baseado em corotina, com alto desempenho escrito em C e C++ para PHP.&lt;/p&gt;

&lt;p&gt;Uma extensão PHP, que permite escrever serviços de alto desempenho, escaláveis e simultâneos, TCP, UDP, Unix socket, HTTP, WebSocket , sem muito conhecimento sobre non-blocking I/O e Linux Kernel de baixo nível.&lt;/p&gt;
&lt;h1&gt;
  
  
  Como funciona o PHP Swoole?
&lt;/h1&gt;

&lt;p&gt;O Swoole funciona diferente do modelo tradicional do PHP, ele é executado no modo CLI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/5d7808facc40cb47a23056827d38afa639d7b3ec/68747470733a2f2f692e696d6775722e636f6d2f675150747377462e706e67" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/5d7808facc40cb47a23056827d38afa639d7b3ec/68747470733a2f2f692e696d6775722e636f6d2f675150747377462e706e67" alt="PHP Swoole"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Master&lt;/strong&gt;: É processo principal, ele forka o &lt;strong&gt;Main Reactor&lt;/strong&gt; e o &lt;strong&gt;Manager&lt;/strong&gt;, é o processo raiz de toda a aplicação.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Main Reactor&lt;/strong&gt;: Thread principal, gerencia e faz o balanceamento entre os reactors auxiliares.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reactor&lt;/strong&gt;: Multi-thread e totalmente assíncrono, responsável por receber solicitações e entregar ao Manager.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Manager&lt;/strong&gt;: Processo gerenciador, forka e gerencia os workers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Worker&lt;/strong&gt;: É aqui que você realmente deve se preocupar. Onde realmente as tarefas são executadas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Task Worker&lt;/strong&gt;: São auxiliáres dos &lt;strong&gt;Workers&lt;/strong&gt;, bastante utilizado para tarefas paralelas e não bloqueantes ao worker.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Algumas diferenças entre o Swoole e o PHP-FPM são:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;O Swoole forka um determinado número de workers baseado na quantidade de núcleos da CPU, para utilizar todos os núcleos da CPU.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;O Swoole suporta conexões de longa duração para servidor websocket ou servidor TCP / UDP.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Swoole suporta várias requisições ao mesmo tempo (não bloqueantes).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Swoole pode gerenciar e reutilizar o status na memória.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para um entendimento mais avançado de como o PHP Swoole funciona, mesmo não tratando de Websocket, eu recomendo a leitura do artigo disponibilizado em Benchmark.&lt;/p&gt;
&lt;h1&gt;
  
  
  Instalando PHP Swoole
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Instalação básica&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="n"&gt;pecl&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;swoole&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Instalação Recomendada&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="k"&gt;clone&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="o"&gt;://&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;swoole&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;swoole&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt;
&lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="n"&gt;swoole&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;
&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;checkout&lt;/span&gt; &lt;span class="n"&gt;v4&lt;/span&gt;&lt;span class="mf"&gt;.4.12&lt;/span&gt;
&lt;span class="n"&gt;phpize&lt;/span&gt;
&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;configure&lt;/span&gt;
&lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  Criando Websocket Server
&lt;/h1&gt;

&lt;p&gt;Exemplo básico da construção de um websocket server com 3 eventos (open, mensage, close)&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;swoole_websocket_server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9502&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;SWOOLE_PROCESS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'task_worker_num'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'log_file'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'/var/log/supervisor/swoole.log'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'open_tcp_keepalive'&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;));&lt;/span&gt;


&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'open'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"connection open: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$req&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$frame&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"received message: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$frame&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;connections&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$fd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$frame&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'close'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$fd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"connection close: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$fd&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'task'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$fd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Task"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;A variável &lt;strong&gt;$server&lt;/strong&gt; é usada para construir o próprio servidor websocket.&lt;/p&gt;

&lt;p&gt;Nela podemos definir algumas configurações de inicialização com o método -&amp;gt;set().&lt;/p&gt;

&lt;p&gt;No exemplo acima inicializamos o servidor com 10 workers para task, o caminho do log e habilitamos a conexão persistente do websocket.&lt;/p&gt;

&lt;p&gt;Utilizamos o método -&amp;gt;on() para mapear os eventos de callback dentro do server, no exemplo acima configuramos evento de abertura de conexão, mensagem e desconexão.&lt;/p&gt;

&lt;h1&gt;
  
  
  Como testar?
&lt;/h1&gt;

&lt;p&gt;Você pode utilizar a extensão do Chrome chamada WS Client:&lt;br&gt;
&lt;a href="https://chrome.google.com/webstore/detail/web-socket-client/lifhekgaodigcpmnakfhaaaboididbdn" rel="noopener noreferrer"&gt;https://chrome.google.com/webstore/detail/web-socket-client/lifhekgaodigcpmnakfhaaaboididbdn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Basta colocar a URL como ws://localhost:9501 e enviar qualquer mensagem de texto. No código descrito acima será feito um broadcast, todos que estiverem conectados receberão uma cópia da mensagem.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fassb8i4o69zwfdvecslx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fassb8i4o69zwfdvecslx.png" alt="Websocket Client"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A mensagem pode ser de qualquer tipo, mas normalmente usamos padrão Json entre os sistemas.&lt;/p&gt;

&lt;h1&gt;
  
  
  Memória
&lt;/h1&gt;

&lt;p&gt;A memória entre os Workers não é compartilhada, já que cada worker recebe uma cópia da classe.&lt;/p&gt;

&lt;p&gt;Mas para trabalhar com memória compartilhada entre workers existem 3 funcionalidades nativas no Swoole:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.swoole.co.uk/docs/modules/swoole-buffer" rel="noopener noreferrer"&gt;swoole_buffer&lt;/a&gt;, &lt;a href="https://www.swoole.co.uk/docs/modules/swoole-channel" rel="noopener noreferrer"&gt;swoole_channel&lt;/a&gt;, &lt;a href="https://www.swoole.co.uk/docs/modules/swoole-table" rel="noopener noreferrer"&gt;swoole_table&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ou criar uma memória compartilhada via Unix Socket, um bom exemplo é o repositório abaixo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Yurunsoft/swoole-shared-memory" rel="noopener noreferrer"&gt;Swoole Shared Memory&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;No caso do nosso projeto, utilizamos a memória compartilhada via Unix Socket para as listas de FDs associando a uma hash e o Redis (Utilizando o Type Hash com Lua) para gerenciamento de salas.&lt;/p&gt;

&lt;p&gt;Outra dica importante é utilizar Ec2 focada em memória, pela maneira que o Swoole funciona.&lt;/p&gt;

&lt;h1&gt;
  
  
  Variáveis importantes do Callback
&lt;/h1&gt;

&lt;p&gt;A variável &lt;strong&gt;$frame&lt;/strong&gt; no escopo do callback possui 4 atributos importantes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;$frame-&amp;gt;fd:&lt;/strong&gt; Descritor de arquivo, é o id único de cada conexão no sistema.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cada aba dos clientes é um FD único associado a um hash.&lt;/li&gt;
&lt;li&gt;Por padrão o swoole usa um inteiro incremental iniciando de 1. &lt;strong&gt;Os FDs são resetados a cada vez que o server inicializa.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;$frame-&amp;gt;data&lt;/strong&gt;: A mensagem do cliente que chegou no websocket, na imagem acima seria o “1234567”.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;$frame-&amp;gt;opcode:&lt;/strong&gt; Tipo da mensagem, default é TEXT.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Exemplos de opcode:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WEBSOCKET_OPCODE_TEXT = 0x1, utf8 text data;&lt;/li&gt;
&lt;li&gt;WEBSOCKET_OPCODE_BINARY = 0x2, binary data;&lt;/li&gt;
&lt;li&gt;WEBSOCKET_OPCODE_PING = 0x9, ping data;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;$frame-&amp;gt;finish:&lt;/strong&gt; Retorna um boolean se o frame está completo.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;A variável &lt;strong&gt;$server&lt;/strong&gt; no escopo do callback possui 4 métodos/atributos importantes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;$server-&amp;gt;isEstablished($fd):&lt;/strong&gt; Retorna boolean se o &lt;strong&gt;FD&lt;/strong&gt; está conectado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$server-&amp;gt;push($fd, $message):&lt;/strong&gt; Envia a mensagem para o &lt;strong&gt;FD&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$server-&amp;gt;connection:&lt;/strong&gt; Retorna um array numérico com a lista de todos os &lt;strong&gt;FD&lt;/strong&gt;s conectados.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$server-&amp;gt;getClientInfo($fd):&lt;/strong&gt; Retorna um array com as informações do &lt;strong&gt;FD&lt;/strong&gt; fornecido.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  AWS Elastic Load Balance (timeout)
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Por padrão, o Elastic Load Balancing define o valor do tempo limite de inatividade para 60 segundos. Portanto, se o destino não enviar dados pelo menos a cada 60 segundos enquanto a solicitação estiver em trânsito, o load balancer poderá fechar a conexão front-end. Para garantir que operações demoradas, como uploads de arquivo, tenham tempo para serem concluídas, envie pelo menos 1 byte de dados antes de decorrer cada período de tempo limite de inatividade e aumente a duração do período do tempo limite de inatividade conforme o necessário.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/pt_br/elasticloadbalancing/latest/application/application-load-balancers.html#connection-idle-timeout" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/pt_br/elasticloadbalancing/latest/application/application-load-balancers.html#connection-idle-timeout&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Para resolver este problema, enviamos um pacote a cada 30 segundos utilizando o opcode de PING.&lt;/p&gt;

&lt;p&gt;Este pacote não ativa o evento onMessage e mantém todas as conexões ativas.&lt;/p&gt;

&lt;p&gt;Sem este keep_alive via ping, todos nossos clientes desconectariam e reconectariam a cada 60 segundos.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'managerStart'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$fd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;connections&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;isEstablished&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'ping'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;WEBSOCKET_OPCODE_PING&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Explicando o código acima, adicionamos no server um mapeamento para evento de callback &lt;strong&gt;managerStart&lt;/strong&gt; que será executado somente 1 vez por inicialização do servidor.&lt;/p&gt;

&lt;p&gt;Com isso adicionamos um timer de 30 segundos que vai correr a lista de todos FDs conectados no websocket, conferindo se o mesmo ainda está conectado e enviando um pacote de PING para manter a conexão aberta.&lt;/p&gt;

&lt;h1&gt;
  
  
  Task
&lt;/h1&gt;

&lt;p&gt;Utilizamos a task por exemplo para publicar no SNS (Simple Notification Service) da AWS uma cópia de cada mensagem que é trafegada no Websocket, mas você pode usa-la para qualquer tarefa não bloqueante dentro de todos os eventos.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'managerStart'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$server&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$task_id&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$from_id&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;awsService&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'topic'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'subject'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'payload'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;// Disparando manualmente uma task paralela&lt;/span&gt;&lt;br&gt;
&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;br&gt;
    &lt;span class="s1"&gt;'topic'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br&gt;
    &lt;span class="s1"&gt;'subject'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Message'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br&gt;
    &lt;span class="s1"&gt;'payload'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$frame&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Configurar a máquina para suportar 2 milhões de conexões&lt;br&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/mustafaturan/47268d8ad6d56cadda357e4c438f51ca" rel="noopener noreferrer"&gt;https://gist.github.com/mustafaturan/47268d8ad6d56cadda357e4c438f51ca&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Lista de callbacks
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://www.swoole.co.uk/docs/modules/swoole-server/callback-functions" rel="noopener noreferrer"&gt;https://www.swoole.co.uk/docs/modules/swoole-server/callback-functions&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusão
&lt;/h1&gt;

&lt;p&gt;Podemos concluir que realmente é possível desenvolver um servidor Websocket em PHP Swoole, escalável e sem muita complexidade, batendo de frente com as linguagens mais rápidas do mercado.&lt;/p&gt;

&lt;p&gt;O único cuidado é ao utilizar a memória compartilhada entre workers, não esqueça de remover o que não estiver sendo usado, pois o Swoole vai manter tudo em memória.&lt;/p&gt;

&lt;p&gt;Bom, é isso. Acabei resumindo muita coisa, mas caso precisem, eu posso explicar como funciona todo o sistema de handshake e gerenciamento entre workers em outro post, ou até mesmo desenvolver um chat de exemplo para a comunidade.&lt;/p&gt;

&lt;h1&gt;
  
  
  Fontes
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.swoole.co.uk" rel="noopener noreferrer"&gt;https://www.swoole.co.uk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.swoole.com/" rel="noopener noreferrer"&gt;https://wiki.swoole.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.treinaweb.com.br/blog/introducao-ao-swoole-framework-php-assincrono-baseado-em-corrotinas/" rel="noopener noreferrer"&gt;https://www.treinaweb.com.br/blog/introducao-ao-swoole-framework-php-assincrono-baseado-em-corrotinas/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/mustafaturan/47268d8ad6d56cadda357e4c438f51ca" rel="noopener noreferrer"&gt;https://gist.github.com/mustafaturan/47268d8ad6d56cadda357e4c438f51ca&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>php</category>
      <category>swoole</category>
      <category>websocket</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
