zoukankan      html  css  js  c++  java
  • hyperf从零开始构建微服务(一)——构建服务提供者

    阅读目录

    上一篇文章我们了解了如何使用hyperf对项目进行垂直拆分,这是我们整个微服务模块的基础。

    hyperf支持JSON-RPC和gRPC,我们在分布式服务架构一文中介绍过什么是JSON-RPC以及JSON-RPC请求响应的案例(后来做的补充),后面我们会着重以JSON-RPC为例来解决整个微服务系统出现的各种问题。

    首先我们加以明确什么是服务。

    服务有两种角色,一种是 服务提供者(ServiceProvider),即为其它服务提供服务的服务,另一种是 服务消费者(ServiceConsumer),即依赖其它服务的服务,一个服务既可能是 服务提供者(ServiceProvider),同时又是 服务消费者(ServiceConsumer)。而两者直接可以通过 服务契约 来定义和约束接口的调用,在 Hyperf 里,可直接理解为就是一个 接口类(Interface),通常来说这个接口类会同时出现在提供者和消费者下。——摘自官网。

    简单的说,我们的项目模块将会被分为服务提供者模块和服务消费者模块。 服务提供者模块指的是提供各种服务的模块,它需要与数据库进行交互。 服务消费者模块指的是消费服务的模块。它需要远程访问服务提供者。

    本节课的源码已上传至github,https://github.com/bailangzhan/hyperf-rpc

    下面我们按照步骤,看看如何构建服务提供者。

    1、创建数据表

    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 '创建时间',
      `updated_at` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户基础表';
    

    2、构建服务提供者

    composer create-project hyperf/hyperf-skeleton shop_provider_user
    

    安装的时候会让我们选择默认的组件,除了时区和数据库外,其他一律选择“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 应用对外提供服务,所以需要安装 rpc server组件

    composer require hyperf/rpc-server
    

    5、修改server配置

    shop_provider_user 提供的是 jsonrpc服务,不需要提供http服务,所以屏蔽 http 服务配置,新加 jsonrpc-http 服务。

    hyperf支持 jsonrpc-http 协议、jsonrpc 协议以及jsonrpc-tcp-length-check 协议,我们后续都将以 jsonrpc-http为例。

    以下配置在 config/autoload/server.php 文件内,注意 jsonrpc-http服务配置的端口号是9600

    'servers' => [
    //        [
    //            'name' => 'http',
    //            'type' => Server::SERVER_HTTP,
    //            'host' => '0.0.0.0',
    //            'port' => 9501,
    //            'sock_type' => SWOOLE_SOCK_TCP,
    //            'callbacks' => [
    //                Event::ON_REQUEST => [HyperfHttpServerServer::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 => [HyperfJsonRpcHttpServer::class, 'onRequest'],
            ],
        ],
    ],
    

    6、配置数据库

    修改.env文件,修改 APP_NAME以及数据库配置

    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、编写基础代码

    7-1、编写model代码

    生成model并修改如下:

    php bin/hyperf.php gen:model User
    【app/Model/User.php】
    <?php
    declare (strict_types=1);
    namespace AppModel;
    use HyperfDbConnectionModelModel;
    /**
     */
    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 对外提供两个接口,一个用于创建用户,一个用于获取用户信息。

    【UserServiceInterface】
    <?php
    namespace AppJsonRpc;
    interface UserServiceInterface
    {
        public function createUser(string $name, int $gender);
        public function getUserInfo(int $id);
    }
    【UserService】
    <?php
    namespace AppJsonRpc;
    use AppModelUser;
    use HyperfRpcServerAnnotationRpcService;
    /**
     * @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 HyperfRpcServerAnnotationRpcService;

    @RpcService 共有 4 个参数,也就是 HyperfRpcServerAnnotationRpcService 的4个属性:

    1. name 属性为定义该服务的名称,注意不同的service不要用相同的名字,该名字唯一,Hyperf 会根据该属性生成对应的 ID 注册到服务中心去,后面我们会详细介绍,这里有个印象就好;
    2. protocol 属性为定义该服务暴露的协议,目前仅支持 jsonrpc-http, jsonrpc, jsonrpc-tcp-length-check ,分别对应于 HTTP 协议和 TCP 协议下的两种协议,默认值为 jsonrpc-http,这里的值对应在 HyperfRpcProtocolManager 里面注册的协议的 key,它们本质上都是 JSON RPC 协议,区别在于数据格式化、数据打包、数据传输器等不同;
    3. server 属性为绑定该服务类发布所要承载的 Server,默认值为 jsonrpc-http,该属性对应 config/autoload/server.php 文件内 servers 下所对应的 name;
    4. publishTo 属性为定义该服务所要发布的服务中心,目前仅支持 consul、nacos 或为空,我们这里先不做设置,留空

    到这里我们就构建好一个基本的服务提供者了。

    postman测试

    下面我们测试下这两个接口是否正常。执行命令 php bin/hyperf.php start 启动服务,利用postman发送请求。

    请求地址:http://127.0.0.1:9600
    请求方法:POST
    请求参数
    {
        "jsonrpc": "2.0",
        "method": "/user/createUser",
        "params": {
            "name": "zhangsan",
            "gender": 3
        },
        "id": "61025bc35e07d",
        "context": []
    }
    header头
    Content-Type: application/json
    响应结果
    {
        "jsonrpc": "2.0",
        "id": "61025bc35e07d",
        "result": "success",
        "context": []
    }
    

    看下数据表

    created_at 和 update_at 这两个字段被自动填充。

    再利用 postman访问 /user/getUserInfo 方获试试。

    请求地址:http://127.0.0.1:9600
    请求方法:POST
    请求参数
    {
        "jsonrpc": "2.0",
        "method": "/user/getUserInfo",
        "params": {
            "id": 1
        },
        "id": "61025bc35e07d",
        "context": []
    }
    header头
    Content-Type: application/json
    响应结果
    {
        "jsonrpc": "2.0",
        "id": "61025bc35e07d",
        "result": {
            "id": 1,
            "name": "zhangsan",
            "gender": 3,
            "created_at": "1630101991",
            "updated_at": "1630101991"
        },
        "context": []
    }
    

    到这里,我们的服务提供者基本上就构建好了,有同学可能看其他文章介绍还有consul的内容,我们后续还会介绍更多内容,稍安勿躁。

    下一节,我们继续构建服务消费者。

  • 相关阅读:
    界面控件DevExpress WPF入门 表达式编辑器功能
    Telerik UI for WPF全新版本——拥有Office2019高对比度主题
    DevExpress报表控件v21.2 全新的Visual Studio报表设计器
    报告生成器FastReport .NET入门指南 在Linux中启动应用程序
    文档控件DevExpress Office File API v21.2 自定义字体加载引擎
    UI组件库Kendo UI for Angular入门 如何开始使用图表功能
    WPF界面工具Telerik UI for WPF入门级教程 设置一个主题(二)
    DevExtreme初级入门教程(React篇) TypeScript支持
    报表开发利器FastReport .NET v2022.1 添加关键对象和属性
    python项目打包(一) setup.py、Python源代码项目结构
  • 原文地址:https://www.cnblogs.com/wwolf/p/15242642.html
Copyright © 2011-2022 走看看