hyperf從零開始構(gòu)建微服務(wù)(一)——構(gòu)建服務(wù)提供者

閱讀目錄

上一篇文章我們了解了如何使用hyperf對項目進行垂直拆分,這是我們整個微服務(wù)模塊的基礎(chǔ)。

hyperf支持JSON-RPC和gRPC,我們在分布式服務(wù)架構(gòu)一文中介紹過什么是JSON-RPC以及JSON-RPC請求響應(yīng)的案例(后來做的補充),后面我們會著重以JSON-RPC為例來解決整個微服務(wù)系統(tǒng)出現(xiàn)的各種問題。

首先我們加以明確什么是服務(wù)。

服務(wù)有兩種角色,一種是 服務(wù)提供者(ServiceProvider),即為其它服務(wù)提供服務(wù)的服務(wù),另一種是 服務(wù)消費者(ServiceConsumer),即依賴其它服務(wù)的服務(wù),一個服務(wù)既可能是 服務(wù)提供者(ServiceProvider),同時又是 服務(wù)消費者(ServiceConsumer)。而兩者直接可以通過 服務(wù)契約 來定義和約束接口的調(diào)用,在 Hyperf 里,可直接理解為就是一個 接口類(Interface),通常來說這個接口類會同時出現(xiàn)在提供者和消費者下。——摘自官網(wǎng)。

簡單的說,我們的項目模塊將會被分為服務(wù)提供者模塊和服務(wù)消費者模塊。 服務(wù)提供者模塊指的是提供各種服務(wù)的模塊,它需要與數(shù)據(jù)庫進行交互。 服務(wù)消費者模塊指的是消費服務(wù)的模塊。它需要遠程訪問服務(wù)提供者。

本節(jié)課的源碼已上傳至github,https://github.com/bailangzhan/hyperf-rpc

下面我們按照步驟,看看如何構(gòu)建服務(wù)提供者。

1、創(chuàng)建數(shù)據(jù)表

CREATE DATABASE hyperf;
USE hyperf;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(30) NOT NULL DEFAULT '' COMMENT '姓名',
  `gender` tinyint(1) NOT NULL DEFAULT '0' COMMENT '性別 1男 2女 0未知',
  `created_at` int(11) NOT NULL DEFAULT '0' COMMENT '創(chuàng)建時間',
  `updated_at` int(11) NOT NULL DEFAULT '0' COMMENT '更新時間',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用戶基礎(chǔ)表';

2、構(gòu)建服務(wù)提供者

composer create-project hyperf/hyperf-skeleton shop_provider_user

安裝的時候會讓我們選擇默認的組件,除了時區(qū)和數(shù)據(jù)庫外,其他一律選擇“n”,選擇如下

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): y
  - Adding package hyperf/database (~2.2.0)
  - Adding package hyperf/db-connection (~2.2.0)
  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

需要什么組件后面可以我們再自行添加。

3、安裝json rpc依賴

cd shop_provider_user
composer require hyperf/json-rpc

4、安裝rpc server組件

我們準備讓 shop_provider_user 應(yīng)用對外提供服務(wù),所以需要安裝 rpc server組件

composer require hyperf/rpc-server

5、修改server配置

shop_provider_user 提供的是 jsonrpc服務(wù),不需要提供http服務(wù),所以屏蔽 http 服務(wù)配置,新加 jsonrpc-http 服務(wù)。

hyperf支持 jsonrpc-http 協(xié)議、jsonrpc 協(xié)議以及jsonrpc-tcp-length-check 協(xié)議,我們后續(xù)都將以 jsonrpc-http為例。

以下配置在 config/autoload/server.php 文件內(nèi),注意 jsonrpc-http服務(wù)配置的端口號是9600

'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'],
//            ],
//        ],
    [
        'name' => 'jsonrpc-http',
        'type' => Server::SERVER_HTTP,
        'host' => '0.0.0.0',
        'port' => 9600,
        'sock_type' => SWOOLE_SOCK_TCP,
        'callbacks' => [
            Event::ON_REQUEST => [\Hyperf\JsonRpc\HttpServer::class, 'onRequest'],
        ],
    ],
],

6、配置數(shù)據(jù)庫

修改.env文件,修改 APP_NAME以及數(shù)據(jù)庫配置

APP_NAME=shop_provider_user
DB_DRIVER=mysql
DB_HOST=192.168.33.20
DB_PORT=3306
DB_DATABASE=hyperf
DB_USERNAME=www
DB_PASSWORD=123456
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_unicode_ci
DB_PREFIX=

7、編寫基礎(chǔ)代碼

7-1、編寫model代碼

生成model并修改如下:

php bin/hyperf.php gen:model User
【app/Model/User.php】
<?php
declare (strict_types=1);
namespace App\Model;
use Hyperf\DbConnection\Model\Model;
/**
 */
class User extends Model
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'user';
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['name', 'gender'];
    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = ['id' => 'integer', 'gender' => 'integer'];
    // 自定義時間戳的格式 U表示int
    protected $dateFormat = 'U';
}

7-2、編寫service代碼

app下新建JsonRpc目錄,編寫UserService.php和UserServiceInterface.php文件。

UserServiceInterface 對外提供兩個接口,一個用于創(chuàng)建用戶,一個用于獲取用戶信息。

【UserServiceInterface】
<?php
namespace App\JsonRpc;
interface UserServiceInterface
{
    public function createUser(string $name, int $gender);
    public function getUserInfo(int $id);
}
【UserService】
<?php
namespace App\JsonRpc;
use App\Model\User;
use Hyperf\RpcServer\Annotation\RpcService;
/**
 * @RpcService(name="UserService", protocol="jsonrpc-http", server="jsonrpc-http")
 */
class UserService implements UserServiceInterface
{
    /**
     * @param string $name
     * @param string $gender
     * @return string
     */
    public function createUser(string $name, int $gender)
    {
        if (empty($name)) {
            throw new \RuntimeException("name不能為空");
        }
        $result = User::query()->create([
            'name' => $name,
            'gender' => $gender,
        ]);
        return $result ? "success" : "fail";
    }
    /**
     * @param int $id
     * @return array
     */
    public function getUserInfo(int $id)
    {
        $user = User::query()->find($id);
        if (empty($user)) {
            throw new \RuntimeException("user not found");
        }
        return $user->toArray();
    }
}

注意,在 UserService 類中,我們使用了 @RpcService 注解,記得 use Hyperf\RpcServer\Annotation\RpcService;

@RpcService 共有 4 個參數(shù),也就是 Hyperf\RpcServer\Annotation\RpcService 的4個屬性:

  1. name 屬性為定義該服務(wù)的名稱,注意不同的service不要用相同的名字,該名字唯一,Hyperf 會根據(jù)該屬性生成對應(yīng)的 ID 注冊到服務(wù)中心去,后面我們會詳細介紹,這里有個印象就好;
  2. protocol 屬性為定義該服務(wù)暴露的協(xié)議,目前僅支持 jsonrpc-http, jsonrpc, jsonrpc-tcp-length-check ,分別對應(yīng)于 HTTP 協(xié)議和 TCP 協(xié)議下的兩種協(xié)議,默認值為 jsonrpc-http,這里的值對應(yīng)在 Hyperf\Rpc\ProtocolManager 里面注冊的協(xié)議的 key,它們本質(zhì)上都是 JSON RPC 協(xié)議,區(qū)別在于數(shù)據(jù)格式化、數(shù)據(jù)打包、數(shù)據(jù)傳輸器等不同;
  3. server 屬性為綁定該服務(wù)類發(fā)布所要承載的 Server,默認值為 jsonrpc-http,該屬性對應(yīng) config/autoload/server.php 文件內(nèi) servers 下所對應(yīng)的 name;
  4. publishTo 屬性為定義該服務(wù)所要發(fā)布的服務(wù)中心,目前僅支持 consul、nacos 或為空,我們這里先不做設(shè)置,留空

到這里我們就構(gòu)建好一個基本的服務(wù)提供者了。

postman測試

下面我們測試下這兩個接口是否正常。執(zhí)行命令 php bin/hyperf.php start 啟動服務(wù),利用postman發(fā)送請求。

請求地址:http://127.0.0.1:9600
請求方法:POST
請求參數(shù)
{
    "jsonrpc": "2.0",
    "method": "/user/createUser",
    "params": {
        "name": "zhangsan",
        "gender": 3
    },
    "id": "61025bc35e07d",
    "context": []
}
header頭
Content-Type: application/json
響應(yīng)結(jié)果
{
    "jsonrpc": "2.0",
    "id": "61025bc35e07d",
    "result": "success",
    "context": []
}
image

看下數(shù)據(jù)表

image

created_at 和 update_at 這兩個字段被自動填充。

再利用 postman訪問 /user/getUserInfo 方獲試試。

請求地址:http://127.0.0.1:9600
請求方法:POST
請求參數(shù)
{
    "jsonrpc": "2.0",
    "method": "/user/getUserInfo",
    "params": {
        "id": 1
    },
    "id": "61025bc35e07d",
    "context": []
}
header頭
Content-Type: application/json
響應(yīng)結(jié)果
{
    "jsonrpc": "2.0",
    "id": "61025bc35e07d",
    "result": {
        "id": 1,
        "name": "zhangsan",
        "gender": 3,
        "created_at": "1630101991",
        "updated_at": "1630101991"
    },
    "context": []
}

到這里,我們的服務(wù)提供者基本上就構(gòu)建好了,有同學可能看其他文章介紹還有consul的內(nèi)容,我們后續(xù)還會介紹更多內(nèi)容,稍安勿躁。

下一節(jié),我們繼續(xù)構(gòu)建服務(wù)消費者。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,048評論 6 542
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,414評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,169評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,722評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,465評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,823評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,813評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,000評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,554評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,295評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,513評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,035評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,722評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,125評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,430評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,237評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,482評論 2 379

推薦閱讀更多精彩內(nèi)容