首页后端开发JAVAHyperf 源码分析-HttpServer

Hyperf 源码分析-HttpServer

时间2023-12-07 01:46:03发布访客分类JAVA浏览855
导读:实例化在 Hyperf 启动 中在注册服务事件(registerSwooleEvents)的时候会对回调方法和类进行实例化,然后指定回调方法 onRequest ,还有在对初始化回调的时候,对于 MiddlewareInitializerI...

实例化

在 Hyperf 启动 中在注册服务事件(registerSwooleEvents)的时候会对回调方法和类进行实例化,然后指定回调方法 onRequest ,还有在对初始化回调的时候,对于 MiddlewareInitializerInterface 回调进行中间件初始化。所以在注册事件的时候就执行了 HttpServer 的两个方法

构建方法

在构造方法中,定义了一个容器对象,两个分发起,还有一个返回发送器。

  • HttpDispatcher
  • ExceptionHandlerDispatcher
  • ResponseEmitter
public function __construct(ContainerInterface $container, HttpDispatcher $dispatcher, ExceptionHandlerDispatcher $exceptionHandlerDispatcher, ResponseEmitter $responseEmitter)
  {
    
    $this->
    container = $container;
    
    $this->
    dispatcher = $dispatcher;
    
    $this->
    exceptionHandlerDispatcher = $exceptionHandlerDispatcher;
    
    
    $this->
    responseEmitter = $responseEmitter;

  }

Http分发器 HttpDispatcher

在分发器处理方法中,接收的参数是 $request, $middlewares, $coreHandler ,并实例化 HttpRequestHandler 对象处理。也就是每次分发都是由一个新的Handle处理的。

  • request 请求对象
  • middlewares 中间件
  • coreHandler 核心中间件
public function dispatch(...$params): ResponseInterface
{
    
  /**
  * @param RequestInterface $request
  * @param array $middlewares
  * @param MiddlewareInterface $coreHandler

  */
  [$request, $middlewares, $coreHandler] = $params;
    
  $requestHandler = new HttpRequestHandler($middlewares, $coreHandler, $this->
    container);
    
  return $requestHandler->
    handle($request);

}

异常处理分发器 exceptionHandlerDispatcher

异常处理异常分发器,将异常 $throwable 分发到各个handler去。所以分发处理方法有两个参数

  • throwable
  • handlers

主要是处理业务中没有处理异常,根据匹配规则将异常交给指定的异常处理器。

  public function dispatch(...$params)
    {
    
        /**
         * @param Throwable $throwable
         * @param string[] $handlers
         */
        [$throwable, $handlers] = $params;
    
        $response = Context::get(ResponseInterface::class);


        foreach ($handlers as $handler) {
    
            //找不到处理对象
            if (! $this->
    container->
has($handler)) {
    
                throw new \InvalidArgumentException(sprintf('Invalid exception handler %s.', $handler));

            }
    
            //对象是否异常处理,还有是是否通过 isValid 校验,如果不通过,直接跳过处理下一个
            $handlerInstance = $this->
    container->
    get($handler);
    
            if (! $handlerInstance instanceof ExceptionHandler || ! $handlerInstance->
isValid($throwable)) {
    
                continue;

            }
    
            $response = $handlerInstance->
    handle($throwable, $response);
    
            //是否继续往下处理
            if ($handlerInstance->
isPropagationStopped()) {
    
                break;

            }

        }
    
        return $response;

    }

返回发送器 ResponseEmitter

顾名思义,返回发送器就是将http请求的Response发送出去。主要原理就是将常规的Response构建成SwooleResponse进行发送。

 public function emit(ResponseInterface $response, $swooleResponse, bool $withContent = true)
    {

        try {
    
            if (strtolower($swooleResponse->
header['Upgrade'] ?? '') === 'websocket') {
    
                return;

            }
    
            $this->
    buildSwooleResponse($swooleResponse, $response);
    
            $content = $response->
    getBody();

            if ($content instanceof FileInterface) {
    
                $swooleResponse->
    sendfile($content->
    getFilename());
    
                return;

            }


            if ($withContent) {
    
                $swooleResponse->
    end((string) $content);

            }
 else {
    
                $swooleResponse->
    end();

            }

        }
 catch (\Throwable $exception) {

        }

    }

初始化中间件 initCoreMiddleware

public function initCoreMiddleware(string $serverName): void
  {
    
    $this->
    serverName = $serverName;
    
    $this->
    coreMiddleware = $this->
    createCoreMiddleware();
    
    $this->
    routerDispatcher = $this->
    createDispatcher($serverName);
    

    $config = $this->
    container->
    get(ConfigInterface::class);
    
    $this->
    middlewares = $config->
    get('middlewares.' . $serverName, []);
    
    $this->
    exceptionHandlers = $config->
    get('exceptions.handler.' . $serverName, $this->
    getDefaultExceptionHandler());

  }
    

构建中间件

  1. createCoreMiddleware 创建实例化核心中间件,然后由 HttpDispatcher 分发。
  2. 获取配置文件中的全局中间件。

$this-> middlewares = $config-> get('middlewares.' . $serverName, []);

创建路由分发器

路由分发器由 hyperf/http-server/src/Router/DispatcherFactory.php 类进行处理,路由主要分两类,一类是配置路由,一类是注解路由。后续会专门针对Hyperf路由再写一章。

public function __construct()
  {
    
    $this->
    initAnnotationRoute(AnnotationCollector::list());
    
    $this->
    initConfigRoute();

  }

异常处理集合

异常集合由默认的异常处理 HttpExceptionHandler 和配置文件 exceptions.php 中指定的为服务异常处理数组组成。简单点说,就是在 exceptions.php 文件配置HttpServer的多个异常处理。

请求回调方法 onRequest

初始化请求和返回 initRequestAndResponse

回调接收到的参数的 Swoole\Http\RequestSwoole\Http\Response 这是 Swoole 中的请求和返回格式。initRequestAndResponse方法就是将它们重构成 符合 psr7 标准的请求和返回。

这里还使用协程上下文Context还存储Request 和 Response,因为每个请求都是独立的,这样保证每个http请求拿到的Request和返回的Response都是独立的。

protected function initRequestAndResponse($request, $response): array
  {
    
    Context::set(ResponseInterface::class, $psr7Response = new Psr7Response());


    if ($request instanceof ServerRequestInterface) {
    
      $psr7Request = $request;

    }
 else {
    
      $psr7Request = Psr7Request::loadFromSwooleRequest($request);
    
      $psr7Response->
    setConnection(new SwooleConnection($response));

    }
    

    Context::set(ServerRequestInterface::class, $psr7Request);
    
    return [$psr7Request, $psr7Response];

  }

Hyperf\HttpMessage\Server\Request

Hyperf\HttpMessage\Server\Response

核心中间件 CoreMiddleware

调度 dispatch

public function dispatch(ServerRequestInterface $request): ServerRequestInterface
  {
    
    $routes = $this->
    dispatcher->
    dispatch($request->
    getMethod(), $request->
    getUri()->
    getPath());
    

    $dispatched = new Dispatched($routes);
    

    return Context::set(ServerRequestInterface::class, $request->
    withAttribute(Dispatched::class, $dispatched));

  }

核心中间件的调度分两步,

  • 通过自身的分发器价获取路由数组 $routes,打印 $routes 信息发现,里面有一个 Hyperf\HttpServer\Router\Handler 对象组成的数据,这里说明路由的回调处理发放,路由规则,还有中间件。
array(3) {
    
  [0]=>
    
  int(1)
  [1]=>

  object(Hyperf\HttpServer\Router\Handler)#1298 (3) {
    
    ["callback"]=>

    array(2) {
    
      [0]=>
    
      string(49) "App\Application\Admin\Controller\AccessController"
      [1]=>

      string(5) "lists"
    }
    
    ["route"]=>
    
    string(25) "/admin/access/index/lists"
    ["options"]=>

    array(1) {
    
      ["middleware"]=>

      array(1) {
    
        [0]=>

        string(48) "App\Application\Admin\Middleware\AdminMiddleware"
      }

    }

  }
    
  [2]=>

  array(0) {

  }

}
    
  • New 一个新的路由分发器,将获得的 $routes 作为路由分发的构造参数。然后将路由分发器 $dispatched 加入到请求对象 $request中,再与配置中间件合并成为最后的中间件集合。
if ($dispatched->
isFound()) {
    
  $registeredMiddlewares = MiddlewareManager::get($this->
    serverName, $dispatched->
    handler->
    route, $psr7Request->
    getMethod());
    
  $middlewares = array_merge($middlewares, $registeredMiddlewares);

}

处理器 process

所有中间件都有处理器,核心中间件处理器主要负责路由中callback(控制器业务)的执行。

处理之后会将Response的 Header Server 赋值 Hyperf。

public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
  {
    
    $request = Context::set(ServerRequestInterface::class, $request);
    

    /** @var Dispatched $dispatched */
    $dispatched = $request->
    getAttribute(Dispatched::class);


    if (! $dispatched instanceof Dispatched) {
    
      throw new ServerException(sprintf('The dispatched object is not a %s object.', Dispatched::class));

    }
    

    $response = null;
    
    switch ($dispatched->
status) {
    
      case Dispatcher::NOT_FOUND:
      $response = $this->
    handleNotFound($request);
    
      break;
    
      case Dispatcher::METHOD_NOT_ALLOWED:
      $response = $this->
    handleMethodNotAllowed($dispatched->
    params, $request);
    
      break;
    
      case Dispatcher::FOUND:
      $response = $this->
    handleFound($dispatched, $request);
    
      break;

    }

    if (! $response instanceof ResponseInterface) {
    
      $response = $this->
    transferToResponse($response, $request);

    }
    
    return $response->
    withAddedHeader('Server', 'Hyperf');

  }
  • 通过Request 获取路由分发器 $dispatched
  • 查看路由状态,调用路由中在callback方法(也就是具体的业务实现控制器),具体看
protected function handleFound(Dispatched $dispatched, ServerRequestInterface $request)
  {
    
    if ($dispatched->
    handler->
callback instanceof Closure) {
    
      $parameters = $this->
    parseClosureParameters($dispatched->
    handler->
    callback, $dispatched->
    params);
    
      $response = call($dispatched->
    handler->
    callback, $parameters);

    }
 else {
    
      [$controller, $action] = $this->
    prepareHandler($dispatched->
    handler->
    callback);
    
      $controllerInstance = $this->
    container->
    get($controller);

      if (! method_exists($controllerInstance, $action)) {
    
        // Route found, but the handler does not exist.
        throw new ServerErrorHttpException('Method of class does not exist.');

      }
    
      $parameters = $this->
    parseMethodParameters($controller, $action, $dispatched->
    params);
    
      $response = $controllerInstance->
{
$action}
    (...$parameters);

    }
    
    return $response;

  }
    
  • 返回 $response

请求调度器 dispatcher

onRequest最重要异步就是对http请求执行调度,其实就是控制中间件集合的调度。在前面步骤中已经获取所有中间件集合。$middlewares

[$request, $middlewares, $coreHandler] = $params;
    
$requestHandler = new HttpRequestHandler($middlewares, $coreHandler, $this->
    container);
    
return $requestHandler->
    handle($request);

HttpRequestHandler

整个调度器就是交由 HttpRequestHandler 对象进行控制。 handleRequest 方法就是控制各个中间件处理顺序,然后将处理后的Response 一个个中间件交下去。

protected function handleRequest($request)
  {
    
    if (! isset($this->
    middlewares[$this->
    offset]) &
    &
     ! empty($this->
coreHandler)) {
    
      $handler = $this->
    coreHandler;

    }
 else {
    
      $handler = $this->
    middlewares[$this->
    offset];
    
      is_string($handler) &
    &
     $handler = $this->
    container->
    get($handler);

    }

    if (! method_exists($handler, 'process')) {
    
      throw new InvalidArgumentException(sprintf('Invalid middleware, it has to provide a process() method.'));

    }
    
    return $handler->
    process($request, $this->
    next());

  }


protected function next(): self
  {
    
    ++$this->
    offset;
    
    return $this;

  }

异常处理

整个onRequest 回调方法处理抛出的异常$throwable 都会交由 exceptionHandlerDispatcher调度。就是将异常交给一个个 exceptionHandler 处理。

catch (Throwable $throwable) {
    
  // Delegate the exception to exception handler.
  $psr7Response = $this->
    exceptionHandlerDispatcher->
    dispatch($throwable, $this->
    exceptionHandlers);

}

返回结果发送

无论是处理完成的结果,还是异常结果,都会通过 responseEmitter将结果发送出去。

finally {

  // Send the Response to client.
  if (! isset($psr7Response)) {
    
    return;

  }
    
  if (isset($psr7Request) &
    &
     $psr7Request->
getMethod() === 'HEAD') {
    
    $this->
    responseEmitter->
    emit($psr7Response, $response, false);

  }
 else {
    
    $this->
    responseEmitter->
    emit($psr7Response, $response, true);

  }

}
    

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!


若转载请注明出处: Hyperf 源码分析-HttpServer
本文地址: https://pptw.com/jishu/571309.html
【多线程系列】终于理解了多线程中不得不谈的并发三大性质 彩虹Kangle一键脚本,是一款可以一键安装Kangle+Easypanel+MySQL+PHP集合的Linux脚本

游客 回复需填写必要信息