рд╣рдо рд╕реНрд╡реЛрдЗрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╡реЗрдмрд╕реЛрдХреЗрдЯ рдкрд░ рдПрдХ рдСрдирд▓рд╛рдЗрди рдЪреИрдЯ рд▓рд┐рдЦрддреЗ рд╣реИрдВ



рд╡реЗрдмрд╕реЛрдХреЗрдЯреНрд╕ рдХрд╛ рд╡рд┐рд╖рдп рдкрд╣рд▓реЗ рд╣реА рдмрд╛рд░-рдмрд╛рд░ рд╣реИрдмреЗ рдкрд░ рдЫреБрдЖ рдЧрдпрд╛ рдерд╛ , PHP рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢реЗрд╖ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╡рд┐рднрд┐рдиреНрди рддрдХрдиреАрдХреЛрдВ рдХреЗ рдЕрд╡рд▓реЛрдХрди рдХреЗ рд╕рд╛рде рдЕрдВрддрд┐рдо рд▓реЗрдЦ рдХреЗ рдмрд╛рдж рд╕реЗ рдПрдХ рд╡рд░реНрд╖ рд╕реЗ рдЕрдзрд┐рдХ рд╕рдордп рдмреАрдд рдЪреБрдХрд╛ рд╣реИ, рдФрд░ PHP рджреБрдирд┐рдпрд╛ рдореЗрдВ рд╕рдордп рдХреЗ рд╕рд╛рде рдШрдордВрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╣реИ ред

рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ Swoole рдХреЛ рд░реВрд╕реА рднрд╛рд╖реА рд╕рдореБрджрд╛рдп рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рдХрд░рд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ - PHP рдХреЗ рд▓рд┐рдП рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдУрдкрди рд╕реЛрд░реНрд╕ рдлреНрд░реЗрдорд╡рд░реНрдХ, рд╕реА рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ, рдФрд░ рдПрдХ pecl рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреЗ рд░реВрдк рдореЗрдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рдЧреАрдереВрдм рдкрд░ рд╕реВрддреНрд░ ред

рдЭрдкрдЯреНрдЯрд╛ рдХреНрдпреЛрдВ?


рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдРрд╕реЗ рд▓реЛрдЧ рд╣реЛрдВрдЧреЗ рдЬреЛ рд╕реИрджреНрдзрд╛рдВрддрд┐рдХ рд░реВрдк рд╕реЗ рдРрд╕реЗ рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП PHP рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдЦрд┐рд▓рд╛рдл рд╣реЛрдВрдЧреЗ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╡реЗ рдЕрдХреНрд╕рд░ PHP рдХреЗ рдкрдХреНрд╖ рдореЗрдВ рдЦреЗрд▓ рд╕рдХрддреЗ рд╣реИрдВ:

  • рдкрд░рд┐рдпреЛрдЬрдирд╛ рдкрд░ рд╡рд┐рднрд┐рдиреНрди рднрд╛рд╖рд╛рдУрдВ рдХреЗ рдЪрд┐рдбрд╝рд┐рдпрд╛рдШрд░ рдХрд╛ рдкреНрд░рдЬрдирди рдХрд░рдиреЗ рдХреА рдЕрдирд┐рдЪреНрдЫрд╛
  • рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╡рд┐рдХрд╕рд┐рдд рдХреЛрдб рдЖрдзрд╛рд░ (рдпрджрд┐ рдкрд░рд┐рдпреЛрдЬрдирд╛ PHP рдореЗрдВ рд╣реИ) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ред

рдлрд┐рд░ рднреА, рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдиреЛрдб.рдЬреЗрдПрд╕ / рдЧреЛ / рдПрд░рд▓рдВрдЧ рдФрд░ рдЕрдиреНрдп рднрд╛рд╖рд╛рдУрдВ рдХреЗ рд╕рд╛рде рддреБрд▓рдирд╛ рдХрд░рдирд╛, рдЬреЛ рдореВрд▓ рд░реВрдк рд╕реЗ рдПрдХ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдореЙрдбрд▓ рдХреА рдкреЗрд╢рдХрд╢ рдХрд░рддреЗ рд╣реИрдВ, рд╕реНрд╡реЛрд▓реЗ - рд╕реА рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдПрдХ рдврд╛рдВрдЪрд╛ рдФрд░ рдХрдо рдкреНрд░рд╡реЗрд╢ рд╕реАрдорд╛ рдФрд░ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рд╕рдВрдпреЛрдЬрди рдПрдХ рдЕрдЪреНрдЫрд╛ рдЙрдореНрдореАрджрд╡рд╛рд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

рдврд╛рдВрдЪреЗ рдХреА рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдВ:

  • рдШрдЯрдирд╛, рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдореЙрдбрд▓
  • рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдЯреАрд╕реАрдкреА / рдпреВрдбреАрдкреА / рдПрдЪрдЯреАрдЯреАрдкреА / рд╡реЗрдмрд╕реЛрдХреЗрдЯ / рдПрдЪрдЯреАрдЯреАрдкреА реи рдХреНрд▓рд╛рдЗрдВрдЯ / рд╕рд░реНрд╡рд░ рдПрдкреАрдЖрдИ
  • IPv4 / IPv6 / Unixsocket / TCP / UDP рдФрд░ SSL / TLS рдХрд╛ рд╕рдорд░реНрдерди рдХрд░реЗрдВ
  • рддреЗрдЬреА рд╕реЗ рдбреЗрдЯрд╛ рдХреНрд░рдорд╛рдВрдХрди / deserialization
  • рдЙрдЪреНрдЪ рдкреНрд░рджрд░реНрд╢рди, рдПрдХреНрд╕реНрдЯреЗрдВрд╕рд┐рдмрд┐рд▓рд┐рдЯреА, 1 рдорд┐рд▓рд┐рдпрди рддрдХ рдПрдХ рд╕рд╛рде рдХрдиреЗрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди
  • рдорд┐рд▓рд┐рд╕рдХреЙрдиреНрдб рдХрд╛рд░реНрдп рдЕрдиреБрд╕реВрдЪрдХ
  • рдЦреБрд▓рд╛ рд╕реНрд░реЛрдд
  • Coroutines рдХрд╛ рд╕рдорд░реНрдерди

рд╕рдВрднрд╛рд╡рд┐рдд рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ:

  • Mikroservisy
  • рдЦреЗрд▓ рд╕рд░реНрд╡рд░
  • рдЪреАрдЬреЛрдВ рдХрд╛ рдЗрдВрдЯрд░рдиреЗрдЯ
  • рд▓рд╛рдЗрд╡ рд╕рдВрдЪрд╛рд░ рдкреНрд░рдгрд╛рд▓реА
  • рд╡реЗрдм рдПрдкреАрдЖрдИ
  • рдХрд┐рд╕реА рднреА рдЕрдиреНрдп рд╕реЗрд╡рд╛рдУрдВ рдХреЛ рддрддреНрдХрд╛рд▓ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ / рдЙрдЪреНрдЪ рдЧрддрд┐ / рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдирд┐рд╖реНрдкрд╛рджрди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ

рд╕рд╛рдЗрдЯ рдХреЗ рдореБрдЦреНрдп рдкреГрд╖реНрда рдкрд░ рдХреЛрдб рдХреЗ рдЙрджрд╛рд╣рд░рдг рджреЗрдЦреЗ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред рдкреНрд░рд▓реЗрдЦрди рдЕрдиреБрднрд╛рдЧ рдореЗрдВ, рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреА рд╕рднреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддреГрдд рдЬрд╛рдирдХрд╛рд░реАред

рдЪрд▓рд┐рдП рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ


рдиреАрдЪреЗ рдореИрдВ рдСрдирд▓рд╛рдЗрди рдЪреИрдЯ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ рд╡реЗрдмрд╕реЛрдХреЗрдЯ рд╕рд░реНрд╡рд░ рд▓рд┐рдЦрдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдФрд░ рдЗрд╕рдХреЗ рд╕рд╛рде рд╕рдВрднрд╛рд╡рд┐рдд рдХрдард┐рдирд╛рдЗрдпреЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░реВрдВрдЧрд╛ред

рд╢реБрд░реВ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ: swoole_websocket_server рдФрд░ swoole_server classes рдкрд░ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА (рджреВрд╕рд░реА рдХрдХреНрд╖рд╛ рдкрд╣рд▓реА рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓реА рд╣реИ)ред
рдЪреИрдЯ рдХреЗ рд╕реВрддреНрд░ред

рдврд╛рдВрдЪрд╛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛
Linux users

#!/bin/bash
pecl install swoole

Mac users

# get a list of avaiable packages
brew install swoole
#!/bin/bash
brew install homebrew/php/php71-swoole


рдЖрдИрдбреАрдИ рдореЗрдВ рд╕реНрд╡рдд: рдкреВрд░реНрдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдпрд╣ рд╡рд┐рдЪрд╛рд░рдзрд╛рд░рд╛-рд╕рд╣рд╛рдпрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рд╣реИ

рдиреНрдпреВрдирддрдо рд╡реЗрдмрд╕реЛрдХреЗрдЯ рд╕рд░реНрд╡рд░ рдЯреЗрдореНрдкрд▓реЗрдЯ:

 <?php $server = new swoole_websocket_server("127.0.0.1", 9502); $server->on('open', function($server, $req) { echo "connection open: {$req->fd}\n"; }); $server->on('message', function($server, $frame) { echo "received message: {$frame->data}\n"; $server->push($frame->fd, json_encode(["hello", "world"])); }); $server->on('close', function($server, $fd) { echo "connection close: {$fd}\n"; }); $server->start(); 

$ fd рдХрдиреЗрдХреНрд╢рди рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рд╣реИред
рд╡рд░реНрддрдорд╛рди рдХрдиреЗрдХреНрд╢рди рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ:

 $server->connections; 

$ рдлрд╝реНрд░реЗрдо рдореЗрдВ рднреЗрдЬреЗ рдЧрдП рд╕рднреА рдбреЗрдЯрд╛ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рдпрд╣рд╛рдБ рдПрдХ рд╡рд╕реНрддреБ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдЬреЛ рдСрдирдореИрд╕реЗрдЬ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдЖрдпрд╛ рд╣реИ:

 Swoole\WebSocket\Frame Object ( [fd] => 20 [data] => {"type":"login","username":"new user"} [opcode] => 1 [finish] => 1 ) 

рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдбреЗрдЯрд╛ рднреЗрдЬрд╛ рдЬрд╛рддрд╛ рд╣реИ

 Server::push($fd, $data, $opcode=null, $finish=null) 

рд░реВрд╕реА рдореЗрдВ рдлреНрд░реЗрдо рдФрд░ рдУрдкрдХреЛрдб рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдФрд░ рдЬрд╛рдиреЗрдВ ред javascript ред рдЕрдиреБрднрд╛рдЧ "рдбреЗрдЯрд╛ рдкреНрд░рд╛рд░реВрдк"

Websocket рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд┐рддрдирд╛ рд╕рдВрднрд╡ рд╣реЛ - RFC

рдФрд░ рд╕рд░реНрд╡рд░ рдкрд░ рдЖрдП рдбреЗрдЯрд╛ рдХреЛ рдХреИрд╕реЗ рдмрдЪрд╛рдпрд╛ рдЬрд╛рдП?
Swoole MySQL , Redis , рдлрд╝рд╛рдЗрд▓ I / O рдХреЗ рд╕рд╛рде рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд░реВрдк рд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рдкрд░рд┐рдЪрдп рджреЗрддрд╛ рд╣реИ

рд╕рд╛рде рд╣реА swoole_buffer , swoole_channel рдФрд░ swoole_table
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдкреНрд░рд▓реЗрдЦрди рд╕реЗ рдЕрдВрддрд░ рд╕рдордЭрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдореЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ swoole_table рдХрд╛ рдЪрдпрди рдХрд┐рдпрд╛ред рд╕рдВрджреЗрд╢ рд╕реНрд╡рдпрдВ MySQL рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реЛрддреЗ рд╣реИрдВред

рдЗрд╕рд▓рд┐рдП, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо рддрд╛рд▓рд┐рдХрд╛ рдХрд╛ рдЖрд░рдВрдн:

 $users_table = new swoole_table(131072); $users_table->column('id', swoole_table::TYPE_INT, 5); $users_table->column('username', swoole_table::TYPE_STRING, 64); $users_table->create(); 

рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рднрд░рдирд╛ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:

 $count = count($messages_table); $dateTime = time(); $row = ['username' => $username, 'message' => $data->message, 'date_time' => $dateTime]; $messages_table->set($count, $row); 

MySQL рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдЕрднреА рддрдХ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдореЙрдбрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛, рд▓реЗрдХрд┐рди рдЗрд╕реЗ рдкреАрдбреАрдУ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╡реЗрдм рд╕реЙрдХреЗрдЯ рд╕рд░реНрд╡рд░ рд╕реЗ рдорд╛рдирдХ рддрд░реАрдХреЗ рд╕реЗ рдПрдХреНрд╕реЗрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред

рдЖрдзрд╛рд░ рдХреА рдЕрдкреАрд▓
 /** * @return Message[] */ public function getAll() { $stmt = $this->pdo->query('SELECT * from messages'); $messages = []; foreach ($stmt->fetchAll() as $row) { $messages[] = new Message( $row['username'], $row['message'], new \DateTime($row['date_time']) ); } return $messages; } 


Websocket рд╕рд░реНрд╡рд░ рдХреЛ рдПрдХ рд╡рд░реНрдЧ рдХреЗ рд░реВрдк рдореЗрдВ рдЬрд╛рд░реА рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рдЗрд╕реЗ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рд╢реБрд░реВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛:

рдбрд┐рдЬрд╛рдЗрдирд░
 public function __construct() { $this->ws = new swoole_websocket_server('0.0.0.0', 9502); $this->ws->on('open', function ($ws, $request) { $this->onConnection($request); }); $this->ws->on('message', function ($ws, $frame) { $this->onMessage($frame); }); $this->ws->on('close', function ($ws, $id) { $this->onClose($id); }); $this->ws->on('workerStart', function (swoole_websocket_server $ws) { $this->onWorkerStart($ws); }); $this->ws->start(); } 


рд╕рдорд╕реНрдпрд╛рдУрдВ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рд╛:

  1. рдХреЛрдИ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ 60 рд╕реЗрдХрдВрдб рдХреЗ рдмрд╛рдж рдЪреИрдЯ рдбрд┐рд╕реНрдХрдиреЗрдХреНрдЯ рдХрд░рддрд╛ рд╣реИ рдпрджрд┐ рдХреЛрдИ рдкреИрдХреЗрдЯ рдПрдХреНрд╕рдЪреЗрдВрдЬ рдирд╣реАрдВ рд╣реИ (рдпрд╛рдиреА, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдиреЗ рдХреБрдЫ рднреА рдирд╣реАрдВ рднреЗрдЬрд╛ рдпрд╛ рдкреНрд░рд╛рдкреНрдд рдирд╣реАрдВ рдХрд┐рдпрд╛)
  2. рдпрджрд┐ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдХреЛрдИ рдмрд╛рддрдЪреАрдд рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ, рддреЛ рд╡реЗрдмрд╕рд░реНрд╡рд░ MySQL рдХреЗ рд╕рд╛рде рд╕рдВрдмрдВрдз рдЦреЛ рджреЗрддрд╛ рд╣реИ

рд╕рдорд╛рдзрд╛рди:

рджреЛрдиреЛрдВ рд╣реА рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рд╣рдореЗрдВ рдкрд┐рдВрдЧ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬреЛ рдкрд╣рд▓реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рд╣рд░ n рд╕реЗрдХрдВрдб рдореЗрдВ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдкрд┐рдВрдЧ рдХрд░реЗрдЧрд╛, рдФрд░ рджреВрд╕рд░реЗ рдореЗрдВ MySQL рдбреЗрдЯрд╛рдмреЗрд╕ред

рдЪреВрдВрдХрд┐ рджреЛрдиреЛрдВ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд░реВрдк рд╕реЗ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЗрд╕рд▓рд┐рдП рдЙрдиреНрд╣реЗрдВ рд╕рд░реНрд╡рд░ рдХреА рдмрд╛рд▓ рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдореЗрдВ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЙрдиреНрд╣реЗрдВ "рд╡рд░реНрдХрд░рд╕реНрдЯрд╛рд░реНрдЯ" рдИрд╡реЗрдВрдЯ рдХреЗ рд╕рд╛рде рдЖрд░рдВрдн рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд╣рдордиреЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЗрд╕реЗ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рд╣реИ, рдФрд░ рдЗрд╕ рдШрдЯрдирд╛ рдХреЗ рд╕рд╛рде $ рдЗрд╕-> onWorkerStart рд╡рд┐рдзрд┐ рдХреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ:
Websocket рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдкрд┐рдВрдЧ-рдкреЛрдВрдЧ рдмреЙрдХреНрд╕ рд╕реЗ рдмрд╛рд╣рд░ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред рдиреАрдЪреЗ рдЖрдк рд╕реНрд╡реЛрд▓ рдкрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред

onWorkerStart
 private function onWorkerStart(swoole_websocket_server $ws) { $this->messagesRepository = new MessagesRepository(); $ws->tick(self::PING_DELAY_MS, function () use ($ws) { foreach ($ws->connections as $id) { $ws->push($id, 'ping', WEBSOCKET_OPCODE_PING); } }); } 


рдЗрд╕рдХреЗ рдмрд╛рдж, рдореИрдВрдиреЗ sSQL рдФрд░ рдЯрд╛рдЗрдорд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рддреНрдпреЗрдХ N рд╕реЗрдХрдВрдб рдореЗрдВ рдПрдХ MySQL рд╕рд░реНрд╡рд░ рдХреЛ рдкрд┐рдВрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдлрд╝рдВрдХреНрд╢рди рд▓рд╛рдЧреВ рдХрд┐рдпрд╛:

DatabaseHelper
рдЯрд╛рдЗрдорд░ рд╣реА initPdo рдореЗрдВ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ рдЕрдЧрд░ рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реИ:

  /** * Init new Connection, and ping DB timer function */ private static function initPdo() { if (self::$timerId === null || (!Timer::exists(self::$timerId))) { self::$timerId = Timer::tick(self::MySQL_PING_INTERVAL, function () { self::ping(); }); } self::$pdo = new PDO(self::DSN, DBConfig::USER, DBConfig::PASSWORD, self::OPT); } /** * Ping database to maintain the connection */ private static function ping() { try { self::$pdo->query('SELECT 1'); } catch (PDOException $e) { self::initPdo(); } } 


рдХрд╛рдо рдХреЗ рдореБрдЦреНрдп рднрд╛рдЧ рдореЗрдВ рдЬреЛрдбрд╝рдиреЗ, рд╕рд╣реЗрдЬрдиреЗ, рд╕рдВрджреЗрд╢ рднреЗрдЬрдиреЗ (рд╕рд╛рдорд╛рдиреНрдп CRUD рд╕реЗ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдирд╣реАрдВ) рдХреЗ рд▓рд┐рдП рддрд░реНрдХ рд▓рд┐рдЦрдиреЗ рдФрд░ рдлрд┐рд░ рд╕реБрдзрд╛рд░ рдХреА рдмрд╣реБрдд рдмрдбрд╝реА рдЧреБрдВрдЬрд╛рдЗрд╢ рдереАред

рдЕрдм рддрдХ рдореИрдВ рдЕрдкрдиреЗ рдХреЛрдб рдХреЛ рдЕрдзрд┐рдХ рдпрд╛ рдХрдо рдкрдардиреАрдп рд░реВрдк рдФрд░ рдПрдХ рд╡рд╕реНрддреБ-рдЙрдиреНрдореБрдЦ рд╢реИрд▓реА рдореЗрдВ рд▓рд╛рдпрд╛ рд╣реВрдВ, рдореИрдВрдиреЗ рдереЛрдбрд╝реА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд▓рд╛рдЧреВ рдХреА рд╣реИ:

- рдирд╛рдо рд╕реЗ рд▓реЙрдЧрд┐рди рдХрд░реЗрдВ;

- рдЬрд╛рдВрдЪреЗрдВ рдХрд┐ рдирд╛рдо рд╡реНрдпрд╕реНрдд рдирд╣реАрдВ рд╣реИ
 /** * @param string $username * @return bool */ private function isUsernameCurrentlyTaken(string $username) { foreach ($this->usersRepository->getByIds($this->ws->connection_list()) as $user) { if ($user->getUsername() == $username) { return true; } } return false; } 


- рд╕реНрдкреИрдо рд╕реАрдордХ
 <?php namespace App\Helpers; use Swoole\Channel; class RequestLimiter { /** * @var Channel */ private $userIds; const MAX_RECORDS_COUNT = 10; const MAX_REQUESTS_BY_USER = 4; public function __construct() { $this->userIds = new Channel(1024 * 64); } /** * Check if there are too many requests from user * and make a record of request from that user * * @param int $userId * @return bool */ public function checkIsRequestAllowed(int $userId) { $requestsCount = $this->getRequestsCountByUser($userId); $this->addRecord($userId); if ($requestsCount >= self::MAX_REQUESTS_BY_USER) return false; return true; } /** * @param int $userId * @return int */ private function getRequestsCountByUser(int $userId) { $channelRecordsCount = $this->userIds->stats()['queue_num']; $requestsCount = 0; for ($i = 0; $i < $channelRecordsCount; $i++) { $userIdFromChannel = $this->userIds->pop(); $this->userIds->push($userIdFromChannel); if ($userIdFromChannel === $userId) { $requestsCount++; } } return $requestsCount; } /** * @param int $userId */ private function addRecord(int $userId) { $recordsCount = $this->userIds->stats()['queue_num']; if ($recordsCount >= self::MAX_RECORDS_COUNT) { $this->userIds->pop(); } $this->userIds->push($userId); } } 

рдкреБрдирд╢реНрдЪ: рд╣рд╛рдБ, рдХрдиреЗрдХреНрд╢рди рдЖрдИрдбреА рдкрд░ рд╕рддреНрдпрд╛рдкрди рд╣реИред рд╢рд╛рдпрдж рдпрд╣ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдЗрд╕реЗ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдЖрдИрдкреА рдкрддреЗ рдХреЗ рд╕рд╛рдеред

рдореБрдЭреЗ рдпрд╣ рднреА рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдпрд╣ swoole_channel рдерд╛ рдЬреЛ рд╕рдмрд╕реЗ рдЙрдкрдпреБрдХреНрдд рдерд╛ред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдмрд╛рдж рдореЗрдВ рдЗрд╕ рдкрд▓ рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред

- ezyang / htmlpurifier рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рд░рд▓ XSS рд╕реБрд░рдХреНрд╖рд╛

- рд╕рд┐рдВрдкрд▓ рд╕реНрдкреИрдо рдлрд┐рд▓реНрдЯрд░
рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЕрддрд┐рд░рд┐рдХреНрдд рдЪреЗрдХ рдЬреЛрдбрд╝рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдХреЗ рд╕рд╛рдеред

 <?php namespace App\Helpers; class SpamFilter { /** * @var string[] errors */ private $errors = []; /** * @param string $text * @return bool */ public function checkIsMessageTextCorrect(string $text) { $isCorrect = true; if (empty(trim($text))) { $this->errors[] = 'Empty message text'; $isCorrect = false; } return $isCorrect; } /** * @return string[] errors */ public function getErrors(): array { return $this->errors; } } 


рдлреНрд░рдВрдЯреЗрдВрдб рдЪреИрдЯ рдЕрднреА рднреА рдмрд╣реБрдд рдХрдЪреНрдЪреА рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдореИрдВ рдмреИрдХрдПрдВрдб рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рдЖрдХрд░реНрд╖рд┐рдд рд╣реВрдВ, рд▓реЗрдХрд┐рди рдЬрдм рдЕрдзрд┐рдХ рд╕рдордп рд╣реЛрдЧрд╛, рддреЛ рдореИрдВ рдЗрд╕реЗ рдФрд░ рдЕрдзрд┐рдХ рд╕реБрдЦрдж рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ред

рдЬрд╛рдирдХрд╛рд░реА рдХрд╣рд╛рдБ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ, рд░реВрдкрд░реЗрдЦрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рдорд╛рдЪрд╛рд░ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ?


  • рдЕрдВрдЧреНрд░реЗрдЬреА рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рд╕рд╛рдЗрдЯ - рдЙрдкрдпреЛрдЧреА рд▓рд┐рдВрдХ, рдЕрдк-рдЯреВ-рдбреЗрдЯ рдкреНрд░рд▓реЗрдЦрди, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рд╕реЗ рдХреБрдЫ рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдВ
  • рдЯреНрд╡рд┐рдЯрд░ - рд╡рд░реНрддрдорд╛рди рд╕рдорд╛рдЪрд╛рд░, рдЙрдкрдпреЛрдЧреА рд▓рд┐рдВрдХ, рджрд┐рд▓рдЪрд╕реНрдк рд▓реЗрдЦ
  • рдЗрд╢реНрдпреВ рдЯреНрд░реИрдХрд░ (рдЬреАрдереВрдм) - рдмрдЧ, рдкреНрд░рд╢реНрди, рд░реВрдкрд░реЗрдЦрд╛ рдХреЗ рд░рдЪрдирд╛рдХрд╛рд░реЛрдВ рдХреЗ рд╕рд╛рде рд╕рдВрдЪрд╛рд░ред рд╡реЗ рдмрд╣реБрдд рдЪрд╛рд▓рд╛рдХреА рд╕реЗ рдЬрд╡рд╛рдм рджреЗрддреЗ рд╣реИрдВ (рдЙрдиреНрд╣реЛрдВрдиреЗ рдХреБрдЫ рдШрдВрдЯреЛрдВ рдореЗрдВ рдПрдХ рд╕рд╡рд╛рд▓ рдХреЗ рд╕рд╛рде рдореЗрд░реЗ рд╕рд╡рд╛рд▓ рдХрд╛ рдЬрд╡рд╛рдм рджрд┐рдпрд╛, рдкрд┐рдВрдЧрд▓реЛрдк рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдорджрдж рдХреА)ред
  • рдмрдВрдж рдореБрджреНрджреЗ - рдореИрдВ рднреА рд╕рд▓рд╛рд╣ рджреЗрддрд╛ рд╣реВрдВред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд╕рд╡рд╛рд▓реЛрдВ рдХрд╛ рдПрдХ рдмрдбрд╝рд╛ рдбреЗрдЯрд╛рдмреЗрд╕ рдФрд░ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЗ рд░рдЪрдирд╛рдХрд╛рд░реЛрдВ рд╕реЗ рдЙрддреНрддрд░ред
  • рдбреЗрд╡рд▓рдкрд░реНрд╕ рджреНрд╡рд╛рд░рд╛ рд▓рд┐рдЦрд┐рдд рдкрд░реАрдХреНрд╖рдг - рдкреНрд░рд▓реЗрдЦрди рдХреЗ рд▓рдЧрднрдЧ рд╣рд░ рдореЙрдбреНрдпреВрд▓ рдореЗрдВ PHP рдореЗрдВ рд▓рд┐рдЦреЗ рдЧрдП рдкрд░реАрдХреНрд╖рдг рд╣реИрдВ, рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рджрд┐рдЦрд╛рддреЗ рд╣реИрдВред
  • рдЪреАрдиреА рд╡рд┐рдХреА рдлреНрд░реЗрдорд╡рд░реНрдХ - рдЕрдВрдЧреНрд░реЗрдЬреА рдореЗрдВ рдЬреИрд╕рд╛ рдХрд┐ рд╕рднреА рдЬрд╛рдирдХрд╛рд░реА рд╣реИ, рд▓реЗрдХрд┐рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рд╕реЗ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдВ (рдорджрдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Google рдЕрдиреБрд╡рд╛рджрдХ)ред

рдПрдкреАрдЖрдИ рдкреНрд░рд▓реЗрдЦрди - рдХрд╛рдлреА рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд░реВрдк рдореЗрдВ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЗ рдХреБрдЫ рд╡рд░реНрдЧреЛрдВ рдФрд░ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рд╡рд┐рд╡рд░рдгред

рд╕рд╛рд░рд╛рдВрд╢


рдпрд╣ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╕реНрд╡реЛрд▓реЛрд▓ рдкрд┐рдЫрд▓реЗ рд╕рд╛рд▓ рдмрд╣реБрдд рд╕рдХреНрд░рд┐рдп рд░реВрдк рд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рд╣реЛ рд░рд╣рд╛ рд╣реИ, рдпрд╣ рдордВрдЪ рд╕реЗ рдмрд╛рд╣рд░ рдЖ рдЧрдпрд╛ рд╣реИ рдЬрдм рдЗрд╕реЗ "рдХрдЪреНрдЪрд╛" рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдЕрдм рдпрд╣ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдФрд░ рдиреЗрдЯрд╡рд░реНрдХ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдиреЛрдб.рдЬреЗрдПрд╕ / рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рд╕рд╛рде рдкреВрд░реНрдг рдкреНрд░рддрд┐рдпреЛрдЧрд┐рддрд╛ рдореЗрдВ рд╣реИред

рдореБрдЭреЗ рдЙрди рд╡рд┐рд╖рдпреЛрдВ рдкрд░ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд░рд╛рдп рд╕реБрдирдиреЗ рдФрд░ рдЙрди рд▓реЛрдЧреЛрдВ рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рдЦреБрд╢реА рд╣реЛрдЧреА рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕реНрд╡реЛрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдЕрдиреБрднрд╡ рд░рдЦрддреЗ рд╣реИрдВ

рдЖрдк рд▓рд┐рдВрдХ рджреНрд╡рд╛рд░рд╛ рдЪреИрдЯ рд░реВрдо рдореЗрдВ рдЪреИрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ
рдЧреАрдереВрдм рдкрд░ рд╕реНрд░реЛрдд рдЙрдкрд▓рдмреНрдз рд╣реИрдВред

Source: https://habr.com/ru/post/hi427589/


All Articles