PHPackages                             luoxiaojun/grpc - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. luoxiaojun/grpc

ActiveLibrary[HTTP &amp; Networking](/categories/http)

luoxiaojun/grpc
===============

Grpc PHP Client base on Swoole Http2 Coroutine &amp; Service Generator

v1.0.5(5y ago)15.7k1Apache-2.0PHPPHP &gt;=7.1

Since Oct 18Pushed 4y ago1 watchersCompare

[ Source](https://github.com/luoxiaojun1992/grpc)[ Packagist](https://packagist.org/packages/luoxiaojun/grpc)[ RSS](/packages/luoxiaojun-grpc/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (4)Dependencies (1)Versions (8)Used By (1)

Swoole-Grpc-Client
==================

[](#swoole-grpc-client)

[![Latest Version](https://camo.githubusercontent.com/ddf920d145d0d2dc4a89cca8f6289eb49155e5f43cfa691049d92e26a77eb994/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f72656c656173652f73776f6f6c652f677270632d636c69656e742e737667)](https://github.com/swoole/grpc-client/releases)[![Php Version](https://camo.githubusercontent.com/c197ef1e57a32c886b2a54d02ead7dbc035f18b3f39a642703b9372eef7819f9/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d2533453d372e312d627269676874677265656e2e7376673f6d61784167653d32353932303030)](https://secure.php.net/)[![Swoole Version](https://camo.githubusercontent.com/4827b21711de47a3b4a2e4b32ae0e65ac88207e52e822312d18c9f871b2f46e7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f73776f6f6c652d2533453d342e302e342d627269676874677265656e2e7376673f6d61784167653d32353932303030)](https://github.com/swoole/swoole-src)[![Swoole License](https://camo.githubusercontent.com/1c419f89412ea6c234c184ad6d85decb127c18584858d3707ae7d8e2131eccc4/68747470733a2f2f696d672e736869656c64732e696f2f686578706d2f6c2f706c75672e7376673f6d61784167653d32353932303030)](https://github.com/swoole/grpc-client/blob/master/LICENSE)

Introduction
------------

[](#introduction)

由Swoole驱动的Grpc协程客户端, 底层使用高性能协程Http2-Client客户端

- 同步代码几乎无改动
    - 自动**协程调度获得异步高性能**
    - 提供Grpc代码生成器Plus版, 0成本迁移
- 基于Channel实现的消息生产消费
    - **一个客户端连接**即可**同时**hold住**上万个**请求响应
    - 支持跨协程并发, 多类型Client分享同一连接

Requirement
-----------

[](#requirement)

- PHP7及以上
- [Swoole](https://github.com/swoole/swoole-src): v4.4.0及以上, StreamingCall支持需要v4.5.3及以上
- [Protobuf](https://github.com/google/protobuf/tree/master/php)
- [grpc\_php\_plugin](https://github.com/grpc/grpc/)
- 请不要启用grpc的php扩展, 也无需grpc的php库
- 请不要启用protobuf的php扩展, 也无需protobuf的php库

Usage
-----

[](#usage)

仓库已提供Etcd的生成代码, 如要自己根据proto文件生成代码, 请使用`tools`目录下的生成工具`generator`, 使用方法和`protoc`命令完全一样, 增强了支持以目录作为参数, 自动查找目录下的proto文件生成, 如: 该目录下已提供的`grpc`生成代码脚本:

```
# it's generate_grpc.sh
./generator \
--proto_path=./../src/Grpc/Proto \
--php_out=./../src/Grpc \
--grpc_out=./../src/Grpc \
--grpc_php_out=./src/Grpc \
--plugin=protoc-gen-grpc=$1 \
--custom_plugin=protoc-gen-grpc-php=./../bin/protoc-gen-grpc-php-plugin.php \
./../src/Grpc/Proto
```

只需要将proto文件放在`Grpc/Proto`下, 运行`./generate_grpc.sh ../../grpc/bins/opt/grpc_php_plugin` (参数是你的grpc php插件位置, 一般在`grpc/bins/opt`目录中), 即可生成相关代码

生成的文件目录结构如下

```
src/Grpc
├── GPBMetadata
│   └── Helloworld.php
├── Helloworld
│   ├── GreeterClient.php           -- php service client
│   ├── HelloReply.php              -- request message class generated by protoc
│   └── HelloRequest.php            -- response message class generated by protoc
└── Services
    ├── GreeterClient.php           -- php service client for sw-fw-less
    ├── GreeterInterface.php        -- php service interface for sw-fw-less
    └── GreeterService.php          -- php server side service for sw-fw-less

```

Examples
--------

[](#examples)

> 以下示例都可在`examples`目录下找到并直接运行

### Grpc

[](#grpc)

---

#### HelloWorld

[](#helloworld)

经典的Grpc官方示例, 代码更加简洁

```
$greeterClient = new GreeterClient('127.0.0.1:50051');
$request = new HelloRequest();
$request->setName('Swoole');
list($reply, $status) = $greeterClient->SayHello($request);
$message = $reply->getMessage();
echo "{$message}\n"; // Output: Hello Swoole
```

### Etcd

[](#etcd)

---

Etcd的几个基本操作的使用

#### Put

[](#put)

```
use Swoole\Coroutine;

Coroutine::create(function () {
    $kvClient = new Etcdserverpb\KVClient(GRPC_SERVER_DEFAULT_URI);
    $request = new Etcdserverpb\PutRequest();
    $request->setPrevKv(true);
    $request->setKey('Hello');
    $request->setValue('Swoole');
    [$reply, $status] = $kvClient->Put($request);
    if ($status === 0) {
        echo "{$reply->getPrevKv()->getKey()}\n";
        echo "{$reply->getPrevKv()->getValue()}\n";
    } else {
        echo "Error#{$status}: {$reply}\n";
    }
    $kvClient->close();
});
```

#### Watch

[](#watch)

> 创建一个协程负责Watch, 创建两个协程定时写入/删除键值以便观察效果

```
use Etcdserverpb\WatchCreateRequest;
use Etcdserverpb\WatchCreateRequest\FilterType;
use Etcdserverpb\WatchRequest;
use Swoole\Coroutine;

// The Watcher
Coroutine::create(function () {
    $watchClient = new Etcdserverpb\WatchClient(GRPC_SERVER_DEFAULT_URI);

    $watchCall = $watchClient->Watch();
    $request = new WatchRequest();
    $createRequest = new WatchCreateRequest();
    $createRequest->setKey('Hello');
    $request->setCreateRequest($createRequest);

    _retry:
    $watchCall->push($request);
    /**@var $reply Etcdserverpb\WatchResponse */
    while (true) {
        [$reply, $status] = $watchCall->recv();
        if ($status === 0) { // success
            if ($reply->getCreated() || $reply->getCanceled()) {
                continue;
            }
            foreach ($reply->getEvents() as $event) {
                /**@var $event Mvccpb\Event */
                $type = $event->getType();
                $kv = $event->getKv();
                if (FilterType::NOPUT === $type) {
                    echo "Put key {$kv->getKey()} => {$kv->getValue()}\n";
                    break;
                } elseif (FilterType::NODELETE === $type) {
                    echo "Delete key {$kv->getKey()}\n";
                    break;
                }
            }
        } else { // failed
            static $retry_time = 0;
            if ($watchClient->isConnected()) {
                $retry_time++;
                echo "Retry#{$retry_time}\n";
                goto _retry;
            } else {
                echo "Error#{$status}: {$reply}\n";
                break;
            }
        }
    }
    $watchClient->close();
});

// The Writer Put and Delete
Coroutine::create(function () {
    $kvClient = new Etcdserverpb\KVClient(GRPC_SERVER_DEFAULT_URI);
    Coroutine::create(function () use ($kvClient) {
        $request = new Etcdserverpb\PutRequest();
        $request->setKey('Hello');
        $request->setPrevKv(true);
        while (true) {
            static $count = 0;
            Coroutine::sleep(.5);
            $request->setValue('Swoole#' . (++$count));
            [$reply, $status] = $kvClient->Put($request);
            if ($status !== 0) {
                echo "Error#{$status}: {$reply}\n";
                break;
            }
        }
        $kvClient->close();
    });
    Coroutine::create(function () use ($kvClient) {
        $request = new Etcdserverpb\DeleteRangeRequest();
        $request->setKey('Hello');
        $request->setPrevKv(true);
        while (true) {
            Coroutine::sleep(1);
            [$reply, $status] = $kvClient->DeleteRange($request);
            if ($status !== 0) {
                echo "Error#{$status}: {$reply}\n";
                break;
            }
        }
        $kvClient->close();
    });
});
```

#### Auth and Share Client

[](#auth-and-share-client)

> 用户添加/展示/删除以及展示了如何让不同类型的EtcdClient能够使用同一个Grpc\\Client创建的连接

```
use Swoole\Coroutine;

Coroutine::create(function () {
    $grpcClient = new Grpc\Client(GRPC_SERVER_DEFAULT_URI);
    // use in different type clients

    Coroutine::create(function () use ($grpcClient) {
        $kvClient = new Etcdserverpb\KVClient(GRPC_SERVER_DEFAULT_URI, ['use' => $grpcClient]);
        $request = new Etcdserverpb\PutRequest();
        $request->setPrevKv(true);
        $request->setKey('Hello');
        $request->setValue('Swoole');
        [$reply, $status] = $kvClient->Put($request);
        if ($status === 0) {
            echo "\n=== PUT KV OK ===\n";
        } else {
            echo "Error#{$status}: {$reply}\n";
        }
    });

    Coroutine::create(function () use ($grpcClient) {
        $authClient = new Etcdserverpb\AuthClient(GRPC_SERVER_DEFAULT_URI, ['use' => $grpcClient]);

        $userRequest = new Etcdserverpb\AuthUserAddRequest();
        $userNames = ['ranCoroutine::create', 'twosee', 'gxh', 'stone', 'sjl'];
        foreach ($userNames as $username) {
            $userRequest->setName($username);
            [$reply, $status] = $authClient->UserAdd($userRequest);
            if ($status !== 0) {
                goto _error;
            }
        }

        $useListRequest = new Etcdserverpb\AuthUserListRequest();
        [$reply, $status] = $authClient->UserList($useListRequest);
        if ($status !== 0) {
            goto _error;
        }
        echo "\n=== SHOW USER LIST ===\n";
        foreach ($reply->getUsers() as $user) {
            /**@var \Authpb\User */
            echo "* {$user}\n";
        }
        echo "=== SHOW USER LIST OK ===\n";

        $userRequest = new Etcdserverpb\AuthUserDeleteRequest();
        foreach ($userNames as $username) {
            $userRequest->setName($username);
            [$reply, $status] = $authClient->UserDelete($userRequest);
            if ($status !== 0) {
                goto _error;
            }
        }

        if (false) {
            _error:
            echo "Error#{$status}: {$reply}\n";
        }

        echo "\n=== SHOW ALL CLIENT STATS ===\n";
        var_dump(grpc_client_num_stats());
        $grpcClient->close();
    });

});
```

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity19

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity61

Established project with proven stability

 Bus Factor1

Top contributor holds 55.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~154 days

Recently: every ~185 days

Total

6

Last Release

1990d ago

PHP version history (2 changes)v1.0.0PHP &gt;=7.0

v1.0.2PHP &gt;=7.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/3a9a7ab17addb5818306fe7052bf2fa4c5028284ab1e6c91c26894cf645cbf5f?d=identicon)[luoxiaojun1992](/maintainers/luoxiaojun1992)

---

Top Contributors

[![twose](https://avatars.githubusercontent.com/u/25978241?v=4)](https://github.com/twose "twose (27 commits)")[![luoxiaojun1992](https://avatars.githubusercontent.com/u/6905700?v=4)](https://github.com/luoxiaojun1992 "luoxiaojun1992 (15 commits)")[![sy-records](https://avatars.githubusercontent.com/u/33931153?v=4)](https://github.com/sy-records "sy-records (2 commits)")[![Reasno](https://avatars.githubusercontent.com/u/3881629?v=4)](https://github.com/Reasno "Reasno (1 commits)")[![huangzhhui](https://avatars.githubusercontent.com/u/12077148?v=4)](https://github.com/huangzhhui "huangzhhui (1 commits)")[![woody712](https://avatars.githubusercontent.com/u/3671429?v=4)](https://github.com/woody712 "woody712 (1 commits)")[![inhere](https://avatars.githubusercontent.com/u/5302062?v=4)](https://github.com/inhere "inhere (1 commits)")[![matyhtf](https://avatars.githubusercontent.com/u/2017766?v=4)](https://github.com/matyhtf "matyhtf (1 commits)")

---

Tags

httpphpclienthttp2generatorgRPCserviceswoolecoroutineetcd

### Embed Badge

![Health badge](/badges/luoxiaojun-grpc/health.svg)

```
[![Health](https://phpackages.com/badges/luoxiaojun-grpc/health.svg)](https://phpackages.com/packages/luoxiaojun-grpc)
```

###  Alternatives

[swoole/grpc

Grpc PHP Client base on Swoole Http2 Coroutine

19718.9k1](/packages/swoole-grpc)[swoole/etcd-client

Grpc PHP Client base on Swoole Http2 Coroutine

1973.2k1](/packages/swoole-etcd-client)[swlib/saber

Swoole coroutine HTTP client

985145.0k27](/packages/swlib-saber)[simps/mqtt

MQTT Protocol Analysis and Coroutine Client for PHP

39351.6k9](/packages/simps-mqtt)[swoft/http-client

HTTP Client Component for Swoft

1139.3k4](/packages/swoft-http-client)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
