浏览目录

  • 构建服务消费者
  • 装置json rpc依赖
  • 装置JSON RPC客户端
  • server配置
  • 编写业务代码
  • 编写服务消费者类
  • consumer配置
  • 配置 UserServiceInterface
  • 编写UserController
  • postman测试
  • 主动配置服务消费者
  • 配置优化
  • 对立后果解决

咱们说过,服务提供者能够提供各种服务,它能够和数据库进行交互;服务消费者是纯生产的服务,只须要近程拜访服务提供者即可。

上面咱们按步骤构建消费者模块。

源码已上传至github,https://github.com/bailangzha...

1、构建服务消费者

除了对时区进行设置,其余的组件临时都不装置,抉择“n”即可。

composer create-project hyperf/hyperf-skeleton shop_consumer_user Creating a "hyperf/hyperf-skeleton" project at "./shop_consumer_user"Installing hyperf/hyperf-skeleton (v2.2.1)  - Installing hyperf/hyperf-skeleton (v2.2.1): Extracting archiveCreated project in /data/web/test/hyperf-rpc/shop_consumer_user> @php -r "file_exists('.env') || copy('.env.example', '.env');"> Installer\Script::installSetting up optional packagesSetup data and cache dirRemoving installer development dependencies  What time zone do you want to setup ?  [n] Default time zone for php.iniMake your selection or type a time zone name, like Asia/Shanghai (n):Asia/Shanghai  Do you want to use Database (MySQL Client) ?  [y] yes  [n] None of the above  Make your selection or type a composer package name and version (yes): n  Do you want to use Redis Client ?  [y] yes  [n] None of the above  Make your selection or type a composer package name and version (yes): n  Which RPC protocol do you want to use ?  [1] JSON RPC with Service Governance  [2] JSON RPC  [3] gRPC  [n] None of the above  Make your selection or type a composer package name and version (n): n  Which config center do you want to use ?  [1] Apollo  [2] Aliyun ACM  [3] ETCD  [4] Nacos  [n] None of the above  Make your selection or type a composer package name and version (n): n  Do you want to use hyperf/constants component ?  [y] yes  [n] None of the above  Make your selection (n): n  Do you want to use hyperf/async-queue component ? (A simple redis queue component)  [y] yes  [n] None of the above  Make your selection or type a composer package name and version (n): n  Do you want to use hyperf/amqp component ?  [y] yes  [n] None of the above  Make your selection or type a composer package name and version (n): n  Do you want to use hyperf/model-cache component ?  [y] yes  [n] None of the above  Make your selection or type a composer package name and version (n): n  Do you want to use hyperf/elasticsearch component ?  [y] yes  [n] None of the above  Make your selection or type a composer package name and version (n): n  Do you want to use hyperf/tracer component ? (An open tracing protocol component, adapte with Zipkin etc.)  [y] yes  [n] None of the above  Make your selection or type a composer package name and version (n): n

2、装置json rpc依赖

cd shop_consumer_usercomposer require hyperf/json-rpc

3、装置 JSON RPC 客户端

shop_consumer_user 不须要对外提供服务,所以咱们只装置客户端,不须要装置hyperf/rpc-server组件

composer require hyperf/rpc-client

4、server配置

server的配置这里用默认的就好了,9501端口提供http服务,不须要改变

'servers' => [    [        'name' => 'http',        'type' => Server::SERVER_HTTP,        'host' => '0.0.0.0',        'port' => 9501,        'sock_type' => SWOOLE_SOCK_TCP,        'callbacks' => [            Event::ON_REQUEST => [Hyperf\HttpServer\Server::class, 'onRequest'],        ],    ],],

5、编写业务代码

5-1、编写服务消费者类

app下新建JsonRpc目录,编写UserService.php和UserServiceInterface.php文件

【UserServiceInterface.php】<?phpnamespace App\JsonRpc;interface UserServiceInterface{    public function createUser(string $name, int $gender);    public function getUserInfo(int $id);}<span class="redactor-invisible-space"></span>【UserService.php】<?phpnamespace App\JsonRpc;use Hyperf\RpcClient\AbstractServiceClient;class UserService extends AbstractServiceClient implements UserServiceInterface{    /**     * 定义对应服务提供者的服务名称     * @var string     */    protected $serviceName = 'UserService';    /**     * 定义对应服务提供者的服务协定     * @var string     */    protected $protocol = 'jsonrpc-http';    /**     * @param string $name     * @param int $gender     * @return mixed     */    public function createUser(string $name, int $gender)    {        return $this->__request(__FUNCTION__, compact('name', 'gender'));    }    /**     * @param int $id     * @return mixed     */    public function getUserInfo(int $id)    {        return $this->__request(__FUNCTION__, compact('id'));    }}

hyperf 官网的hyperf/rpc-client组件曾经帮咱们实现了rpc近程调用的实现,所以咱们只须要再配置一下服务消费者,通知hyperf从哪个节点哪个端口调用即可。

5-2、consumer配置

config/autoload/services.php内定义consumers如下:(没有services.php文件的能够自行创立)

<?phpreturn [    'consumers' => [        [            // 对应消费者类的 $serviceName            'name' => 'UserService',            // 间接对指定的节点进行生产,通过上面的 nodes 参数来配置服务提供者的节点信息            'nodes' => [                ['host' => '127.0.0.1', 'port' => 9600],            ],        ]    ],];

5-3、配置 UserServiceInterface

为了能够不便的注入 UserServiceInterface,咱们在 config/autoload/dependencies.php 内定义 UserServiceInterface 和 UserService 的关系如下:

App\JsonRpc\UserServiceInterface::class => App\JsonRpc\UserService::class,

5-4、编写UserController,实现获取用户和创立用户的接口调用

【app\Controller\UserController.php】<?phpdeclare(strict_types=1);namespace App\Controller;use App\JsonRpc\UserServiceInterface;use Hyperf\Di\Annotation\Inject;use Hyperf\HttpServer\Annotation\AutoController;/** * Class UserController * @package App\Controller * @AutoController() */class UserController extends AbstractController{    /**     * @Inject()     * @var UserServiceInterface     */    private $userServiceClient;    public function createUser()    {        $name = (string) $this->request->input('name', '');        $gender = (int) $this->request->input('gender', 0);        return $this->userServiceClient->createUser($name, $gender);    }    public function getUserInfo()    {        $id = (int) $this->request->input('id');        return $this->userServiceClient->getUserInfo($id);    }}

6、postman拜访测试

启动shop_consumer_user我的项目的同时,务必要保障 shop_provider_user 也启动了,不然申请会失败。

7、主动配置服务消费者

你可能曾经留神到 app\JsonRpc\UserService 类的办法并没有实际意义,只是构建参数发动申请并返回响应后果,千篇一律的操作着实减少了复杂度。hyperf反对主动配置服务消费者代理类(生产者暂不反对主动配置)。

主动配置非常简单,只须要在 consumer 配置项减少service配置即可,如下:

return [    'consumers' => [        [            // 对应消费者类的 $serviceName            'name' => 'UserService',            // 服务接口名,可选,默认值等于 name 配置的值,如果 name 间接定义为接口类则可疏忽此行配置,            // 如 name 为字符串则须要配置 service 对应到接口类            'service' => \App\JsonRpc\UserServiceInterface::class,            // 间接对指定的节点进行生产,通过上面的 nodes 参数来配置服务提供者的节点信息            'nodes' => [                ['host' => '127.0.0.1', 'port' => 9600],            ],        ]    ],];

当初咱们做两件事,测试consumer走的是主动配置还是手动创立的UserService

  1. 把 config/autoload/dependencies.php 内定义 UserServiceInterface 和 UserService 的关系屏蔽
  2. 在 App\JsonRpc\UserService::getUserInfo() 办法内打印点数据测试
GET申请 http://127.0.0.1:9501/user/getUserInfo?id=2后果发现控制台并没有任何输入,走的是主动配置的consumer

反过来

  1. 咱们再把 config/autoload/dependencies.php 内定义 UserServiceInterface 和 UserService 的关系放开
  2. 把 config/autoload/services.php 文件内 consumers 的配置项 service 屏蔽
GET申请 http://127.0.0.1:9501/user/getUserInfo?id=2string(36) "App\JsonRpc\UserService::getUserInfo"发现控制台输入了咱们在 App\JsonRpc\UserService::getUserInfo() 办法内打印的数据,走的是手动创立的consumer

在没有非凡状况下,后续consumer咱们仅做配置,不在手动创立,因为没有创立的必要。

8、配置优化

咱们留神到 config/autoload/services.php 文件内 consumers 的配置,一个服务是一个配置,服务消费者须要生产的服务可能很多,所以咱们很有必要优化下这里的写法,上面是参考官网的写法:

// 服务定义$consumerServices = [    'UserService' => \App\JsonRpc\UserServiceInterface::class,];return [    'consumers' => value(function () use ($consumerServices) {        $consumers = [];        foreach ($consumerServices as $name => $interface) {            $consumers[] = [                'name' => $name,                'service' => $interface,                'nodes' => [                    ['host' => '127.0.0.1', 'port' => 9600],                ],            ];        }        return $consumers;    }),];

这样一来,咱们每次只须要在数组 $consumerServices 内增加须要新的服务即可。

最初,咱们来看一个比拟大的问题。

consumer拿到的后果,又是字符串又是对象,还动不动间接 Internal Server Error. 数据格式的不对立十分不利于前端小伙伴解析。

对立后果解决

为了标准,咱们制订了一个简略的规范,对立返回带有code,message,data的数据格式,有趣味的小伙伴能够先钻研下怎么解决这个问题,咱们下一节持续。