浏览目录
- 构建服务消费者
- 装置 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 archive
Created project in /data/web/test/hyperf-rpc/shop_consumer_user
> @php -r "file_exists('.env') || copy('.env.example','.env');"
> Installer\Script::install
Setting up optional packages
Setup data and cache dir
Removing installer development dependencies
What time zone do you want to setup ?
[n] Default time zone for php.ini
Make 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_user
composer 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】<?php
namespace App\JsonRpc;
interface UserServiceInterface
{public function createUser(string $name, int $gender);
public function getUserInfo(int $id);
}
<span class="redactor-invisible-space">
</span>【UserService.php】<?php
namespace 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 文件的能够自行创立)
<?php
return [
'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】<?php
declare(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
- 把 config/autoload/dependencies.php 内定义 UserServiceInterface 和 UserService 的关系屏蔽
- 在 App\JsonRpc\UserService::getUserInfo() 办法内打印点数据测试
GET 申请 http://127.0.0.1:9501/user/getUserInfo?id=2
后果发现控制台并没有任何输入,走的是主动配置的 consumer
反过来
- 咱们再把 config/autoload/dependencies.php 内定义 UserServiceInterface 和 UserService 的关系放开
- 把 config/autoload/services.php 文件内 consumers 的配置项 service 屏蔽
GET 申请 http://127.0.0.1:9501/user/getUserInfo?id=2
string(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 的数据格式,有趣味的小伙伴能够先钻研下怎么解决这个问题,咱们下一节持续。