golang roadrunner中文文档(四)app服务器
2021年6月8日13:18:46
golang roadrunner中文文档(一)基础介绍
golang roadrunner中文文档(二)PHP Workers
golang roadrunner中文文档(三)HTTPS 和 HTTP/2
golang roadrunner中文文档(四)app服务器
golang roadrunner中文文档(五)集成到其他服务 docker
服务器命令
RoadRunner 应用程序可以通过从 PHP 应用程序的根调用一个简单的命令来启动。
$ rr serve
您还可以使用自定义位置的配置启动 RoadRunner:
$ rr serve -c ./app/.rr.yaml
重新加载所有 RoadRunner 服务:
$ rr reset
您可以将此命令附加为 IDE 中的文件观察器。
仅重置特定插件:
$ rr reset http
运行 golang pprof 服务器(调试模式):
$ rr serve -d -c .rr.yaml
以交互模式查看所有活动工作人员的状态。
$ rr workers -i
Workers of [http]: +---------+-----------+---------+---------+-----------------+ | PID | STATUS | EXECS | MEMORY | CREATED | +---------+-----------+---------+---------+-----------------+ | 9440 | ready | 42,320 | 31 MB | 22 days ago | | 9447 | ready | 42,329 | 31 MB | 22 days ago | | 9454 | ready | 42,306 | 31 MB | 22 days ago | | 9461 | ready | 42,316 | 31 MB | 22 days ago | +---------+-----------+---------+---------+-----------------+
日志记录
RoadRunner 提供了单独控制每个插件的日志的能力。
全局配置
要全局配置日志记录,请使用logs
config 部分:
logs:
mode: production
output: stderr
使用开发模式。它启用开发模式(使 DPanicLevel 日志恐慌),使用控制台编码器,写入标准错误,并禁用采样。堆栈跟踪会自动包含在 WarnLevel 及更高级别的日志中。
logs:
mode: development
输出到单独的文件:
logs:
mode: production
output: file.log
要使用控制台友好输出:
logs:
encoding: console # default value
要抑制特定日志级别下的消息:
logs:
encoding: console # default value
level: info
频道
此外,您可以使用channels
部分单独配置每个插件日志消息:
logs:
encoding: console # default value
level: info
channels:
server.mode: none # disable server logging. Also `off` can be used.
http:
mode: production
output: http.log
概括:
- 级别:
panic
、error
、warn
、info
、debug
。默认值:debug
。 - 编码:
console
,json
. 默认值:console
。 - 模式:
production
,development
,raw
. 默认值:development
。 - 输出:
file.log
或stderr
,stdout
。默认stderr
. - 错误输出:
err_file.log
或stderr
,stdout
。默认stderr
.
随意注册您自己的ZapLogger扩展。
自动重载
RoadRunner 能够自动检测 PHP 文件更改并重新加载连接的服务。这种方法使您无需max_jobs: 1
手动或手动重置服务器即可开发应用程序。
配置
要为 http 服务启用重新加载:
reload:
# sync interval
interval: 1s
# global patterns to sync
patterns: [ ".php" ]
# list of included for sync services
services:
http:
# recursive search for file patterns to add
recursive: true
# ignored folders
ignore: [ "vendor" ]
# service specific file pattens to sync
patterns: [ ".php", ".go", ".md" ]
# directories to sync. If recursive is set to true,
# recursive sync will be applied only to the directories in `dirs` section
dirs: [ "." ]
性能
该reload
组件会影响应用服务器的性能。确保仅在开发模式下使用它。将来我们计划重写此插件以使用通知事件的本机操作系统功能。
生产用途
在生产环境中运行 RoadRunner 时,必须承认多个提示和建议。
状态和记忆
状态和内存不在不同的工作实例之间共享,而是为单个工作实例共享。由于单个工作人员通常处理多个请求,因此您应该小心:
- 确保关闭所有描述符(尤其是在出现致命异常的情况下)。
- [可选]
gc_collect_cycles
如果您想保持低内存,请考虑在每次执行后调用(这会稍微减慢您的应用程序的速度)。 - 观察内存泄漏 - 您必须对使用的组件更加挑剔。如果出现内存泄漏,Worker 将被重新启动,但通过正确设计应用程序来完全避免这个问题应该不难。
- 避免状态污染(即内存中的全局变量或用户数据缓存)。
- 数据库连接和任何管道/套接字都是潜在的故障点。处理它的简单方法是在每次迭代后关闭所有连接。请注意,它不是性能最高的解决方案。
配置
- 确保不要在 RPC 服务中监听 0.0.0.0(除非在 Docker 中)。
- 使用管道连接到一个工人以获得更高的性能(Unix 套接字只是慢一点)。
- 将您的泳池时间调整为您喜欢的值。
- workers = 系统中的 CPU 线程数,除非您的应用程序受 IO 限制,否则请试探性地选择该数量。
max_jobs
如果您在一段时间内遇到任何应用程序稳定性问题,请考虑为您的员工使用。- RoadRunner 使用 Keep-Alive 连接的性能提高 40%。
- 将内存限制设置为至少 10-20% 以下
max_memory_usage
。 - 由于 RoadRunner 工作人员从 cli 运行,您需要通过
opcache.enable_cli=1
. - 在云环境中运行 rr 时,请确保使用健康检查端点。
- 使用
user
配置中的选项从基于 Linux 的系统上的特定用户启动工作进程。
在 Linux 上将 RR 服务器作为守护进程运行
在 RR 存储库中,您可以找到 rr.server systemd 单元文件。该文件的结构如下:
[Unit]
Description=High-performance PHP application server
[Service]
Type=simple
ExecStart=/usr/local/bin/roadrunner serve -c <path/to/.rr.yaml>
Restart=always
RestartSec=30
[Install]
WantedBy=default.target
用户应该做的唯一一件事就是ExecStart
用您自己的选项更新选项。为此,请设置正确的roadrunner
二进制路径、所需标志和 .rr.yaml 文件的路径。通常,此类用户单元文件位于.config/systemd/user/
. 对于 RR,它可能是.config/systemd/user/rr.service
. 要启用它,请使用以下命令:systemctl enable --user rr.service
和systemctl start rr.service
. 就是这样。现在 roadrunner 应该在你的服务器上作为守护进程运行。
此外,您可以在此处找到有关 systemd 单元文件的更多信息:链接。
应用指标
RoadRunner 服务器包括一个基于Prometheus的嵌入式指标服务器。
启用指标
要启用指标添加metrics
部分到您的配置:
metrics:
address: localhost:2112
完成后,您可以使用http://localhost:2112/metrics
url访问 Prometheus 指标。
确保安装指标扩展:
$ composer require spiral/roadrunner-metrics
应用指标
您还可以使用到服务器的 RPC 连接发布特定于应用程序的指标。首先,您必须在配置文件中注册一个指标:
metrics:
address: localhost:2112
collect:
app_metric_counter:
type: counter
help: "Application counter."
从应用程序发送指标:
$metrics = new RoadRunner\Metrics\Metrics(
Goridge\RPC\RPC::create(RoadRunner\Environment::fromGlobals()->getRPCAddress())
);
$metrics->add('app_metric_counter', 1);
支持的类型:仪表、计数器、汇总、直方图。
标记指标
您可以使用标记(标签)指标对值进行分组:
metrics:
address: localhost:2112
collect:
app_type_duration:
type: histogram
help: "Application counter."
labels: ["type"]
您应该在推送指标时为标签指定值:
$metrics = new RoadRunner\Metrics\Metrics(
Goridge\RPC\RPC::create(RoadRunner\Environment::fromGlobals()->getRPCAddress())
);
$metrics->add('app_type_duration', 0.5, ['some-type']);
声明指标
您可以从 PHP 应用程序本身声明指标:
$metrics->declare(
'test',
RoadRunner\Metrics\Collector::counter()->withHelp('Test counter')
);
健康端点
RoadRunner 服务器包含一个健康检查端点,用于返回工作人员的健康状况。
启用健康
要启用运行状况检查端点,请status
在您的配置中添加一个部分:
status:
address: localhost:2114
要访问修复检查,请使用以下 URL:
http://localhost:2114/health?plugin=http
您可以使用健康检查检查一个或多个插件。目前,仅支持 HTTP。
启用后,运行状况检查端点将响应以下内容:
HTTP 200
如果至少有一名工作人员准备好处理请求。HTTP 500
如果没有工作人员准备好为请求提供服务。
用例
运行状况检查端点可用于以下用途:
搭建服务器
RoadRunner 使用 Endure 来管理依赖项,这允许您为每个单独的项目调整和扩展应用程序功能。
安装 Golang
要构建应用服务器,您需要安装Golang 1.16+。
创建 main.go
package main
import (
"log"
endure "github.com/spiral/endure/pkg/container"
// plugins
"github.com/spiral/roadrunner-binary/v2/cli"
httpPlugin "github.com/spiral/roadrunner/v2/plugins/http"
"github.com/spiral/roadrunner/v2/plugins/informer"
"github.com/spiral/roadrunner/v2/plugins/kv/boltdb"
"github.com/spiral/roadrunner/v2/plugins/kv/memcached"
"github.com/spiral/roadrunner/v2/plugins/kv/memory"
"github.com/spiral/roadrunner/v2/plugins/logger"
"github.com/spiral/roadrunner/v2/plugins/metrics"
"github.com/spiral/roadrunner/v2/plugins/redis"
"github.com/spiral/roadrunner/v2/plugins/reload"
"github.com/spiral/roadrunner/v2/plugins/resetter"
"github.com/spiral/roadrunner/v2/plugins/rpc"
"github.com/spiral/roadrunner/v2/plugins/server"
"github.com/temporalio/roadrunner-temporal/activity"
temporalClient "github.com/temporalio/roadrunner-temporal/client"
"github.com/temporalio/roadrunner-temporal/workflow"
)
func main() {
var err error
cli.Container, err = endure.NewContainer(nil, endure.SetLogLevel(endure.ErrorLevel), endure.RetryOnFail(false))
if err != nil {
log.Fatal(err)
}
err = cli.Container.RegisterAll(
// logger plugin
&logger.ZapLogger{},
// metrics plugin
&metrics.Plugin{},
// http server plugin
&httpPlugin.Plugin{},
// reload plugin
&reload.Plugin{},
// informer plugin (./rr workers, ./rr workers -i)
&informer.Plugin{},
// resetter plugin (./rr reset)
&resetter.Plugin{},
// rpc plugin (workers, reset)
&rpc.Plugin{},
// server plugin (NewWorker, NewWorkerPool)
&server.Plugin{},
// temporal plugins
&temporalClient.Plugin{},
&activity.Plugin{},
&workflow.Plugin{},
)
if err != nil {
log.Fatal(err)
}
cli.Execute()
}
您现在无需构建go run main.go serve
.
了解如何创建http 中间件以拦截 HTTP 流。
RPC 集成
您可以使用共享 RPC 总线从 PHP 工作人员连接到 RoadRunner 服务器。为此,您必须创建一个RPC
类的实例,并将其配置为使用.rr
文件中指定的地址。
要求
要在 RPC 模式下从 PHP 应用程序连接到 RoadRunner,您需要:
- ext-sockets
- ext-json
配置
要更改默认的 RPC 端口 (localhost:6001),请使用:
rpc:
listen: tcp://127.0.0.1:6001
$rpc = Goridge\RPC\RPC::create(RoadRunner\Environment::fromGlobals()->getRPCAddress());
您可以立即使用此 RPC 调用嵌入式 RPC 服务,例如 HTTP:
var_dump($rpc->call('informer.Workers', 'http'));
您可以在本节中阅读如何创建自己的服务和 RPC 方法。
编写插件
RoadRunner 使用 Endure 容器来管理依赖项。这种方法类似于具有自动方法注入的 PHP 容器实现。您可以创建自己的插件、事件侦听器、中间件等。
要定义您的插件,请使用公共Init
方法创建一个带有错误返回值的结构(您可以spiral/errors
用作error
包):
package custom
const PluginName = "custom"
type Plugin struct{}
func (s *Plugin) Init() error {
return nil
}
您可以通过创建自定义版本的main.go
文件并构建它来注册您的插件。
依赖关系
您可以通过在您的Init
方法中请求依赖项来访问其他 RoadRunner 插件:
package custom
import (
"github.com/spiral/roadrunner/v2/plugins/http"
"github.com/spiral/roadrunner/v2/plugins/rpc"
)
type Service struct {
}
func (s *Service) Init(r *rpc.Plugin, rr *http.Plugin) error {
return nil
}
确保请求依赖项作为指针。
配置
在大多数情况下,您的服务需要一组配置值。RoadRunner 可以使用config
插件(通过接口)自动填充和验证您的配置结构:
配置示例:
custom:
address: tcp://localhost:8888
插入:
package custom
import (
"github.com/spiral/roadrunner/v2/plugins/config"
"github.com/spiral/roadrunner/v2/plugins/http"
"github.com/spiral/roadrunner/v2/plugins/rpc"
"github.com/spiral/errors"
)
const PluginName = "custom"
type Config struct{
Address string `mapstructure:"address"`
}
type Plugin struct {
cfg *Config
}
// You can also initialize some defaults values for config keys
func (cfg *Config) InitDefaults() {
if cfg.Address == "" {
cfg.Address = "tcp://localhost:8088"
}
}
func (s *Plugin) Init(r *rpc.Plugin, h *http.Plugin, cfg config.Configurer) error {
const op = errors.Op("custom_plugin_init") // error operation name
if !cfg.Has(PluginName) {
return errors.E(op, errors.Disabled)
}
// unmarshall
err := cfg.UnmarshalKey(PluginName, &s.cfg)
if err != nil {
// Error will stop execution
return errors.E(op, err)
}
// Init defaults
s.cfg.InitDefaults()
return nil
}
errors.Disabled
是一种特殊的错误,它指示 Endure 禁用此插件和此根的所有依赖项。如果至少插件保持活动状态,RR2 将在此错误类型后继续工作。
服务
在您的结构中创建Serve
和Stop
方法,让 RoadRunner 启动和停止您的服务。
type Plugin struct {}
func (s *Plugin) Serve() chan error {
const op = errors.Op("custom_plugin_serve")
errCh := make(chan error, 1)
err := s.DoSomeWork()
err != nil {
errCh <- errors.E(op, err)
return errCh
}
return nil
}
func (s *Plugin) Stop() error {
return s.stopServing()
}
func (s *Plugin) DoSomeWork() error {
return nil
}
Serve
方法是线程安全的。它运行在由Endure
容器管理的单独 goroutine中。一个注意事项是,您应该在调用Stop
容器时取消阻止它。否则,超时后服务将被杀死(可在 Endure 中设置)。
在运行时收集依赖项
RR2 提供了一种通过Collects
接口在运行时收集依赖项的方法。这对于中间件或具有附加功能的扩展插件非常有用,而无需更改它。
让我们创建一个 HTTP 中间件:
步骤(以实际http
插件和Middleware
界面为例):
-
声明一个必需的接口
// Middleware interface type Middleware interface { Middleware(f http.Handler) http.HandlerFunc }
-
实现方法,它应该有一个参数名称(
endure.Named
接口)和Middleware
(步骤 1)。
// Collects collecting http middlewares
func (s *Plugin) AddMiddleware(name endure.Named, m Middleware) {
s.mdwr[name.Name()] = m
}
Collects
为所需结构实现持久接口并返回在步骤 2 方法上实现的。
// Collects collecting http middlewares
func (s *Plugin) Collects() []interface{} {
return []interface{}{
s.AddMiddleware,
}
}
Endure 将自动检查注册的结构是否实现了该AddMiddleware
方法的所有参数(如果参数是结构,则会找到一个结构)。在我们的例子中,一个结构应该实现endure.Named
接口(它返回插件的用户友好名称)和Middleware
接口。
RPC 方法
您还可以使用 EndureCollects
接口为 PHP 工作人员公开一组 RPC 方法。Endure 将自动获取结构并在PluginName
名称下公开 RPC 方法。
用 RPC 方法扩展你的插件,插件根本不会改变。唯一要做的一件事是使用 RPC 方法创建一个文件(我们称之为rpc.go
),并在此处公开插件的所有 RPC 方法,而无需更改插件本身:
基于informer
插件的示例:
我假设我们创建了一个文件rpc.go
。下一步是创建一个结构:
- 创建一个结构:(记录器是可选的)
package custom
type rpc struct {
srv *Plugin
log logger.Logger
}
- 创建一个要公开的方法:
func (s *rpc) Hello(input string, output *string) error {
*output = input
return nil
}
- 使用
Collects
接口向 Endure 公开 RPC 服务:
// CollectTarget resettable service.
func (p *Plugin) CollectTarget(name endure.Named, r Informer) error {
p.registry[name.Name()] = r
return nil
}
// Collects declares services to be collected.
func (p *Plugin) Collects() []interface{} {
return []interface{}{
p.CollectTarget,
}
}
// Name of the service.
func (p *Plugin) Name() string {
return PluginName
}
// RPCService returns associated rpc service.
func (p *Plugin) RPC() interface{} {
return &rpc{srv: p, log: p.log}
}
让我们来看看这些方法:
CollectTarget
:告诉 Endure,我们要收集所有实现endure.Named
和Informer
接口的插件。Collects
: 忍接口实现。Name
:endure.Named
返回用户友好插件名称的接口实现。RPC
: RPC plugin 收集所有实现RPC
接口和endure.Named
. RPC 接口不接受任何参数,但返回接口(插件)。
要使用RPC
实例在 PHP 中使用它:
var_dump($rpc->call('custom.Hello', 'world'));
服务插件
服务插件是在 RR 中引入的v2.0.5
。
主要能力
- 执行 PHP 代码、二进制文件、bash/powershell 脚本。
- 指定时间后重新启动。
- 控制特定命令的执行时间。
- 提供统计到
Informer
约插件%CPU
,PID
和使用RSS memory
。
配置
service:
some_service_1:
command: "php tests/plugins/service/test_files/loop.php"
process_num: 10
exec_timeout: 0
remain_after_exit: true
restart_sec: 1
some_service_2:
command: "tests/plugins/service/test_files/test_binary"
process_num: 1
remain_after_exit: true
restart_delay: 1s
exec_timeout: 0
描述:
-
服务插件支持任意数量的嵌套命令。
-
command
- 要执行的命令。这里对命令没有限制。这里可能是二进制文件、PHP 文件、脚本等。 -
process_num
- 默认值:1,命令触发的进程数。 -
exec_timeout
- 默认值:0(无限制),允许进程运行的最大时间。 -
remain_after_exit
- 默认值:假。退出后保留进程。例如,如果你需要每 10 秒重启一次进程exec_timeout
应该是 10s,并且remain_after_exit
应该设置为 true。注意:如果您从外部终止该进程并且如果remain_after_exit
为 true,则该进程将重新启动。 -
restart_sec
- 默认值:30 秒。进程停止和重新启动之间的延迟。
QQ二群 166427999
博客文件如果不能下载请进群下载
如果公司项目有技术瓶颈问题,请联系↓↓
如果需要定制系统开发服务,请联系↓↓
技术服务QQ: 903464207