带你轻松使用Hyperf玩转Grpc(六)服务发现

六、服务发现

前面,我们已经将服务实现并注册到 nacos了。下面我们将完成api项目,并从nacos发现并使用服务。

进入 code/api/mall-api 目录中 执行

(小白须知:可以再开个命令行窗口,docker exec -it mall-php /bin/bash 进入容器,之前跑的 服务就不用关掉了 )

composer require crayoon/hyperf-grpc-client

引入我们需要的插件。并执行

php bin/hyperf.php vendor:publish crayoon/hyperf-grpc-client

生成配置文件,同理 我们需要关注 nacos 的配置,还不清楚在哪配置的 移步下 上一篇哈。

1、生成代码

在 mall-api 根目录中执行

protoc --php_out=./ --grpc_out=./ --plugin=protoc-gen-grpc=/usr/local/lib/grpc_php_plugin -I=/app/proto product_srv.proto

在 app/Grpc 目录下新建 GrpcClient 目录

需要复制 app/Grpc/Mall/ProductSrv/ProductSrvClient 到 app/Grpc/GrpcClient 目录下并且修改

<?php

namespace App\Grpc\GrpcClient;

use Crayoon\HyperfGrpcClient\BaseGrpcClient;

/**
 */
class ProductSrvClient extends BaseGrpcClient {  //父类换成 Crayoon\HyperfGrpcClient\BaseGrpcClient

    //注意这里的 构造方法去除

    /**
     * @param \App\Grpc\Mall\ProductSrv\ProductCreateRequest $argument input argument
     * @param array $metadata metadata
     * @param array $options call options
     * @return array  //返回 替换成 array
     */
    public function create(\App\Grpc\Mall\ProductSrv\ProductCreateRequest $argument,
      $metadata = [], $options = []) {
        return $this->_simpleRequest('/mall.ProductSrv/create',
        $argument,
        ['\App\Grpc\Mall\ProductSrv\ProductId', 'decode'],
        $metadata, $options);
    }

    /**
     * @param \App\Grpc\Mall\ProductSrv\ProductListRequest $argument input argument
     * @param array $metadata metadata
     * @param array $options call options
     * @return array
     */
    public function getList(\App\Grpc\Mall\ProductSrv\ProductListRequest $argument,
      $metadata = [], $options = []) {
        return $this->_simpleRequest('/mall.ProductSrv/getList',
        $argument,
        ['\App\Grpc\Mall\ProductSrv\ProductListReply', 'decode'],
        $metadata, $options);
    }

    /**
     * @param \App\Grpc\Mall\ProductSrv\ProductId $argument input argument
     * @param array $metadata metadata
     * @param array $options call options
     * @return array
     */
    public function getStock(\App\Grpc\Mall\ProductSrv\ProductId $argument,
      $metadata = [], $options = []) {
        return $this->_simpleRequest('/mall.ProductSrv/getStock',
        $argument,
        ['\App\Grpc\Mall\ProductSrv\ProductStockReply', 'decode'],
        $metadata, $options);
    }

    /**
     * @param \App\Grpc\Mall\ProductSrv\ProductStockRequest $argument input argument
     * @param array $metadata metadata
     * @param array $options call options
     * @return array
     */
    public function incStock(\App\Grpc\Mall\ProductSrv\ProductStockRequest $argument,
      $metadata = [], $options = []) {
        return $this->_simpleRequest('/mall.ProductSrv/incStock',
        $argument,
        ['\App\Grpc\Mall\ProductSrv\ProductStockReply', 'decode'],
        $metadata, $options);
    }

    /**
     * @param \App\Grpc\Mall\ProductSrv\ProductStockRequest $argument input argument
     * @param array $metadata metadata
     * @param array $options call options
     * @return array
     */
    public function decStock(\App\Grpc\Mall\ProductSrv\ProductStockRequest $argument,
      $metadata = [], $options = []) {
        return $this->_simpleRequest('/mall.ProductSrv/decStock',
        $argument,
        ['\App\Grpc\Mall\ProductSrv\ProductStockReply', 'decode'],
        $metadata, $options);
    }

}

2、编写控制器

并通过注入获取请求客户端

<?php

namespace App\Controller;

use App\Grpc\GrpcClient\ProductSrvClient;
use App\Grpc\Mall\ProductSrv\Product;
use App\Grpc\Mall\ProductSrv\ProductCreateRequest;
use App\Grpc\Mall\ProductSrv\ProductId;
use App\Grpc\Mall\ProductSrv\ProductListReply;
use App\Grpc\Mall\ProductSrv\ProductListRequest;
use Hyperf\Grpc\StatusCode;

//注意这里引入的是 修改后的客户端

class ProductController extends AbstractController
{
    public function __construct(
        protected ProductSrvClient $productSrvClient
    )
    {
    }

    public function create(): array
    {
        $param = $this->request->post();
        //@todo 这里需要验证器验证传参,略

        [$reply, $status] = $this->productSrvClient->create(
            (new ProductCreateRequest())
                ->setTitle($param['title'] ?? '')
                ->setIcon($param['icon'] ?? '')
                ->setStock($param['stock'] ?? 0)
        );
        if ($status != StatusCode::OK) {
            //就直接报错啦
            return [
                "code" => 1,
                "message" => $reply ?? 'fail'
            ];
        }
        /**
         * @var ProductId $reply
         */
        return [
            "code" => 0,
            "message" => 'ok',
            "data" => ["id" => $reply->getId()]
        ];
    }

    public function list(): array
    {
        $param = $this->request->query();

        [$reply, $status] = $this->productSrvClient->getList(
            (new ProductListRequest())
                ->setPage($param['page'] ?? 1)
                ->setPageSize($param['pageSize'] ?? 10)
        );
        if ($status != StatusCode::OK) {
            return [
                "code" => 1,
                "message" => $reply ?? 'fail'
            ];
        }
        $temp = [];
        /**
         * @var ProductListReply $reply
         * @var Product $item
         */
        foreach ($reply->getList() as $item) {
            $temp[] = json_decode($item->serializeToJsonString(),true); //懒人模式
        }
        return [
            "code" => 0,
            "message" => 'ok',
            "data" => [
                "total" => $reply->getTotal(),
                "list" => $temp
            ]
        ];
    }
}

3、配置路由

修改 config/routes.php 加入

Router::addGroup("/product", function () {
    Router::post("/create", [\App\Controller\ProductController::class, 'create']);
    Router::get("/list", [\App\Controller\ProductController::class, 'list']);
});

4、启动并访问

在 mall-api 根目录中执行

php bin/hyperf.php start

看到 [INFO] HTTP Server listening at 0.0.0.0:9501 即启动成功。

我们通过postman访问 看看。

第一次会相对比较慢,因为需要获取grpc连接客户端。

再次试下 访问 127.0.0.1:9501/product/list 会发现速度变快啦

总结

可以发现,我们并无配置 product服务地址,但插件自动帮我们在nacos中发现并使用了服务地址。我们把 mall-service 关闭,再访问看看

[ERROR] Get Node[mall] From nacos[round-robin] Fail! Because:Cannot select any node from load balancer.

程序就会提示我们,无节点可访问。感兴趣的同学可以 把策略改成 加权轮询(weighted-round-robin),并且再 nacos 中设置权重试试。

本作品采用《CC 协议》,转载必须注明作者和本文链接
from crayxn github.com/crayxn
本帖由 MArtian 于 1年前 加精
讨论数量: 2

应该是grpc链接不上

file

导致这一步会出现http错误!

file

顺着走下来就走不下去了。奇怪了

10个月前 评论
Crayxn (楼主) 10个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!