• PHP微服务 hyperf+nacos使用


    PHP微服务 hyperf+nacos使用

    这里简单说下微服务,及架构方面东西
    1:微服务对php +fpm 模式意义不是很大,原因就是php+fpm 天生支持模块拆分,热更新,如果只是性能上的考虑,那php+fpm 还是比较耗cpu的,这样用微服务就不如单体+多库的方案,即一个项目拆分多个数据库,不同业务调用对应的库即可

    2:微服务可不可以直接调用http 接口?
    答案是可以的,都是自己公司内部的项目,并且项目不是说特别大,完全可以直接通过接口,这里注意几个点:
    a:保证这些接口通过内网调用,毕竟走外网时间是比较长的
    b:Http接口默认为同步调用,当需要同时调用多个服务时,考虑接口时间问题
    c:定义好规范,写好文档

    3:微服务的服务治理方式
    a:现在流行的都是统一服务治理中心(nacos/zookeeper)及 统一配置管理服务;
    优点就是: 统一管理,动态增减,及时上下线
    缺点是: 多个服务集中到了一起,容易形成瓶颈压力,多一层服务增加了系统的复杂性,在性能测试时需要考虑服务中心的压力
    b:服务自治模式,即每个服务提供统一的对外域名,由服务内部自己负载均衡实现减压,这样可以省去服务治理这一层,也不需要服务一直ping 治理中心;
    缺点就是新增服务得手动添加到负载均衡器里

    这里主要记录使用统一治理中心(nacos) 跟hyerf 搭建微服务的过程及注意点

    nacos 安装

    官网链接:https://nacos.io/zh-cn/docs/quick-start.html
    建议 直接下载nacos编译包解压后,开箱即用,这里注意配置,官方建议最低 2c 4g 太低可能导致启动失败

    unzip nacos-server-$version.zip 或者 tar -xvf nacos-server-$version.tar.gz
      cd nacos/bin
    
    • 1
    • 2

    启动建议先用单机模式

    启动命令(standalone代表着单机模式运行,非集群模式):
    
    sh startup.sh -m standalone
    
    • 1
    • 2
    • 3

    管理后台连接,默认账号 nacos 密码nacos
    http://host:8848/nacos/
    在这里插入图片描述

    注意端口是否有放开,生产环境建议端口白名单方式,因为更新删除服务是不需要账号密码的,外网很容易被人攻击

    PS:nacos 服务默认会健康检测,30s内没有心跳会默认删除,所以自己后台创建的 可能过一会就不见了,不要大惊小怪,还有通过api服务,创建要注意对应的命名空间,命名空间一定要在服务端先创建好,不然直接添加是不会在后端显示的,不熟悉的以为是bug

    Hyperf 使用(下面流程都是参照官方文档,这里说明下注意点)

    官网:https://hyperf.wiki/2.2

    一:根据文档安装好 swoole,跟Hyperf框架

    二:配置rpc 个服务 主要下面2个文档里
    1:https://hyperf.wiki/2.2/#/zh-cn/json-rpc
    2:https://hyperf.wiki/2.2/#/zh-cn/service-register

    这里主要说下注意的
    1:rpc 服务注解需要加上publishTo=“nacos” 才会同步到到nacos

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    2:配置config/autoload/services.php 的 namespace_id 需要提前在nacos 后台新增命名空间,获取对应的id,随便填写一个链接上nacos 也不会在nacos后台显示的

    3:作为消费者端使用nacos的话 在config/autoload/services.php 也是要配置服务驱动相关配置drivers (服务提供端可以不配置consumers),不然获取不到服务
    配置如下

    return [
        'enable' => [
            // 开启服务发现
            'discovery' => true,
            // 开启服务注册
            'register' => true,
        ],
        // 服务消费者相关配置
        //服务消费者
        'consumers' => [
            [
                // 对应消费者类的 $serviceName
                'name' => 'CaculatorService',
                // 这个消费者要从哪个服务中心获取节点信息,如不配置则不会从服务中心获取节点信息
                'registry' => [
                    'protocol' => 'nacos',
                    'address' => 'http://127.0.0.1:8848',
                ],
                // 如果没有指定上面的 registry 配置,即为直接对指定的节点进行消费,通过下面的 nodes 参数来配置服务提供者的节点信息
    //            'nodes' => [
    //                ['host' => '127.0.0.1', 'port' => 9513],
    //            ],
            ],
            [
                // 对应消费者类的 $serviceName
                'name' => 'DefaultService',
                // 这个消费者要从哪个服务中心获取节点信息,如不配置则不会从服务中心获取节点信息
                'registry' => [
                    'protocol' => 'nacos',
                    'address' => 'http://127.0.0.1:8848',
                ],
                // 如果没有指定上面的 registry 配置,即为直接对指定的节点进行消费,通过下面的 nodes 参数来配置服务提供者的节点信息
    //            'nodes' => [
    //                ['host' => '127.0.0.1', 'port' => 9513],
    //            ],
            ]
        ],
        // 服务提供者相关配置
        'providers' => [],
        // 服务驱动相关配置
        'drivers' => [
    //        'consul' => [
    //
    //        ],
            'nacos' => [
                // nacos server url like https://nacos.hyperf.io, Priority is higher than host:port
                // 'url' => '',
                // The nacos host info
                'host' => '127.0.0.1',
                'port' => 8848,
                // The nacos account info
                'username' => 'nacos',//可以不用配置
                'password' => '',//似乎可以不用密码
                'guzzle' => [
                    'config' => null,
                ],
                'group_name' => 'api',
                'namespace_id' => '950fdb39-edeb-4978-8ab6-3cf742732449',//这个要从nacos 后台获取
                'heartbeat' => 5,
                'ephemeral' => false, // 是否注册临时实例
            ],
        ],
    ];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    链接成功后
    在这里插入图片描述
    使用&优化:
    按照官方的使用方式是
    服务提供者Service写好对应类 通过注解 RpcService 对外提供服务
    服务消费者Consumer 需要写对应的类跟方法,之后才能调用
    这里就会有个问题,如果一个服务被很多项目调用,那提供者每添加一个服务 其他的消费者都要对应添加一个服务类或者修改对应的方法,这个对消费者非常不友好,服务多了需要浪费大量的时间互相同步

    简单优化
    消费端提供默认消费者 DefaultConsumer ,生成唯一get 方法 通过传入方法名跟参数调用对应的服务,这样服务端新增一个服务时 消费者端就不在需要写对应的消费类,但这里要求服务接收的参数就只有一个数组,通过数组约定里面的参数(这里还是要生成对应的消费端类继承DefaultConsumer,将$serviceName 默认好,Hyperf 通过容器绑定了对象,初始化就会获取此属性,没法更改,如果自己new DefaultConsumer 会造成内存泄露,随着访问量上升cpu 跟内存很快就爆满…)
    代码如下
    DefaultConsumer

    __request($method, ['pms'=>$parms]);
        }
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    CalculatorServiceConsumer

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    测试

    消费者代码

    get(CalculatorServiceConsumer::class);
             $d= $cus->get("add",['a'=>1,'b'=>2]);
            return [
                '本机ip' => get_server_ip(),
                'message' => "微服务调用结果=$d",
            ];
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    服务提供者代码

结果
在这里插入图片描述

注册中心下线服务后,再调用就不可用了
在这里插入图片描述
在这里插入图片描述

  • 相关阅读:
    【SIP&MRCP】freeswitch中的transfer和bridge有什么区别
    Ubuntu20.24安装记录——安装VM-Tools
    直击产业落地 | 飞桨重磅推出业界首个模型选型工具
    Jmeter(十五):jmeter场景的运行方式详解
    【Metaverse系列一】元宇宙的奥秘
    做好性能测试计划的4个步骤!全都是精华!【建议收藏】
    基于Java的师生健康体检管理系统设计与实现(源码+lw+部署文档+讲解等)
    51单片机控制智能家居监控系统设计仿真
    时间管理的本质,是少做事情
    【Vue实例对象】五分钟学会配置对象的配置选项
  • 原文地址:https://blog.csdn.net/lqb3732842/article/details/126545495