热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

MySQL异步c语言_PHP的异步、并行、高性能网络通信引擎,使用纯C语言编写

English|中文SwooleSwooleisanevent-drivenasynchronous&coroutine-basedconcurrencynetworkingcom

English | 中文

Swoole

mascot.png

Swoole is an event-driven asynchronous & coroutine-based concurrency networking communication engine with high performance written in C and C++ for PHP.

✨Event-based

The network layer in Swoole is event-based and takes full advantage of the underlying epoll/kqueue implementation, making it really easy to serve millions of requests.

Swoole 4.x uses a brand new engine kernel and now it has a full-time developer team, so we are entering an unprecedented period in PHP history which offers a unique possibility for rapid evolution in performance.

⚡️Coroutine

Swoole 4.x or later supports the built-in coroutine with high availability, and you can use fully synchronized code to implement asynchronous performance. PHP code without any additional keywords, the underlying automatic coroutine-scheduling.

Developers can understand coroutines as ultra-lightweight threads, and you can easily create thousands of coroutines in a single process.

MySQL

Concurrency 10K requests to read data from MySQL takes only 0.2s!

$s = microtime(true);

Co\run(function() {

for ($c = 100; $c--;) {

go(function () {

$mysql = new Swoole\Coroutine\MySQL;

$mysql->connect([

'host' => '127.0.0.1',

'user' => 'root',

'password' => 'root',

'database' => 'test'

]);

$statement = $mysql->prepare('SELECT * FROM `user`');

for ($n = 100; $n--;) {

$result = $statement->execute();

assert(count($result) > 0);

}

});

}

});

echo 'use ' . (microtime(true) - $s) . ' s';

Mixed server

You can create multiple services on the single event loop: TCP, HTTP, Websocket and HTTP2, and easily handle thousands of requests.

function tcp_pack(string $data): string

{

return pack('N', strlen($data)) . $data;

}

function tcp_unpack(string $data): string

{

return substr($data, 4, unpack('N', substr($data, 0, 4))[1]);

}

$tcp_options = [

'open_length_check' => true,

'package_length_type' => 'N',

'package_length_offset' => 0,

'package_body_offset' => 4

];

$server = new Swoole\WebSocket\Server('127.0.0.1', 9501, SWOOLE_BASE);

$server->set(['open_http2_protocol' => true]);

// http && http2

$server->on('request', function (Swoole\Http\Request $request, Swoole\Http\Response $response) {

$response->end('Hello ' . $request->rawcontent());

});

// websocket

$server->on('message', function (Swoole\WebSocket\Server $server, Swoole\WebSocket\Frame $frame) {

$server->push($frame->fd, 'Hello ' . $frame->data);

});

// tcp

$tcp_server = $server->listen('127.0.0.1', 9502, SWOOLE_TCP);

$tcp_server->set($tcp_options);

$tcp_server->on('receive', function (Swoole\Server $server, int $fd, int $reactor_id, string $data) {

$server->send($fd, tcp_pack('Hello ' . tcp_unpack($data)));

});

$server->start();

Coroutine clients

Whether you DNS query or send requests or receive responses, all of these are scheduled by coroutine automatically.

go(function () {

// http

$http_client = new Swoole\Coroutine\Http\Client('127.0.0.1', 9501);

assert($http_client->post('/', 'Swoole Http'));

var_dump($http_client->body);

// websocket

$http_client->upgrade('/');

$http_client->push('Swoole Websocket');

var_dump($http_client->recv()->data);

});

go(function () {

// http2

$http2_client = new Swoole\Coroutine\Http2\Client('localhost', 9501);

$http2_client->connect();

$http2_request = new Swoole\Http2\Request;

$http2_request->method = 'POST';

$http2_request->data = 'Swoole Http2';

$http2_client->send($http2_request);

$http2_response = $http2_client->recv();

var_dump($http2_response->data);

});

go(function () use ($tcp_options) {

// tcp

$tcp_client = new Swoole\Coroutine\Client(SWOOLE_TCP);

$tcp_client->set($tcp_options);

$tcp_client->connect('127.0.0.1', 9502);

$tcp_client->send(tcp_pack('Swoole Tcp'));

var_dump(tcp_unpack($tcp_client->recv()));

});

Channel

Channel is the only way for exchanging data between coroutines, the development combination of the Coroutine + Channel is the famous CSP programming model.

In Swoole development, Channel is usually used for implementing connection pool or scheduling coroutine concurrent.

The simplest example of a connection pool

In the following example, we have a thousand concurrently requests to redis. Normally, this has exceeded the maximum number of Redis connections setting and will throw a connection exception, but the connection pool based on Channel can perfectly schedule requests. We don't have to worry about connection overload.

class RedisPool

{

/**@var \Swoole\Coroutine\Channel */

protected $pool;

/**

* RedisPool constructor.

* @param int $size max connections

*/

public function __construct(int $size = 100)

{

$this->pool = new \Swoole\Coroutine\Channel($size);

for ($i &#61; 0; $i <$size; $i&#43;&#43;) {

$redis &#61; new \Swoole\Coroutine\Redis();

$res &#61; $redis->connect(&#39;127.0.0.1&#39;, 6379);

if ($res &#61;&#61; false) {

throw new \RuntimeException("failed to connect redis server.");

} else {

$this->put($redis);

}

}

}

public function get(): \Swoole\Coroutine\Redis

{

return $this->pool->pop();

}

public function put(\Swoole\Coroutine\Redis $redis)

{

$this->pool->push($redis);

}

public function close(): void

{

$this->pool->close();

$this->pool &#61; null;

}

}

go(function () {

$pool &#61; new RedisPool();

// max concurrency num is more than max connections

// but it&#39;s no problem, channel will help you with scheduling

for ($c &#61; 0; $c <1000; $c&#43;&#43;) {

go(function () use ($pool, $c) {

for ($n &#61; 0; $n <100; $n&#43;&#43;) {

$redis &#61; $pool->get();

assert($redis->set("awesome-{$c}-{$n}", &#39;swoole&#39;));

assert($redis->get("awesome-{$c}-{$n}") &#61;&#61;&#61; &#39;swoole&#39;);

assert($redis->delete("awesome-{$c}-{$n}"));

$pool->put($redis);

}

});

}

});

Producer and consumers

Some Swoole&#39;s clients implement the defer mode for concurrency, but you can still implement it flexible with a combination of coroutines and channels.

go(function () {

// User: I need you to bring me some information back.

// Channel: OK! I will be responsible for scheduling.

$channel &#61; new Swoole\Coroutine\Channel;

go(function () use ($channel) {

// Coroutine A: Ok! I will show you the github addr info

$addr_info &#61; Co::getaddrinfo(&#39;github.com&#39;);

$channel->push([&#39;A&#39;, json_encode($addr_info, JSON_PRETTY_PRINT)]);

});

go(function () use ($channel) {

// Coroutine B: Ok! I will show you what your code look like

$mirror &#61; Co::readFile(__FILE__);

$channel->push([&#39;B&#39;, $mirror]);

});

go(function () use ($channel) {

// Coroutine C: Ok! I will show you the date

$channel->push([&#39;C&#39;, date(DATE_W3C)]);

});

for ($i &#61; 3; $i--;) {

list($id, $data) &#61; $channel->pop();

echo "From {$id}:\n {$data}\n";

}

// User: Amazing, I got every information at earliest time!

});

Timer

$id &#61; Swoole\Timer::tick(100, function () {

echo "⚙️ Do something...\n";

});

Swoole\Timer::after(500, function () use ($id) {

Swoole\Timer::clear($id);

echo "⏰ Done\n";

});

Swoole\Timer::after(1000, function () use ($id) {

if (!Swoole\Timer::exists($id)) {

echo "✅ All right!\n";

}

});

The way of coroutine

go(function () {

$i &#61; 0;

while (true) {

Co::sleep(0.1);

echo "&#x1f4dd; Do something...\n";

if (&#43;&#43;$i &#61;&#61;&#61; 5) {

echo "&#x1f6ce; Done\n";

break;

}

}

echo "&#x1f389; All right!\n";

});

&#x1f525; Amazing runtime hooks

As of Swoole v4.1.0, we added the ability to transform synchronous PHP network libraries into co-routine libraries using a single line of code.

Simply call the Swoole\Runtime::enableCoroutine() method at the top of your script. In the sample below we connect to php-redis and concurrently read 10k requests in 0.1s:

Swoole\Runtime::enableCoroutine();

$s &#61; microtime(true);

Co\run(function() {

for ($c &#61; 100; $c--;) {

go(function () {

($redis &#61; new Redis)->connect(&#39;127.0.0.1&#39;, 6379);

for ($n &#61; 100; $n--;) {

assert($redis->get(&#39;awesome&#39;) &#61;&#61;&#61; &#39;swoole&#39;);

}

});

}

});

echo &#39;use &#39; . (microtime(true) - $s) . &#39; s&#39;;

By calling this method, the Swoole kernel replaces ZendVM stream function pointers. If you use php_stream based extensions, all socket operations can be dynamically converted to be asynchronous IO scheduled by coroutine at runtime!

How many things you can do in 1s?

Sleep 10K times, read, write, check and delete files 10K times, use PDO and MySQLi to communicate with the database 10K times, create a TCP server and multiple clients to communicate with each other 10K times, create a UDP server and multiple clients to communicate with each other 10K times... Everything works well in one process!

Just see what the Swoole brings, just imagine...

Swoole\Runtime::enableCoroutine();

$s &#61; microtime(true);

Co\run(function() {

// i just want to sleep...

for ($c &#61; 100; $c--;) {

go(function () {

for ($n &#61; 100; $n--;) {

usleep(1000);

}

});

}

// 10K file read and write

for ($c &#61; 100; $c--;) {

go(function () use ($c) {

$tmp_filename &#61; "/tmp/test-{$c}.php";

for ($n &#61; 100; $n--;) {

$self &#61; file_get_contents(__FILE__);

file_put_contents($tmp_filename, $self);

assert(file_get_contents($tmp_filename) &#61;&#61;&#61; $self);

}

unlink($tmp_filename);

});

}

// 10K pdo and mysqli read

for ($c &#61; 50; $c--;) {

go(function () {

$pdo &#61; new PDO(&#39;mysql:host&#61;127.0.0.1;dbname&#61;test;charset&#61;utf8&#39;, &#39;root&#39;, &#39;root&#39;);

$statement &#61; $pdo->prepare(&#39;SELECT * FROM &#96;user&#96;&#39;);

for ($n &#61; 100; $n--;) {

$statement->execute();

assert(count($statement->fetchAll()) > 0);

}

});

}

for ($c &#61; 50; $c--;) {

go(function () {

$mysqli &#61; new Mysqli(&#39;127.0.0.1&#39;, &#39;root&#39;, &#39;root&#39;, &#39;test&#39;);

$statement &#61; $mysqli->prepare(&#39;SELECT &#96;id&#96; FROM &#96;user&#96;&#39;);

for ($n &#61; 100; $n--;) {

$statement->bind_result($id);

$statement->execute();

$statement->fetch();

assert($id > 0);

}

});

}

// php_stream tcp server & client with 12.8K requests in single process

function tcp_pack(string $data): string

{

return pack(&#39;n&#39;, strlen($data)) . $data;

}

function tcp_length(string $head): int

{

return unpack(&#39;n&#39;, $head)[1];

}

go(function () {

$ctx &#61; stream_context_create([&#39;socket&#39; &#61;> [&#39;so_reuseaddr&#39; &#61;> true, &#39;backlog&#39; &#61;> 128]]);

$socket &#61; stream_socket_server(

&#39;tcp://0.0.0.0:9502&#39;,

$errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctx

);

if (!$socket) {

echo "$errstr ($errno)\n";

} else {

$i &#61; 0;

while ($conn &#61; stream_socket_accept($socket, 1)) {

stream_set_timeout($conn, 5);

for ($n &#61; 100; $n--;) {

$data &#61; fread($conn, tcp_length(fread($conn, 2)));

assert($data &#61;&#61;&#61; "Hello Swoole Server #{$n}!");

fwrite($conn, tcp_pack("Hello Swoole Client #{$n}!"));

}

if (&#43;&#43;$i &#61;&#61;&#61; 128) {

fclose($socket);

break;

}

}

}

});

for ($c &#61; 128; $c--;) {

go(function () {

$fp &#61; stream_socket_client("tcp://127.0.0.1:9502", $errno, $errstr, 1);

if (!$fp) {

echo "$errstr ($errno)\n";

} else {

stream_set_timeout($fp, 5);

for ($n &#61; 100; $n--;) {

fwrite($fp, tcp_pack("Hello Swoole Server #{$n}!"));

$data &#61; fread($fp, tcp_length(fread($fp, 2)));

assert($data &#61;&#61;&#61; "Hello Swoole Client #{$n}!");

}

fclose($fp);

}

});

}

// udp server & client with 12.8K requests in single process

go(function () {

$socket &#61; new Swoole\Coroutine\Socket(AF_INET, SOCK_DGRAM, 0);

$socket->bind(&#39;127.0.0.1&#39;, 9503);

$client_map &#61; [];

for ($c &#61; 128; $c--;) {

for ($n &#61; 0; $n <100; $n&#43;&#43;) {

$recv &#61; $socket->recvfrom($peer);

$client_uid &#61; "{$peer[&#39;address&#39;]}:{$peer[&#39;port&#39;]}";

$id &#61; $client_map[$client_uid] &#61; ($client_map[$client_uid] ?? -1) &#43; 1;

assert($recv &#61;&#61;&#61; "Client: Hello #{$id}!");

$socket->sendto($peer[&#39;address&#39;], $peer[&#39;port&#39;], "Server: Hello #{$id}!");

}

}

$socket->close();

});

for ($c &#61; 128; $c--;) {

go(function () {

$fp &#61; stream_socket_client("udp://127.0.0.1:9503", $errno, $errstr, 1);

if (!$fp) {

echo "$errstr ($errno)\n";

} else {

for ($n &#61; 0; $n <100; $n&#43;&#43;) {

fwrite($fp, "Client: Hello #{$n}!");

$recv &#61; fread($fp, 1024);

list($address, $port) &#61; explode(&#39;:&#39;, (stream_socket_get_name($fp, true)));

assert($address &#61;&#61;&#61; &#39;127.0.0.1&#39; && (int)$port &#61;&#61;&#61; 9503);

assert($recv &#61;&#61;&#61; "Server: Hello #{$n}!");

}

fclose($fp);

}

});

}

});

echo &#39;use &#39; . (microtime(true) - $s) . &#39; s&#39;;

⌛️ Installation

As with any open source project, Swoole always provides the most reliable stability and the most powerful features in the latest released version. Please ensure as much as possible that you are using the latest version.

Compiling requirements

Linux, OS X or Cygwin, WSL

PHP 7.0.0 or later (The higher the version, the better the performance.)

GCC 4.8 or later

1. Install via PECL (beginners)

pecl install swoole

2. Install from source (recommended)

Please download the source packages from Releases or:

git clone https://github.com/swoole/swoole-src.git && \

cd swoole-src && \

git checkout v4.x.x

Compile and install at the source folder:

phpize && \

./configure && \

make && make install

Enable extension in PHP

After compiling and installing to the system successfully, you have to add a new line extension&#61;swoole.so to php.ini to enable Swoole extension.

Extra compiler configurations

for example: ./configure --enable-openssl --enable-sockets

--enable-openssl or --with-openssl-dir&#61;DIR

--enable-sockets

--enable-http2

--enable-mysqlnd (need mysqlnd, it just for supporting $mysql->escape method)

Upgrade

⚠️ If you upgrade from source, don&#39;t forget to make clean before you upgrade your swoole

pecl upgrade swoole

git pull && cd swoole-src && make clean && make && sudo make install

if you change your PHP version, please re-run phpize clean && phpize then try to compile

Major change since version 4.3.0

Async clients and API are moved to a separate PHP extension swoole_async since version 4.3.0, install swoole_async:

git clone https://github.com/swoole/async-ext.git

cd async-src

phpize

./configure

make -j 4

sudo make install

Enable it by adding a new line extension&#61;swoole_async.so to php.ini.

&#x1f48e; Frameworks & Components

Hyperf is a coroutine framework that focuses on hyperspeed and flexibility, specifically used for build microservices or middlewares.

Swoft is a modern, high-performance AOP and coroutine PHP framework.

Easyswoole is a simple, high-performance PHP framework, based on Swoole, which makes using Swoole as easy as echo "hello world".

MixPHP is a powerful single-threaded coroutine framework with a very small footprint, simple and elegant.

imi is a high-performance coroutine application development framework based on PHP Swoole, which supports the development of HttpApi, WebSocket, TCP, UDP services.

Saber is a human-friendly, high-performance HTTP client component that has almost everything you can imagine.

One is a minimalist, high-performance PHP framework that supports the [swoole | php-fpm] environment

&#x1f6e0; Develop & Discussion

&#x1f36d; Benchmark

On the open source Techempower Web Framework benchmarks Swoole used MySQL database benchmark to rank first, and all performance tests ranked in the first echelon.

You can just run Benchmark Script to quickly test the maximum QPS of Swoole-HTTP-Server on your machine.

&#x1f530;️ Security issues

Security issues should be reported privately, via email, to the Swoole develop team team&#64;swoole.com. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message.

&#x1f58a;️ Contribution

Your contribution to Swoole development is very welcome!

You may contribute in the following ways:

Submit fixes, features via Pull Request

Write/polish documentation

❤️ Contributors

This project exists thanks to all the people who contribute. [Contributors]. 68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f73776f6f6c652d7372632f636f6e7472696275746f72732e7376673f77696474683d38393026627574746f6e3d66616c7365

&#x1f399;️ Official Evangelist

Demin has been playing with PHP since 2000, focusing on building high-performance, secure web services. He is an occasional conference speaker on PHP and Swoole, and has been working for companies in the states like eBay, Visa and Glu Mobile for years. You may find Demin on Twitter or GitHub.

&#x1f4c3; License



推荐阅读
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了如何使用iptables添加非对称的NAT规则段,以实现内网穿透和端口转发的功能。通过查阅相关文章,得出了解决方案,即当匹配的端口在映射端口的区间内时,可以成功进行端口转发。详细的操作步骤和命令示例也在文章中给出。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 本文介绍了在rhel5.5操作系统下搭建网关+LAMP+postfix+dhcp的步骤和配置方法。通过配置dhcp自动分配ip、实现外网访问公司网站、内网收发邮件、内网上网以及SNAT转换等功能。详细介绍了安装dhcp和配置相关文件的步骤,并提供了相关的命令和配置示例。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
author-avatar
Cri_Hello
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有