当前位置: 首页 > news >正文

Hyperf 安装,使用,

安装,

一般开发都是windows,所以用虚拟机或docker

使用

启动

 php bin/hyperf.php start

在这里插入图片描述

如果出现端口被占用,下面的处理方法

  1. 查看9501端口那个进程在占用
 netstat -anp|grep 9501

在这里插入图片描述
2. kill掉

kill 18
  1. 然后再启动即可

热更新

Watcher 组件除了解决上述启动问题,还提供了文件修改后立马重启的功能。

安装

composer require hyperf/watcher --dev

发布配置

php bin/hyperf.php vendor:publish hyperf/watcher

发布配置后在目录config/autoload/下自动生成watcher.php文件

在这里插入图片描述
配置 默认值 备注

driverScanFileDriver默认定时扫描文件驱动
binPHP_BINARY用于启动服务的脚本
watch.dirapp, config监听目录
watch.file.env监听文件
watch.interval2000扫描间隔(毫秒)
ext.php, .env监听目录下的文件扩展名

启动

hyperf框架可以使用hyperf/watcher进行热更新操作,不用每次修改完代码都重启服务
注意:
使用php bin/hyperf.php server:watch这个命令后,php bin/hyperf.php start 这个命令将废弃

php bin/hyperf.php server:watch

路由

配置文件路由

<?php
use Hyperf\HttpServer\Router\Router;// 此处代码示例为每个示例都提供了三种不同的绑定定义方式,实际配置时仅可采用一种且仅定义一次相同的路由// 设置一个 GET 请求的路由,绑定访问地址 '/get' 到 App\Controller\IndexController 的 get 方法
Router::get('/get', 'App\Controller\IndexController::get');
Router::get('/get', 'App\Controller\IndexController@get');
Router::get('/get', [\App\Controller\IndexController::class, 'get']);// 设置一个 POST 请求的路由,绑定访问地址 '/post' 到 App\Controller\IndexController 的 post 方法
Router::post('/post', 'App\Controller\IndexController::post');
Router::post('/post', 'App\Controller\IndexController@post');
Router::post('/post', [\App\Controller\IndexController::class, 'post']);// 设置一个允许 GET、POST 和 HEAD 请求的路由,绑定访问地址 '/multi' 到 App\Controller\IndexController 的 multi 方法
Router::addRoute(['GET', 'POST', 'HEAD'], '/multi', 'App\Controller\IndexController::multi');
Router::addRoute(['GET', 'POST', 'HEAD'], '/multi', 'App\Controller\IndexController@multi');
Router::addRoute(['GET', 'POST', 'HEAD'], '/multi', [\App\Controller\IndexController::class, 'multi']);

路由组

Router::addGroup('/user',function (){Router::get('/index', 'App\Controller\UserController::index');Router::post('/create', 'App\Controller\UserController::createUser');Router::put('/update', 'App\Controller\UserController::update');Router::delete('/delete', 'App\Controller\UserController::delete');
});

必填参数

我们可以对 $uri 进行一些参数定义,通过 {} 来声明参数,如 /user/{id} 则声明了 id 值为一个必填参数。

可选参数

有时候您可能会希望这个参数是可选的,您可以通过[]来声明中括号内的参数为一个可选参数,如 /user/[{id}]

校验参数

您也可以使用正则表达式对参数进行校验,以下是一些例子

use Hyperf\HttpServer\Router\Router;// 可以匹配 /user/42, 但不能匹配 /user/xyz
Router::addRoute('GET', '/user/{id:\d+}', 'handler');// 可以匹配 /user/foobar, 但不能匹配 /user/foo/bar
Router::addRoute('GET', '/user/{name}', 'handler');// 也可以匹配 /user/foo/bar as well
Router::addRoute('GET', '/user/{name:.+}', 'handler');// 这个路由
Router::addRoute('GET', '/user/{id:\d+}[/{name}]', 'handler');
// 等同于以下的两个路由
Router::addRoute('GET', '/user/{id:\d+}', 'handler');
Router::addRoute('GET', '/user/{id:\d+}/{name}', 'handler');// 多个可选的嵌套也是允许的
Router::addRoute('GET', '/user[/{id:\d+}[/{name}]]', 'handler');// 这是一条无效的路由, 因为可选部分只能出现在最后
Router::addRoute('GET', '/user[/{id:\d+}]/{name}', 'handler');

注解路由

在这里插入图片描述

例如:

<?php
/*** OrderController.php** Created on Orders-11:19* Created by xxp 332410549@qq.com*/namespace App\Controller;use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Contract\RequestInterface;/*** @Controller(prefix="order")*/
class OrderController extends AbstractController
{/*** @GetMapping(path="index")*/public function index(RequestInterface $request){return 'OrderController'.$request->input('id');}
}

访问地址

http://hyperf.demos.xp:9501/order/index

HTTP 异常

在路由匹配不到路由时,如 路由找不到(404)请求方法不允许(405) 等 HTTP 异常,Hyperf 会统一抛出一个 Hyperf\HttpMessage\Exception\HttpException 异常类的子类,
您需要通过 ExceptionHandler 机制来管理这些异常并做对应的响应处理,默认情况下可以直接使用组件提供的 Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler 来进行异常捕获处理,注意这个异常处理器需要您自行配置到 config/autoload/exceptions.php 配置文件中去,并保障多个异常处理器之间的顺序链路是正确的。
当您需要对 路由找不到(404)请求方法不允许(405) 等 HTTP 异常情况的响应进行自定义处理时,您可直接根据 HttpExceptionHandler 的代码实现您自己的异常处理器,并配置您自己的异常处理器。关于异常处理器的逻辑和使用说明,可具体查阅 异常处理

异常处理器

在 Hyperf 里,业务代码都运行在 Worker 进程 上,也就意味着一旦任意一个请求的业务存在没有捕获处理的异常的话,都会导致对应的 Worker 进程 被中断退出,这对服务而言也是不能接受的,捕获异常并输出合理的报错内容给客户端也是更加友好的。
我们可以通过对各个 server 定义不同的 异常处理器(ExceptionHandler),一旦业务流程存在没有捕获的异常,都会被传递到已注册的 异常处理器(ExceptionHandler) 去处理。

自定义一个异常处理

在这里插入图片描述

1. 通过配置文件注册异常处理器

config/autoload/exceptions.php 文件

<?php
// config/autoload/exceptions.php
return ['handler' => ['http' => [Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler::class,App\Exception\Handler\AppExceptionHandler::class,App\Exception\Handler\FooExceptionHandler::class,],],
];
2. 定义异常处理器

app/Exception/Handler/FooExceptionHandler.php

<?php
/*** FooExceptionHandler.php** Created on ExceptionHandler -13:35* Created by xxp 332410549@qq.com*/namespace App\Exception\Handler;use App\Exception\FooException;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Psr\Http\Message\ResponseInterface;
use Throwable;class FooExceptionHandler extends ExceptionHandler
{/*** @inheritDoc*/public function handle(Throwable $throwable, ResponseInterface $response){// 判断被捕获到的异常是希望被捕获的异常if ($throwable instanceof FooException) {// 格式化输出$data = json_encode(['code' => $throwable->getCode(),'message' => $throwable->getMessage(),], JSON_UNESCAPED_UNICODE);// 阻止异常冒泡$this->stopPropagation();return $response->withStatus(500)->withBody(new SwooleStream($data));}// 交给下一个异常处理器return $response;}/*** @inheritDoc*/public function isValid(Throwable $throwable): bool{return true;}}
3. 定义异常类

app/Exception/FooException.php

<?php
/*** FooException.php** Created on FooException-13:40* Created by xxp 332410549@qq.com*/namespace App\Exception;use Hyperf\Server\Exception\ServerException;class FooException extends ServerException
{}
4. 触发异常
<?php
/*** OrderController.php** Created on Orders-11:19* Created by xxp 332410549@qq.com*/namespace App\Controller;use App\Exception\FooException;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Contract\RequestInterface;/*** @Controller(prefix="order")*/
class OrderController extends AbstractController
{/*** @GetMapping(path="index")*/public function index(RequestInterface $request){try {$data = ['code' => 0,'msg' => '获取成功','data' => ['orders' => '订单列表']];if (1) {   // 如果没有数据,返回空数组throw new FooException('自定义异常');}return $this->response->json($data);} catch (\Exception $e) {return $this->response->json(['code' => 1,'msg' => $e->getMessage()]);}}}
查看解决

在这里插入图片描述

总结:
在上面这个例子,我们先假设 FooException 是存在的一个异常,以及假设已经完成了该处理器的配置,那么当业务抛出一个没有被捕获处理的异常时,就会根据配置的顺序依次传递,整一个处理流程可以理解为一个管道,若前一个异常处理器调用 $this->stopPropagation() 则不再往后传递,若最后一个配置的异常处理器仍不对该异常进行捕获处理,那么就会交由 Hyperf 的默认异常处理器处理了。

Error 监听器

框架提供了 error_reporting() 错误级别的监听器 Hyperf\ExceptionHandler\Listener\ErrorExceptionHandler

配置

在 config/autoload/listeners.php 中添加监听器

<?php
return [\Hyperf\ExceptionHandler\Listener\ErrorExceptionHandler::class
];

抓取错误

则当出现类似以下的代码时会抛出 \ErrorException 异常

    public function index(RequestInterface $request){try {$a = [];($a[1]);return $this->response->json($data);} catch (\Throwable $e) {return $this->response->json(['code' => 1,'msg' => $e->getMessage() ."\n num:". $e->getLine()]);}}

结果

在这里插入图片描述

Ioc & Di

在这里插入图片描述
在这里插入图片描述

注入方式

简单注入

通过构造函数注入

在这里插入图片描述

Inject 注解

需要和下面 @var UserService 配置 UserService 类的类型
在这里插入图片描述

工厂对象注入

在这里插入图片描述
在这里插入图片描述

config/dependencies.php

在这里插入图片描述

中间件

原理图

中间件主要用于编织从 请求(Request) 到 响应(Response) 的整个流程,通过对多个中间件的组织,使数据的流动按我们预定的方式进行,中间件的本质是一个 洋葱模型
在这里插入图片描述
图中的顺序为按照 Middleware 1 -> Middleware 2 -> Middleware 3 的顺序组织着,我们可以注意到当中间的横线穿过 内核 即 Middleware 3 后,又回到了 Middleware 2,为一个嵌套模型,那么实际的顺序其实就是:
Request -> Middleware 1 -> Middleware 2 -> Middleware 3 -> Middleware 2 -> Middleware 1 -> Response
重点放在 核心 即 Middleware 3 ,它是洋葱的分界点,分界点前面的部分其实都是基于 请求( Request ) 进行处理,而经过了分界点时,内核 就产出了 响应(Response) 对象,也是 内核 的主要代码目标,在之后便是对 响应(Response) 进行处理了,内核 通常是由框架负责实现的,而其它的就由您来编排了。

定义全局中间件

全局中间件只可通过配置文件的方式来配置,配置文件位于 config/autoload/middlewares.php ,配置如下:

<?php
return [// http 对应 config/autoload/server.php 内每个 server 的 name 属性对应的值,该配置仅应用在该 Server 中'http' => [// 数组内配置您的全局中间件,顺序根据该数组的顺序YourMiddleware::class],
];

只需将您的全局中间件配置在该文件及对应的 Server Name 内,即该 Server 下的所有请求都会应用配置的全局中间件。

定义局部中间件

当我们有些中间件仅仅面向某些请求或控制器时,即可将其定义为局部中间件,可通过配置文件的方式定义或注解的方式。

通过配置文件定义

在使用配置文件定义路由时,您仅可通过配置文件来定义对应的中间件,局部中间件的配置将在路由配置上完成。
Hyperf\HttpServer\Router\Router 类的每个定义路由的方法的最后一个参数 $options 都将接收一个数组,可通过传递键值 middleware 及一个数组值来定义该路由的中间件,我们通过几个路由定义来演示一下:

<?php
use App\Middleware\FooMiddleware;
use Hyperf\HttpServer\Router\Router;// 每个路由定义方法都可接收一个 $options 参数
Router::get('/', [\App\Controller\IndexController::class, 'index'], ['middleware' => [FooMiddleware::class]]);
Router::post('/', [\App\Controller\IndexController::class, 'index'], ['middleware' => [FooMiddleware::class]]);
Router::put('/', [\App\Controller\IndexController::class, 'index'], ['middleware' => [FooMiddleware::class]]);
Router::patch('/', [\App\Controller\IndexController::class, 'index'], ['middleware' => [FooMiddleware::class]]);
Router::delete('/', [\App\Controller\IndexController::class, 'index'], ['middleware' => [FooMiddleware::class]]);
Router::head('/', [\App\Controller\IndexController::class, 'index'], ['middleware' => [FooMiddleware::class]]);
Router::addRoute(['GET', 'POST', 'HEAD'], '/index', [\App\Controller\IndexController::class, 'index'], ['middleware' => [FooMiddleware::class]]);// 该 Group 下的所有路由都将应用配置的中间件
Router::addGroup('/v2', function () {Router::get('/index', [\App\Controller\IndexController::class, 'index']);},['middleware' => [FooMiddleware::class]]
);

通过注解定义

在通过注解定义路由时,您仅可通过注解的方式来定义中间件,对中间件的定义有两个注解,分别为:

#[Middleware] 注解为定义单个中间件时使用,在一个地方仅可定义一个该注解,不可重复定义
#[Middlewares] 注解为定义多个中间件时使用,在一个地方仅可定义一个该注解,然后通过在该注解内定义多个 #[Middleware] 注解实现多个中间件的定义
使用 #[Middleware] 注解时需 use Hyperf\HttpServer\Annotation\Middleware; 命名空间;
使用 #[Middlewares] 注解时需 use Hyperf\HttpServer\Annotation\Middlewares; 命名空间;

注意:必须配合 #[AutoController] 或者 #[Controller] 使用

定义单个中间件:
<?php
namespace App\Controller;use App\Middleware\FooMiddleware;
use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\HttpServer\Annotation\Middleware;#[AutoController]
#[Middleware(FooMiddleware::class)]
class IndexController
{public function index(){return 'Hello Hyperf.';}
}
通过 #[Middlewares] 注解定义多个中间件:
<?php
namespace App\Controller;use App\Middleware\BarMiddleware;
use App\Middleware\FooMiddleware;
use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\Middlewares;#[AutoController]
#[Middlewares([FooMiddleware::class, BarMiddleware::class])]
class IndexController
{public function index(){return 'Hello Hyperf.';}
}
定义方法级别的中间件

在通过配置文件的方式配置中间件时定义到方法级别上很简单,那么要通过注解的形式定义到方法级别呢?您只需将注解直接定义到方法上即可。
类级别上的中间件会优先于方法级别的中间件,我们通过代码来举例一下:

<?php
namespace App\Controller;use App\Middleware\BarMiddleware;
use App\Middleware\FooMiddleware;
use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\Middlewares;#[AutoController]
#[Middlewares([FooMiddleware::class])]
class IndexController
{#[Middleware(BarMiddleware::class)]public function index(){return 'Hello Hyperf.';}
}

中间件相关的代码
生成中间件

php ./bin/hyperf.php gen:middleware Auth/FooMiddleware
<?phpdeclare(strict_types=1);namespace App\Middleware\Auth;use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;class FooMiddleware implements MiddlewareInterface
{protected ContainerInterface $container;protected RequestInterface $request;protected HttpResponse $response;public function __construct(ContainerInterface $container, HttpResponse $response, RequestInterface $request){$this->container = $container;$this->response = $response;$this->request = $request;}public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface{// 根据具体业务判断逻辑走向,这里假设用户携带的token有效$isValidToken = true;if ($isValidToken) {return $handler->handle($request);}return $this->response->json(['code' => -1,'data' => ['error' => '中间件验证token无效,阻止继续向下执行',],]);}
}

中间件的执行顺序为 FooMiddleware -> BarMiddleware

中间件的执行顺序

我们从上面可以了解到总共有 3 种级别的中间件,分别为 全局中间件、类级别中间件、方法级别中间件,如果都定义了这些中间件,执行顺序为:全局中间件 -> 类级别中间件 -> 方法级别中间件。

在>=3.0.34的版本中,新增了优先级的配置,可以在配置方法、路由中间件的时候改变中间件的执行顺序,优先级越高,执行顺序越靠前。

// 全局中间件配置文件 middleware.php

return ['http' => [YourMiddleware::class,YourMiddlewareB::class => 3,],
];
Copy to clipboardErrorCopied
// 路由中间件配置
Router::addGroup('/v2', function () {Router::get('/index', [\App\Controller\IndexController::class, 'index']);},['middleware' => [FooMiddleware::class,FooMiddlewareB::class => 3,]]
);

// 注解中间件配置

#[AutoController]
#[Middleware(FooMiddleware::class)]
#[Middleware(FooMiddlewareB::class, 3)]
#[Middlewares([FooMiddlewareC::class => 1, BarMiddlewareD::class => 4])]
class IndexController
{}

全局更改请求和响应对象

首先,在协程上下文内是有存储最原始的 PSR-7 请求对象 和 响应对象 的,且根据 PSR-7 对相关对象所要求的 不可变性(immutable),也就意味着我们在调用 $response = $response->with***() 所调用得到的 $response,并非为改写原对象,而是一个 Clone 出来的新对象,也就意味着我们储存在协程上下文内的 请求对象 和 响应对象 是不会改变的,那么当我们在中间件内的某些逻辑改变了 请求对象 或 响应对象,而且我们希望对后续的 非传递性的 代码再获取改变后的 请求对象 或 响应对象,那么我们便可以在改变对象后,将新的对象设置到上下文中,如代码所示:

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;// $request 和 $response 为修改后的对象
$request = \Hyperf\Context\Context::set(ServerRequestInterface::class, $request);
$response = \Hyperf\Context\Context::set(ResponseInterface::class, $response);

自定义 CoreMiddleWare 的行为

默认情况下,Hyperf 在处理路由找不到或 HTTP 方法不允许时,即 HTTP 状态码为 404、405 的时候,是由 CoreMiddleware 直接处理并返回对应的响应对象的,得益于 Hyperf 依赖注入的设计,您可以通过替换对象的方式来把 CoreMiddleware 指向由您自己实现的 CoreMiddleware 去。

比如我们希望定义一个 App\Middleware\CoreMiddleware 类来重写默认的行为,我们可以先定义一个 App\Middleware\CoreMiddleware 类如下,这里我们仅以 HTTP Server 为例,其它 Server 也可采用同样的做法来达到同样的目的。

<?php
declare(strict_types=1);namespace App\Middleware;use Hyperf\Contract\Arrayable;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;class CoreMiddleware extends \Hyperf\HttpServer\CoreMiddleware
{/*** Handle the response when cannot found any routes.** @return array|Arrayable|mixed|ResponseInterface|string*/protected function handleNotFound(ServerRequestInterface $request){// 重写路由找不到的处理逻辑return $this->response()->withStatus(404);}/*** Handle the response when the routes found but doesn't match any available methods.** @return array|Arrayable|mixed|ResponseInterface|string*/protected function handleMethodNotAllowed(array $methods, ServerRequestInterface $request){// 重写 HTTP 方法不允许的处理逻辑return $this->response()->withStatus(405);}
}

然后再在 config/autoload/dependencies.php 定义对象关系重写 CoreMiddleware 对象:

<?php
return [Hyperf\HttpServer\CoreMiddleware::class => App\Middleware\CoreMiddleware::class,
];

这里直接重写 CoreMiddleware 的做法需要在 1.1.0+ 版本上才有效,1.0.x 版本仍需要你再将 CoreMiddleware 的上层调用通过 DI 进行重写,然后替换 CoreMiddleware 的传值为您定义的中间件类。

常用中间件

跨域中间件
如果您需要在框架中解决跨域,则可以按照您的需求实现以下中间件

<?phpdeclare(strict_types=1);namespace App\Middleware;use Hyperf\Context\Context;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;class CorsMiddleware implements MiddlewareInterface
{public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface{$response = Context::get(ResponseInterface::class);$response = $response->withHeader('Access-Control-Allow-Origin', '*')->withHeader('Access-Control-Allow-Credentials', 'true')// Headers 可以根据实际情况进行改写。->withHeader('Access-Control-Allow-Headers', 'DNT,Keep-Alive,User-Agent,Cache-Control,Content-Type,Authorization');Context::set(ResponseInterface::class, $response);if ($request->getMethod() == 'OPTIONS') {return $response;}return $handler->handle($request);}
}

实际上,跨域配置也可以直接挂在 Nginx 上。

location / {add_header Access-Control-Allow-Origin *;add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';add_header Access-Control-Allow-Headers 'DNT,Keep-Alive,User-Agent,Cache-Control,Content-Type,Authorization';if ($request_method = 'OPTIONS') {return 204;}
}

后置中间件
通常情况下,我们都是最后执行

return h a n d l e r − > h a n d l e ( handler->handle( handler>handle(request);
Copy to clipboardErrorCopied
所以,相当于是前置中间件,如果想要让中间件逻辑后置,其实只需要更换一下执行顺序即可。

<?phpdeclare(strict_types=1);namespace App\Middleware;use Hyperf\HttpServer\Contract\RequestInterface;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;class OpenApiMiddleware implements MiddlewareInterface
{public function __construct(protected ContainerInterface $container){}public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface{// TODO: 前置操作try{$result = $handler->handle($request);} finally {// TODO: 后置操作}return $result;}
}

实践

在这里插入图片描述

中间件文件

<?phpdeclare(strict_types=1);namespace App\Middleware\Auth;use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;class FooMiddleware implements MiddlewareInterface
{/*** @var ContainerInterface*/protected $container;/*** @var RequestInterface*/protected $request;/*** @var HttpResponse*/protected $response;public function __construct(ContainerInterface $container, HttpResponse $response, RequestInterface $request){$this->container = $container;$this->response = $response;$this->request = $request;}public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface{$isValidToken = true;if ($isValidToken) {return $handler->handle($request);}return $this->response->json(['code' => -1,'data' => ['error' => '中间件验证token无效,阻止继续向下执行 ',],]);}
}

$isValidToken 根据具体业务来判断
如果为真,则放行
如果为假,则阻断

中间件调用

<?php
/*** Message.php** Created on Message-15:28* Created by xxp 332410549@qq.com*/namespace App\Controller;use Hyperf\HttpServer\Annotation\AutoController;
use App\Controller\AbstractController;
use Hyperf\HttpServer\Annotation\Middleware;
use App\Middleware\Auth\FooMiddleware;
/*** @AutoController()* @Middleware(FooMiddleware::class)*/
class MessageController extends AbstractController
{public function index(){return 'message';}
}

结果

在这里插入图片描述

php常用命令

查看php运行环境

可以看到php.ini文件所在的位置

php -i | grep ini

在这里插入图片描述

查看php某个扩展的详细详细信息

php --ri  xxx 
php --ri  swoole

在这里插入图片描述

压测工具

ab -k -c 100 -n 10000 http:127.0.0.01:9501
选项作用
-n在测试会话中所执行的请求个数。默认时,仅执行一个请求。
-c一次产生的请求个数。默认是一次一个。
-t测试所进行的最大秒数。其内部隐含值是-n 50000,它可以使对服务器的测试限制在一个固定的总时间以内。默认时,没有时间限制。
-p包含了需要POST的数据的文件。
-P对一个中转代理提供BASIC认证信任。用户名和密码由一个:隔开,并以base64编码形式发送。无论服务器是否需要(即, 是否发送了401认证需求代码),此字符串都会被发送。
-TPOST数据所使用的Content-type头信息。
-v设置显示信息的详细程度-4或更大值会显示头信息,3或更大值可以显示响应代码(404,200等),2或更大值可以显示警告和其他信息。
-V显示版本号并退出。
-w以HTML表的格式输出结果。默认时,它是白色背景的两列宽度的一张表。
-i执行HEAD请求,而不是GET。
-x设置属性的字符串。
-X对请求使用代理服务器。
-y设置属性的字符串。
-z设置属性的字符串。
-C对请求附加一个Cookie:行。其典型形式是name=value的一个参数对,此参数可以重复。
-H对请求附加额外的头信息。此参数的典型形式是一个有效的头信息行,其中包含了以冒号分隔的字段和值的对(如,“Accept-Encoding:zip/zop;8bit”)。
-A对服务器提供BASIC认证信任。用户名和密码由一个:隔开,并以base64编码形式发送。无论服务器是否需要(即,是否发送了401认证需求代码),此字符串都会被发送。
-h显示使用方法。
-d不显示"percentage served within XX [ms] table"的消息(为以前的版本提供支持)。
-e产生一个以逗号分隔的(CSV)文件,其中包含了处理每个相应百分比的请求所需要(从1%到100%)的相应百分比的(以微妙为单位)时间。由于这种格式已经“二进制化”,所以比’gnuplot’格式更有用。
-g把所有测试结果写入一个’gnuplot’或者TSV(以Tab分隔的)文件。此文件可以方便地导入到Gnuplot,IDL,Mathematica,Igor甚至Excel中。其中的第一行为标题。
-i执行HEAD请求,而不是GET。
-k启用HTTP KeepAlive功能,即在一个HTTP会话中执行多个请求。默认时,不启用KeepAlive功能。
-q如果处理的请求数大于150,ab每处理大约10%或者100个请求时,会在stderr输出一个进度计数。此-q标记可以抑制这些信息。
-r在遇到socket接收错误后,不退出测试

yum 安装

如果没安装这个工具,可执行下面的命令

yum -y install httpd-tools #这样安装使其不能支持大于20000的并发数

yum -y install httpd-tools

源码安装

yum -y install gcc gcc-c++ automake apr apr-util pcre apr-devel apr-util-devel pcre-devel		#安装httpd依赖
wget https://mirror.bit.edu.cn/apache//httpd/httpd-2.4.43.tar.gz		#下载httpd包
tar -zxvf httpd-2.4.43.tar.gz -C /usr/src		#解压httpd包
cd /usr/src/httpd-2.4.43						#切换目录到httpd包所在
./configure --prefix=/usr/local/httpd			#编译
make && make install							#安装
ln -s /usr/local/httpd/bin/* /usr/bin			#做软链接
ulimit -n 65535									#修改同时最大打开的文件数,此为临时性的

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 单一责任原则
  • CentOS7上安装RabbitMQ
  • 正则表达式入门:Python ‘ re ‘ 模块详解
  • C++内存泄漏--**关于“异常0xc0000005 读取的位置 0xDDDDDDDD时发生冲突”
  • Flask详细教程
  • <STC32G12K128入门第十步>USB HID键盘
  • 5年前端面试之路
  • 【LeetCode Cookbook(C++ 描述)】一刷二叉树综合(下)
  • “AI+Security”系列第2期(三):面向LLM(大语言模型)的漏洞挖掘与对齐防御研究
  • 橙色简洁大气体育直播自适应模板赛事直播门户自适应网站源码
  • YOLOv10:实时端到端目标检测
  • Linux驱动学习之点灯(一)
  • SVN限制提交文件必须填写日志---实操笔记
  • 【杂乱笔记】Kmp字符串匹配算法
  • 鸿萌数据恢复服务:SQL Server 中的“PFS 可用空间信息不正确”错误
  • JS中 map, filter, some, every, forEach, for in, for of 用法总结
  • 345-反转字符串中的元音字母
  • Docker容器管理
  • Effective Java 笔记(一)
  • Flannel解读
  • Go 语言编译器的 //go: 详解
  • JavaWeb(学习笔记二)
  • Linux快速配置 VIM 实现语法高亮 补全 缩进等功能
  • npx命令介绍
  • vue和cordova项目整合打包,并实现vue调用android的相机的demo
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 缓存与缓冲
  • 理解在java “”i=i++;”所发生的事情
  • 两列自适应布局方案整理
  • 马上搞懂 GeoJSON
  • 批量截取pdf文件
  • 什么是Javascript函数节流?
  • 实习面试笔记
  • 小程序01:wepy框架整合iview webapp UI
  • 学习ES6 变量的解构赋值
  • 移动端 h5开发相关内容总结(三)
  • 走向全栈之MongoDB的使用
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • Python 之网络式编程
  • #Datawhale X 李宏毅苹果书 AI夏令营#3.13.2局部极小值与鞍点批量和动量
  • #HarmonyOS:基础语法
  • #Js篇:单线程模式同步任务异步任务任务队列事件循环setTimeout() setInterval()
  • $(function(){})与(function($){....})(jQuery)的区别
  • (BAT向)Java岗常问高频面试汇总:MyBatis 微服务 Spring 分布式 MySQL等(1)
  • (C语言)共用体union的用法举例
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (独孤九剑)--文件系统
  • (已解决)vue+element-ui实现个人中心,仿照原神
  • (转)fock函数详解
  • .gitignore文件---让git自动忽略指定文件
  • .gitignore文件使用
  • .NET CORE Aws S3 使用