- 后端
- 微服务
【免费下载链接】hyperf
🚀 A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease.
本篇技术指南以 Hyperf 官方配置组件hyperf/config为核心,系统讲解基于 hyperf/hyperf-skeleton 骨架项目创建的 Hyperf 应用中,配置文件的组织结构、加载机制、取值方式(Config 对象 /#[Value]注解 /config()函数)、环境变量解析方案,以及组件配置发布机制与外部化配置中心接入。读完本篇,你将掌握 Hyperf 应用"配置从文件到容器"的完整链路,能够在实际项目中正确组织、读取、覆盖与发布配置。
安装
hyperf/config是 Hyperf 框架默认的配置组件,可通过 Composer 单独安装:
composer require hyperf/config该组件是面向Hyperf\Contract\ConfigInterface接口实现的官方默认实现。组件内的 ConfigProvider 会通过其dependencies声明将Hyperf\Config\Config对象绑定到ConfigInterface接口上,同时注册ValueAspect(AOP 切面)与RegisterPropertyHandlerListener(属性注入监听器)以支撑#[Value]注解的自动注入能力。
配置文件结构
当您使用hyperf/hyperf-skeleton项目创建 Hyperf 应用时,所有配置文件均位于项目根目录的config文件夹内,每个选项都带有说明,您可以随时查看并熟悉可用的选项。
以下结构仅为 Hyperf-Skeleton 在默认配置下的情况,实际文件构成会因您依赖或使用的组件差异而有所不同:
config ├── autoload // 此文件夹内的配置文件会被配置组件自动加载,并以文件夹内的文件名作为第一个键(Key) │ ├── amqp.php // 用于管理 AMQP 组件 │ ├── annotations.php // 用于管理注解(Annotation) │ ├── apollo.php // 用于管理基于 Apollo 实现的配置中心 │ ├── aspects.php // 用于管理 AOP 切面 │ ├── async_queue.php // 用于管理基于 Redis 实现的简易队列服务 │ ├── cache.php // 用于管理缓存组件 │ ├── commands.php // 用于管理自定义命令 │ ├── consul.php // 用于管理 Consul 客户端 │ ├── databases.php // 用于管理数据库客户端 │ ├── dependencies.php // 用于管理 DI 的依赖关系和类对应关系 │ ├── devtool.php // 用于管理开发者工具 │ ├── exceptions.php // 用于管理异常处理器 │ ├── listeners.php // 用于管理事件监听者 │ ├── logger.php // 用于管理日志 │ ├── middlewares.php // 用于管理中间件 │ ├── opentracing.php // 用于管理调用链追踪 │ ├── processes.php // 用于管理自定义进程 │ ├── redis.php // 用于管理 Redis 客户端 │ └── server.php // 用于管理 Server 服务 ├── config.php // 用于管理用户或框架的配置,相对独立的配置亦可放于 autoload 文件夹内 ├── container.php // 负责容器的初始化,作为一个配置文件运行并最终返回一个 Psr\Container\ContainerInterface 对象 └── routes.php // 用于管理路由server.php 配置说明
config/autoload/server.php用于管理 Server 服务。以下为 Hyperf-Skeleton 中该文件提供的默认settings:
<?php declare(strict_types=1); use Hyperf\Server\Server; use Hyperf\Server\Event; return [ // 这里省略了该文件的其它配置 'settings' => [ 'enable_coroutine' => true, // 开启内置协程 'worker_num' => swoole_cpu_num(), // 设置启动的 Worker 进程数 'pid_file' => BASE_PATH . '/runtime/hyperf.pid', // master 进程的 PID 'open_tcp_nodelay' => true, // TCP 连接发送数据时关闭 Nagle 合并算法,立即发往客户端连接 'max_coroutine' => 100000, // 设置当前工作进程最大协程数量 'open_http2_protocol' => true, // 启用 HTTP2 协议解析 'max_request' => 100000, // 设置 worker 进程的最大任务数 'socket_buffer_size' => 2 * 1024 * 1024, // 配置客户端连接的缓冲区长度 ], ];其中settings选项可以直接使用Swoole Server提供的各项设置(更多选项可参考 Swoole 官方 Server 设置文档)。如需要守护进程化,可在settings中增加'daemonize' => true,之后执行php bin/hyperf.php start,程序将转入后台作为守护进程运行。
单独的 Server 配置需要添加在对应servers的settings中。例如为jsonrpc协议的 TCP Server 启用 EOF 自动分包并设置 EOF 字符串:
<?php use Hyperf\Server\Server; use Hyperf\Server\Event; return [ // 这里省略了该文件的其它配置 'servers' => [ [ 'name' => 'jsonrpc', 'type' => Server::SERVER_BASE, 'host' => '0.0.0.0', 'port' => 9503, 'sock_type' => SWOOLE_SOCK_TCP, 'callbacks' => [ Event::ON_RECEIVE => [\Hyperf\JsonRpc\TcpServer::class, 'onReceive'], ], 'settings' => [ 'open_eof_split' => true, // 启用 EOF 自动分包 'package_eof' => "\r\n", // 设置 EOF 字符串 ], ], ], ];config.php与autoload文件夹内配置文件的关系
config.php与autoload文件夹内的配置文件在服务启动时都会被扫描并注入到Hyperf\Contract\ConfigInterface对应的对象中。配置的结构是一个键值对的大数组,两种配置形式的区别在于:
autoload内配置文件的**文件名会作为第一层键(Key)**存在;config.php内的以您自定义的键作为第一层。
我们通过下面的例子来演示。假设存在一个config/autoload/client.php文件,文件内容如下:
return [ 'request' => [ 'timeout' => 10, ], ];那么我们想要得到timeout的值,对应的键(Key)为client.request.timeout。
如果要以相同的键获得同样的结果,但配置写在config/config.php文件内,那么文件内容应如下:
return [ 'client' => [ 'request' => [ 'timeout' => 10, ], ], ];源码视角:配置是如何被扫描与合并的
这一"文件名即键"的行为由 ConfigFactory 实现,它是在Config对象实例化时完成的加载流程:
public function __invoke(ContainerInterface $container) { $configPath = BASE_PATH . '/config'; $config = $this->readConfig($configPath . '/config.php'); $autoloadConfig = $this->readPaths([$configPath . '/autoload']); $merged = array_merge_recursive(ProviderConfig::load(), $config, ...$autoloadConfig); return new Config($merged); }关键点如下:
- 读取
config.php:通过require加载并校验返回值为数组,非数组时按空数组处理; - 扫描
autoload目录:使用Symfony\Component\Finder\Finder递归扫描目录下所有*.php文件,并将相对路径中的目录层级与文件名用.拼接为键,例如autoload/a/apple.php对应的键为a.apple,这正是"文件名作为第一层键"的底层来源。该行为在 ConfigFactoryTest 中有明确验证:测试断言autoload下的apple.php可通过config->get('apple')取到,而a/apple.php可通过config->get('a.apple')取到; - 合并顺序:
array_merge_recursive(ProviderConfig::load(), $config, ...$autoloadConfig),即依次合并组件ConfigProvider提供的默认配置(见 ProviderConfig,它通过 Composer 的extra.hyperf.config收集各组件提供者)、config.php内容、autoload目录下各文件内容。
使用 Hyperf Config 组件
设置配置值
只需在config/config.php与config/autoload/文件夹内放置配置,即可在服务启动时被扫描并注入到Hyperf\Contract\ConfigInterface对应的对象中。这一流程如上所述由Hyperf\Config\ConfigFactory在Config对象实例化时完成。
除了文件配置外,在运行期也可以通过 Config 对象 的set(string $key, mixed $value): void方法动态写入配置,其内部通过data_set()以.连接符定位并写入下级数组:
$config->set('client.request.timeout', 30);获取配置值
Config 组件提供了三种方式获取配置:通过Hyperf\Config\Config对象获取、通过#[Value]注解获取、通过config(string $key, $default)函数获取。
方式一:通过 Config 对象获取
这种方式要求您已经拿到Config对象的实例(默认对象为Hyperf\Config\Config),通常通过依赖注入获得。注入实例的细节可查阅 依赖注入 章节。
/** * @var \Hyperf\Contract\ConfigInterface */ // 通过 get(string $key, $default): mixed 方法获取 $key 所对应的配置, // $key 值可以通过 . 连接符定位到下级数组,$default 是当对应的值不存在时返回的默认值 $config->get($key, $default);从 Config 实现 可以看到,get()底层通过data_get()完成client.request.timeout这类点分键的逐级查找,未找到时返回$default。
方式二:通过#[Value]注解获取
这种方式要求注解应用的对象必须是由 hyperf/di 组件创建的(如Controller类一定由 DI 容器创建)。#[Value]内的字符串对应$config->get($key)中的$key参数,在创建该对象实例时,对应的配置会自动注入到定义的类属性中。
<?php use Hyperf\Config\Annotation\Value; class IndexController { #[Value(key: "config.key")] private $configValue; public function index() { return $this->configValue; } }从源码看,Value 注解 声明为#[Attribute(Attribute::TARGET_PROPERTY)],仅可作用于类属性,构造参数即为配置键;而 ValueAspect 作为一个 AOP 切面仅用于标记该类需要生成代理类,实际的属性注入由RegisterPropertyHandlerListener在 DI 容器创建实例时完成(该监听器同样在 ConfigProvider 中注册)。
方式三:通过config()函数获取
在任意位置都可以通过config(string $key, $default)函数获取对应配置,但这样的使用方式意味着您对hyperf/config与hyperf/support组件是强依赖的。
该函数的实现见 Functions.php:它从ApplicationContext中取出容器,再通过容器解析ConfigInterface并调用get()。若容器尚未初始化或容器中缺少ConfigInterface,将抛出RuntimeException。对应的行为测试见 ConfigTest。
$timeout = config('client.request.timeout', 5);判断配置是否存在
/** * @var \Hyperf\Contract\ConfigInterface */ // 通过 has(): bool 方法判断对应的 $key 值是否存在于配置中, // $key 值可以通过 . 连接符定位到下级数组 $config->has($key);其实现(Config.php)基于Arr::has()判断点分键是否真实存在。
环境变量
对于不同的运行环境使用不同的配置是常见需求。例如测试环境和生产环境的 Redis 配置不同,而生产环境的配置又不能提交到源代码版本管理系统中以免信息泄露。
Hyperf 通过利用 vlucas/phpdotenv 提供的环境变量解析功能,以及env()函数来获取环境变量的值,轻松解决这一需求。
.env文件的创建与安全
在新安装好的 Hyperf 应用中,根目录会包含一个.env.example文件。如果通过 Composer 安装 Hyperf,该文件会自动基于.env.example复制一份并命名为.env;否则需要您手动更改文件名。
您的.env文件不应提交到应用的源代码版本管理系统中:每个使用您的应用的开发人员/服务器可能需要不同的环境配置;此外,一旦入侵者获得源码仓库访问权,所有敏感数据都会被一览无余,将导致严重的安全问题。
.env文件中的所有变量均可被外部环境变量所覆盖(比如服务器级、系统级或 Docker 环境变量)。
环境变量类型
.env文件中的所有变量都会被解析为字符串类型,因此提供了一些保留值,允许您从env()函数中获取更多类型的变量:
| .env 值 | env() 值 |
|---|---|
| true | (bool) true |
| (true) | (bool) true |
| false | (bool) false |
| (false) | (bool) false |
| empty | (string) '' |
| (empty) | (string) '' |
| null | (null) null |
| (null) | (null) null |
上述类型转换逻辑在 support 组件的 env 函数 中逐条实现:getenv()取不到值时返回默认值;命中保留值(不区分大小写)时转换为对应的布尔、空字符串或null;以双引号包裹的值会被去除首尾引号后原样返回。
如果您需要使用包含空格或特殊字符的环境变量,可以通过将值括在双引号中来实现,例如:
APP_NAME="Hyperf Skeleton"读取环境变量
环境变量可以通过env()函数获取。在应用开发中,环境变量只应作为配置的一个值,通过环境变量的值来覆盖配置的值;对于应用层来说应只使用配置,而不是直接使用环境变量。下面是一个合理使用的例子:
// config/config.php return [ 'app_name' => env('APP_NAME', 'Hyperf Skeleton'), ];这样应用层始终通过config('app_name')读取配置,而具体取值由部署环境的APP_NAME环境变量(或其默认值'Hyperf Skeleton')决定。
发布组件配置
Hyperf 采用组件化设计。在向骨架项目添加一些组件后,通常需要为新添加的组件创建对应的配置文件以满足使用需求。Hyperf 为组件提供了组件配置发布机制:通过该机制,只需执行一个vendor:publish命令,即可将组件预设的配置文件模板发布到骨架项目中。
例如,我们希望添加一个hyperf/foo组件(该组件实际并不存在,仅为示例)及其对应的配置文件。在composer require hyperf/foo安装之后,可通过执行以下命令,将组件预设的配置文件发布到骨架项目的config/autoload文件夹内:
php bin/hyperf.php vendor:publish hyperf/foo具体要发布的内容由组件通过其ConfigProvider的publish字段定义提供。
从源码看,该命令由 devtool 组件的 VendorPublishCommand 实现,其关键行为包括:
- 通过参数
package指定要发布的组件包名,并通过Composer::getMergedExtra()读取该包composer.json中extra字段下的hyperf.config配置提供者; - 支持
--show选项列出该包所有可发布项,支持--id选项只发布指定的发布项,支持--force选项覆盖已存在的目标文件; - 每个发布项需包含
id、source(源路径)、destination(目标路径),发布时自动创建目标目录,源为目录时整目录复制,源为文件时单文件复制。
配置中心
Hyperf 为分布式系统提供外部化配置支持。英文文档默认提供由携程开源的项目 Apollo(由hyperf/config-apollo组件提供功能支持);从中文文档看,目前支持由携程开源的Apollo、阿里云 ACM 应用配置管理、ETCD、Nacos 以及 Zookeeper 作为配置中心,对应实现分别位于仓库的 config-apollo、config-aliyun-acm、config-etcd、config-nacos、config-zookeeper 等组件目录中。
关于配置中心的具体接入、拉取与监听配置更新的细节,请查阅 配置中心 章节。
小结
Hyperf 的配置体系围绕Hyperf\Contract\ConfigInterface展开:ConfigFactory在服务启动时将config/config.php、config/autoload/目录及组件ConfigProvider提供的配置合并为一个大数组注入Config对象;业务层可通过$config->get()/has()/set()、#[Value]注解或config()函数三种方式读写配置;env()函数与.env文件为多环境部署提供了安全、灵活的变量覆盖手段;vendor:publish命令则让组件配置模板可以一键落入骨架项目。理解这条链路,即可在 Hyperf 应用中游刃有余地组织与消费配置。
- 后端
- 微服务
【免费下载链接】hyperf
🚀 A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease.
相关推荐
Hyperf 配置组件完全指南:config 目录结构、配置读取方式与环境变量实战
Hyperf 配置组件完全指南:config 目录结构、配置读取方式与环境变量实战 本文是 Hyperf 框架配置体系的实战指南,围绕官方文档 docs/en/
后端Web框架微服务RPC框架异步编程Hyperf 配置体系完全指南:从 config 目录结构、Config 组件到环境变量与配置中心的深度实践
Hyperf 配置体系完全指南:从 config 目录结构、Config 组件到环境变量与配置中心的深度实践 Hyperf 采用组件化设计,其配置系统是整个框架
后端Web框架微服务RPC框架异步编程Boto3 配置完全指南:Config 对象、环境变量与 ~/.aws/config 配置文件详解
Boto3 配置完全指南:Config 对象、环境变量与 ~/.aws/config 配置文件详解 本篇技术指南围绕 Boto3(AWS SDK for Pyt
后端云原生
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考