Swoft source code analysis-what happened to swole and Swoft (Http/Rpc services)

  php, swoft, swoole

Author:bromine
Links:https://www.jianshu.com/p/4c0 …
Source: Simple Book
The copyright belongs to the author. This article has been reprinted with the authorization of the author and the original text has been rearranged.
Swoft Github:https://github.com/swoft-clou …

Swoft source code analysis series catalog:https://segmentfault.com/a/11 …

Preface

SwoftInPHPerThe circle has a higher thresholdWebThe framework, not only because the framework itself brings many new concepts and cutting-edge designs, but also lies inSwoftIs based onSwooleThe framework of.SwooleInPHPerThere is no one of the most expensive learning tools in the circle, althoughSwoftThe emergence of the reducedSwooleThe cost of using, but if you are rightSwooleIt is still very difficult to avoid falling into various kinds of things if one does not have enough in-depth knowledge of oneself.“Pit”China.

Considering this situation, and in order to reduce the reading difficulty, the following several sumsSwooleThe author will adjust his writing thinking and position the article from a more closely linked mechanism.“help readers understand Swoft deeply”Adjust to“help readers understand Swoft and Swoole”, narrative rhythm will slow down.

Web Models for Three PHP Applications

LNMP模型

LNMPAndLAMPIs the overwhelming majorityPHPerThe most familiar infrastructure Web architecture, here to commonLNMPAs an example, describe a commonNo SwooleComponent composition applied:NginxAct asWeb Service,PHP-FPMMaintain a process pool to runWebProject.

Compared with older onesCGIModels,PHP-FPMThe concept of process resident has been introduced to avoid the cost of creating and destroying processes and the cost of expanding loads for each request, but PHP still needs to be executed for each request.RINITAndRSHUTDOWNAll processes between, including reloading the source code of the framework and the project code once, cause great performance waste.

The advantages of this model are simple, mature and stable.One run followed by destructionThe development convenience brought about isPHPOne of the reasons for its popularity. Most of them are on the market.PHPAll projects use variations based on this architecture.

LNMP-with-Swoole模型

LNMP-with-SwooleYesLNMPA variant ofLNMPOn the basis of the introduction ofSwooleComponents.
AndPHP-FPMSame,SwooleIt has its own process management mechanism. However, as code becomes highly resident and programming thinking needs to change from synchronous to asynchronous, soSwooleAnd traditional onesPHP-FPMTheWebThe compatibility of the framework is very low, even if it is old-fashioned and adapted and upgraded.WebFramework, currently inSwooleOn the performance of the operation is often not good.

Therefore, there is a compromise that does not directly change the originalPHPThe code runs onSwooleInstead, use theSwooleA service is set up, and the system connects withSwooleCommunication toWebThe project complements asynchronous processing capabilities. I call this simultaneous usePHP-FPMAndSwooleThe system of is halfSwooleApplication. Because access is simple, it is the Swoole access scheme that most existing projects give priority to.

LNMP-with-Swoole modelAlthough introducedSwooleAnd asynchronous processing capability, the core is stillPHP-FPM, in fact is far from play outSwooleThe real advantage of.

Swoole-HTTP-Server模型

Swoole-HTTP-ServerAndLNMP-with-SwooleCompared with great changes, this model acts asWeb ServerThe components of a role are not onlyNginx, the application itself also contains a built-inWeb ServerHowever, due toSwoole Http ServerNot professionalHTTP ServerYesHttpThe processing of is not perfect, so Nginx still needs to be used as a static resource server and a reverse generation.Swoole HTTP ServerHandle onlyPHPcorrelativeHTTPFlow rate.

On the one hand, due toSwooleIt already includesWebServer, no longer need to implementCGIOr ..Fast-CGIThe general agreement to go withWeb ServerCommunications, on the other handSwooleHas its own process management, thereforePHP-FPMCan be directly removed. ForPHPIn terms of resources, in this model,Swoole Http ServerThe position of the is equivalent to that of the traditional modelNginxAndPHP-FPMThe sum of.

Once the memory resident is loaded, different requests are basically multiplexed.onRequestAll processes other than the above, so that the cost of each request is greatly reduced;Asynchronous IOThe nature of makes this modelThroughput is much higher than traditionalLNMP model. In addition, relative to the independentSwooleServices, embedded inWebIn the systemSwooleIt is more direct and convenient to use and better to support.

What is the relationship between Swoft and Swoole?

  1. SwooleIs an asynchronous engine, the core is forPHPProvideAsynchronous IOAbility to executeAt the same time, it provides a set of tool sets that may be used in asynchronous programming.
  2. Swoole-HTTP-ServerYesSwooleA component of isSwooleServerOne of the, provides a suitableSwooleDirectly operatingHttpServerEnvironment.
  3. SwoftOneModern Web framework,AndSwooleHigh affinityAt the same time, it is also mentioned above.Swoole-HTTP-ServerA practice of the model.

SwoftManage thisWebIn the modelSwoole, andSwoole-HTTP-Server,Block developersSwooleAll kinds of complicated operation details ofAnd as aWeb frameworkProvide developers with a variety ofWeb developmentNeed to useRouting,MVC,Database accessSuch as functional components, etc.

How does Swoft use Swoole?

The most important thing isHttpServeras well asRpcServer

HTTP server

SwoftDirectly used isSwoolebuilt-in\Swoole\Http\Server, it has dealt with allHTTPWe only need to pay attention to the application itself, let’s take a look at everything at the level.HTTPServe several important life cycle points.

Swoole before startup

The behavior at this stage has several characteristics

  1. basisbootstrapBehavior: if necessary constant definition is required,ComposerLoading device introduction, configuration reading, etc.
  2. Need to generate allWorker/TaskObjects of the program global period shared by processes, such asSwoole\Lock,Swoft\Memory\TableThe creation of the;
  3. At startup, operations that can only be performed once in all processes in total: such as prepositingProcessThe start of the;
  4. BeanThe basic initialization of the container and the requirements for the project startup processcoreBeanThe load of the.

This piece involves a lot of things and will be introduced in a separate article for the sake of space control.

AndHttpThe process with the closest service relationship isSwoolehit the targetWorker process (group), most of the business processing is carried out in the process.
For eachSwoole event,SwoftAll provide the correspondingSwoole listener(Correspondence@SwooleListenerComments) as an event mechanism package. To understandSwoftTheHttpServerHow did it happenSwooleUnder the operation of our focus needs to focus on the next two in the twoSwooleEventsswoole.workerStartAndswoole.onRequest.

swoole.workerStartEvents

WorkerStartThe incident occurred atTaskWorker/WorkerOccurs when the process starts, eachTaskWorker/WorkerIt will be executed once in the process.
This is a key node becauseswoole.workerStartNew objects created after callback are all process global, and the memory used is specific.Task/WorkerProcess, independent of each other. Also, only the part initialized at this stage or later can be thermally reloaded.
The key code at the bottom of the event is as follows:

// Swoft\Bootstrap\Server\ServerTrait.php
/**
 * @param bool $isWorker
 * @throws \InvalidArgumentException
 * @throws \ReflectionException
 */
protected function reloadBean(bool $isWorker)
{
    BeanFactory::reload();
    $initApplicationContext = new InitApplicationContext();
    $initApplicationContext->init();

    if($isWorker && $this->workerLock->trylock() && env('AUTO_REGISTER', false)){
        App::trigger(AppEvent::WORKER_START);
    }
}

There are three things to do here.

  1. InitializationBeanContainer:
    The aboveBeanFactory::reload();exactlySwoftTheBeanThe container initializes the entry and the annotation is scanned here (actually this statement is not accurate.BeanThe real initialization phase of the container isSwoole ServerPrior to startupBootStrapThe phase has already been carried out, but only a small part of initialization was carried out at that time, relativelyswoole.workerStartInitialized in theBeanNumber, proportion is very small). InworkerStartInitialization inBeanThe container isSwoftThe code base can be updated hot.
  2. Initialized application context
    initApplicationContext->init()Will registerSwoftEvent Listener (Corresponding@Listener), convenient for users to handleSwoftThe application itself has various hooks. Then trigger aswoft.applicationLoaderEvent, through which each component carries out configuration file loading.HTTP/RPCRouting registration.
  3. Service registration
    The specific content will be described in the service governance chapter.

swoole.onRequestEvents

Each ..HTTPThe request will only be triggered when it arrives.swoole.onRequestEvents.
The framework code itself is made up of a large number of objects in the process global phase and a small number of objects in the program global phase, whileonReceiveFor example$requestAnd$responseIt’s all for the request period, withHTTPAt the end of the request and recycling.

The key code at the bottom of the event is as follows:

/**
 * @param array ...$params
 * @return \Psr\Http\Message\ResponseInterface
 * @throws \InvalidArgumentException
 */
public function dispatch(...$params): ResponseInterface
{
    /**
     * @var RequestInterface $request
     * @var ResponseInterface $response
     */
    list($request, $response) = $params;

    try {
        // before dispatcher
        $this->beforeDispatch($request, $response);

        // request middlewares
        $middlewares = $this->requestMiddleware();
        $request = RequestContext::getRequest();
        $requestHandler = new RequestHandler($middlewares, $this->handlerAdapter);
        $response = $requestHandler->handle($request);

    } catch (\Throwable $throwable) {
        /* @var ErrorHandler $errorHandler */
        $errorHandler = App::getBean(ErrorHandler::class);
        $response = $errorHandler->handle($throwable);
    }

    $this->afterDispatch($response);

    return $response;
}
  1. beforeDispatch($request, $response):
    Set the request context and trigger aswoft.beforeRequestEvents.
  2. RequestHandler->handle($request):
    The middleware is executed corresponding to the requestActionFor details, please refer toRPC chapter, the principle is basically the same.
  3. $afterDispatch($response):
    FinishingHTTPThe response message is sent to the client and triggeredswoft.resourceRelease(Details are atConnection Pool(mentioned in) events andswoft.afterRequestEvents

In general, looking at these life cycle points, you need to know a few things:

  1. SwooleTheWorkerThe process is your overwhelming majority.HTTPThe operating environment of the service code.
  2. Some initialization and load operations are performed inSwooleTheServerCompleted before startup, some inswoole.workerStartEvent callback, the former cannot be hot overloaded but may be shared by multiple processes.
  3. Initialization code is only available at system startup andWorker/TaskThe process is executed once when it is started, unlikePHP-FPMEach request is executed once, and the frame object is not the samePHP-FPMIt will be destroyed upon request.
  4. Each request is triggered onceswoole.onRequestEvent, which is where our request processing code actually runs, only the objects generated in this event will be recycled at the end of the request.

RPC server

Life cycle sumHTTP serviceBasically the same, please refer to the details“Swoft Source Code Analysis -RPC Function Implementation”