国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Swoft 源碼解讀

weij / 2807人閱讀

摘要:官網源碼解讀號外號外歡迎大家我們開發組定了一個就線下聚一次的小目標里面的框架算是非常重的了這里的重先不具體到性能層面主要是框架的設計思想和框架集成的服務讓框架可以既可以快速解決很多問題又可以輕松擴展中的框架有在應該無出其右了這次解讀的源碼

官網: https://www.swoft.org/

源碼解讀: http://naotu.baidu.com/file/8...

號外號外, 歡迎大家 star, 我們開發組定了一個 star 1000+ 就線下聚一次的小目標

PHP 里面的 yii/laravel 框架算是非?!钢亍沟牧? 這里的 先不具體到 性能 層面, 主要是框架的設計思想和框架集成的服務, 讓框架可以既可以快速解決很多問題, 又可以輕松擴展.

PHP 中的框架, 有 yii/laravel 在, 應該無出其右了.

這次解讀 swoft 的源碼 -- 基于 swoole2.0 原生協程的框架. 同時, swoft 使用了大量 swoole 提供的功能, 也非常適合閱讀它的代碼, 來學習如何造輪子. 其實解讀過 yii/laravel 這樣的框架后, 一些 通用 的框架設計思想就不贅述了, 主要講解和 服務器開發 相關的部分, 思路也會按照官網的 feature list 展開.

前半部分聚焦框架常用的功能:

全局容器注入 & MVC 分層設計

注解機制(亮點, 強烈推薦了解一下)

高性能路由

別名機制 $aliases

RestFul風格

事件機制

強大的日志系統

國際化(i18n)

數據庫 ORM

后半部分聚焦服務器相關的功能:

基礎概念(亮點, 第一個基于 swoole2.0 原生協程的框架)

連接池

服務治理熔斷、降級、負載、注冊與發現

任務投遞 & Crontab 定時任務

用戶自定義進程

Inotify 自動 Reload

PHP 框架的設計, 可以參考 [PSR(PHP Standards Recommendations
)](http://www.php-fig.org/psr/).
全局容器注入 & MVC 分層設計

之所以把這 2 個放一起講, 是因為一個是 , 一個是 . 只是新人聽得比較多的是 MVC 的分層設計思想, 全局容器注入了解相對較少.

MVC 分層設計: 更偏向于業務

MVC 是一種簡單通用并且實用的 對業務進行拆分然后加以實現 的設計, 本質還是 分層設計. 更重要的, 還是掌握 分層設計 的思想, 這個在工程實踐中大量的使用到, 比如 OSI 7 層網絡模型 和 TCP/IP 4 層網絡模型. 我分層設計可以有效的確定 系統邊界和職責劃分.

想要培養分層設計的思想, 其實可以從 入手, 在拆輪子然后拼輪子的過程中, 你會驚奇的發現, 藝術就在其中.

榫卯 app: https://www.douban.com/note/3...

全局容器注入

在進入這個概念之前, 先要認清另一個概念: 面向對象編程. 更常用的可能是 面向過程編程 vs 面向對象編程. 這里不會長篇大論, 只就思維方式來進行比較:

面向過程編程: 一條接一條指令的執行, 這是計算機喜歡的方式

面向對象編程: 通過對象來 抽象 里面不同的事物, 通過事物之間的聯系, 來解決與之相關的業務.

從這個角度來看, 面向對象 可能是更符合人類的思維方式, 或者說更智能的思維方式:

上者勞人. 抽象好管理對象, 從而更好的完成任務.

但是使用面向對象編程的過程中, 就會出現一個問題: new, 需要管理好對象之間依賴關系, 全局容器注入就是做這樣一件事. 使用 new, 表明一個對象需要依賴另一個對象, 但是使用容器, 則是一個對象告訴容器它需要什么對象.

怎么實現我不管 -- 這就是使用 new 和容器注入的區別, 學名叫 控制反轉.

所以, 容器是 , 在處理具體業務時, 由容器按需提供相應的 MVC 對象來處理.

注解進制

在容器的實現上, 或者說框架的底層上, 其實各個框架都 大同小異. 這里說一下 swoft 不同的地方 -- 引入注解進制.

簡單解釋一下注解進制: 通過添加注釋 & 解析注釋, 將注釋轉化為一些特定的有意義的代碼.

更簡單一點: 注釋 == 代碼

實現起來其實也很簡單, 只是可能接觸的比較少 -- 反射:

// BeanParserInjectParser
class InjectParser extends AbstractParser
{

    /**
     * Inject注解解析
     *
     * @param string $className
     * @param object $objectAnnotation
     * @param string $propertyName
     * @param string $methodName
     *
     * @return array
     */
    public function parser(string $className, $objectAnnotation = null, string $propertyName = "", string $methodName = "", $propertyValue = null)
    {
        $injectValue = $objectAnnotation->getName();
        if (!empty($injectValue)) {
            return [$injectValue, true];
        }

        // phpdoc解析
        $phpReader = new PhpDocReader(); // 將注釋轉化為類
        $property = new ReflectionProperty($className, $propertyName); // 使用反射
        $propertyClass = $phpReader->getPropertyClass($property);

        $isRef = true;
        $injectProperty = $propertyClass;
        return [$injectProperty, $isRef];
    }
}

如果熟悉 java, 會發現里面有很多地方在方法前用到了 @override, 在 symfony 中也使用到了這樣的方式. 好處是一定程度的內聚, 使用起來更加簡潔, 而且可以減少配置.

高性能路由

首先回答一個問題, 路由是什么? 從對象的角度出發, 其實路由就對應 URL. 那 URL 是什么呢?

URL, Uniform Resource Locator, 統一資源定位符.

所以, 路由這一層抽象, 就是為了解決 -- 找到 URL 對應需要執行的邏輯.

現在再來解釋一下 swoft 提到的高性能:

// app/routes.php: 路由配置文件
$router = SwoftApp::getBean("httpRouter"); // 通過容器拿 httpRouter

// config/beans/base.php: beans 配置文件
"httpRouter"      => [
    "class"          => SwoftRouterHttpHandlerMapping::class, // httpRouter 其實對應這個
    "ignoreLastSep"  => false,
    "tmpCacheNumber" => 1000,
    "matchAll"       => "",
],

// SwoftRouterHttpHandlerMapping
private $cacheCounter = 0;
private $staticRoutes = []; // 靜態路由
private $regularRoutes = []; // 動態路由
protected function cacheMatchedParamRoute($path, array $conf){} // 會緩存匹配到的路由
// 路由匹配的方法也很簡單: 校驗 -> 處理靜態路由 -> 處理動態路由
public function map($methods, $route, $handler, array $opts = [])
{
    ...
    $methods = static::validateArguments($methods, $handler);
    ...
    if (self::isNoDynamicParam($route)) {
        ...
    }
    ...
    list($first, $conf) = static::parseParamRoute($route, $params, $conf);
}

高性能 = 路由匹配邏輯簡單 + 路由緩存

別名機制 $aliases

用過 yii 的對這個就比較熟悉了, 其實是這樣一個 進化過程:

使用 __DIR__ / DIRECTORY_SEPARATOR 等拼接出絕對路徑

使用 define() / defined() 定義全局變量來使用路徑

使用 $aliases 變量替代全局變量

這里只展示一下配置的地方, 實現只是在類中開一個變 $aliases 屬性存儲一下就行了:

// config/define.php
// 基礎根目錄
!defined("BASE_PATH") && define("BASE_PATH", dirname(__DIR__, 1));
// 注冊別名
$aliases = [
    "@root"       => BASE_PATH,
    "@app"        => "@root/app",
    "@res"        => "@root/resources",
    "@runtime"    => "@root/runtime",
    "@configs"    => "@root/config",
    "@resources"  => "@root/resources",
    "@beans"      => "@configs/beans",
    "@properties" => "@configs/properties",
    "@commands"   => "@app/Commands"
];
App::setAliases($aliases);
RestFul風格

restful 的思想其實很簡單: 以資源為核心, 業務其實是圍繞資源的增刪改查. 具體到 http 中:

url 只作為資源標識, 有 2 種形式, itemitem/id, 后者表示操作具體某個資源

http method(get/post/put等)用來對應資源的 CRUD

使用 json 格式進行數據的 輸入輸出

實現起來也很簡單: 路由 + 返回

事件機制

先用 3W1H(who what why how) 分析法的思路來解釋一下 事件機制, 更重要的是, 這個有什么用.

正常的程序執行, 或者說人的思維趨勢, 都是按照 時間線性串行 的, 保持 連續性. 不過現實中會存在各種 打斷, 程序也不是永遠都是 就緒狀態, 那么, 就需要有一種機制, 來處理可能出現的各種打斷, 或者在程序不同狀態之間切換.

事件機制發展到現在, 有時候也算是一種預留手段, 根據你的經驗在需要的地方 埋點, 方便之后 打補丁.

swoft 的事件機制基于 PSR-14 實現, 高度內聚簡潔.

由三部分組成:

EventManager: 事件管理器

Event: 事件

EventHandler / Listener: 事件處理器/監聽器

執行流程:

先生成 EventManager

將 Event 和 EventHandler 注冊到 EventManager

觸發 Event, EventManager 就會調用相應的 EventHandler

使用起來就更加簡單了:

use SwoftEventEventManager;

$em = new EventManager;

// 注冊事件監聽
$em->attach("someEvent", "callback_handler"); // 這里也可以使用注解機制, 實現事件監聽注冊

// 觸發事件
$em->trigger("someEvent", "target", ["more params"]);

// 也可以
$event = new Event("someEvent", ["more params"]);
$em->trigger($event);

來看一下 swoft 在事件機制這里用來提升性能的亮點:

namespace SwoftEvent;

class ListenerQueue implements IteratorAggregate, Countable
{
    protected $store;

    /**
     * 優先級隊列
     * @var SplPriorityQueue
     */
    protected $queue;

    /**
     * 計數器
     * 設定最大值為 PHP_INT_MAX == 300
     * @var int
     */
    private $counter = PHP_INT_MAX;

    public function __construct()
    {
        $this->store = new SplObjectStorage(); // Event 對象先添加都這里
        $this->queue = new SplPriorityQueue(); // 然后加入優先級隊列, 之后進行調度
    }
    ...
}

稍微玩過 ACM 的人對 優先級隊列 就不會陌生了, 基本所有 OJ 都有相關的題庫. 不過 PHPer 不用太操心底層實現, 直接借助 SPL 庫即可.

SPL, Standard PHP Library, 類似 C++ 的 STL, PHPer 一定要了解一下.
強大的日志系統

使用 monolog/monolog 來實現日志系統基本已成為標配了, 當然底層還是實現 PSR-3 標準. 不過這個標準出現比較早, 發展到現在, 隱藏得比較深了.

這也是建立技術標準/協議的理由, 劃定好 最佳實踐, 之后的努力都是朝著越來越易用發展.

swoft 的日志系統, 由 2 部分組成:

SwoftLogLogger: 日志主體功能

SwoftLogFileHandler: 輸出日志

至于另一個文件, SwoftLogLog, 只是對 Logger 的一層封裝, 調用起來更方便而已.

當然, swoft 的日志系統和 yii2 框架有明顯相似的地方:

// 都在 App 中快讀暴露日志功能
public static function info($message, array $context = array())
{
    self::getLogger()->info($message, $context); // 其實還是使用 Logger 來處理
}

// 都添加了 profile 功能
public static function profileStart(string $name)
{
    self::getLogger()->profileStart($name);
}
public static function profileEnd($name)
{
    self::getLogger()->profileEnd($name);
}

值得一提的是, yii2 框架的日志系統由三部分組成:

Logger: 日志主體功能

Dispatch: 日志分發, 可以將同一個日志分發給不同的 Target 處理

Target: 日志消費者

這樣的設計, 其實是將 FileHandler 的功能進行拆解, 更靈活, 更方便擴展.

來看看 swoft 日志系統強大的一面:

private function aysncWrite(string $logFile, string $messageText)
{
    while (true) {
        // 使用 swoole 異步文件 IO
        $result = SwooleAsync::writeFile($logFile, $messageText, null, FILE_APPEND);
        if ($result == true) {
            break;
        }
    }
}

當然, 也可以選擇同步的方式:

private function syncWrite(string $logFile, string $messageText)
{
    $fp = fopen($logFile, "a");
    if ($fp === false) {
        throw new InvalidArgumentException("Unable to append to log file: {$this->logFile}");
    }
    flock($fp, LOCK_EX); // 注意要加鎖
    fwrite($fp, $messageText);
    flock($fp, LOCK_UN);
    fclose($fp);
}

PS: 日志統計分析功能開發團隊正在開發中, 歡迎大家推薦方案~

國際化(i18n)

這個功能的實現比較簡單, 不過 i18n 這個詞倒是可以多講一句, 原詞是 internationalization, 不過實在太長了, 所以簡寫為 i18n, 類似的還有 kubernetes -> k8s.

數據庫 ORM

ORM 這個發展很也成熟了, 看清楚下面的進化史就好了:

Statement: 直接執行 sql 語句

QueryBuild: 使用鏈式調用, 來實現拼接 sql 語句

ActiveRecord: Model, 用來映射數據庫中的表, 實際還是封裝的 QueryBuild

當然這一層層的封裝好處也很明顯, 減少 sql 的存在感.

// insert
$post = new Post();
$post->title = "daydaygo";
$post->save();

// query
$post = Post::find(1);

// update
$post->content = "coder at work";
$post->save();

// delete
$post->del();

要實現這樣的效果, 還是有一定的代碼量的, 也會遇到一些問題, 比如 代碼提示, 還有一些更高級的功能, 比如 關聯查詢

基本概念

并發 vs 并行

抓住 并行 這個范圍更小的概念就容易理解了, 并行是要 同時執行, 那么只能多 cpu 核心同時運算才行; 并發則是因為 cpu運行和切換速度快, 時間段內執行多個程序, 宏觀上 看起來 像在同時執行

協程 vs 進程

一種簡單的說法 協程是用戶態的線程. 線程由操作系統進行調度, 可以自動調度到多 cpu 上執行; 同一個時刻同一個 cpu 核心上只有一個協程運行, 當遇到用戶代碼中的阻塞 IO 時, 底層調度器會進入事件循環, 達到 協程由用戶調度 的效果

swoole2.0 原生

具體的實現原理大家到官網查看, 會有更詳細的 wiki 說明, 我這里從 工具 使用的角度來說明一下

限制條件一: 需要 swoole2.0 的協程 server + 協程 client 配合

限制條件二: 在協程 server 的 onRequet, onReceive, onConnect 事件回調中才能使用

$server = new SwooleHttpServer("127.0.0.1", 9501, SWOOLE_BASE);

// 1: 創建一個協程
$server->on("Request", function($request, $response) {
    $mysql = new SwooleCoroutineMySQL();
    // 協程 client 有阻塞 IO 操作, 觸發協程調度
    $res = $mysql->connect([
        "host" => "127.0.0.1",
        "user" => "root",
        "password" => "root",
        "database" => "test",
    ]);
    // 阻塞 IO 事件就緒, 協程恢復執行
    if ($res == false) {
        $response->end("MySQL connect fail!");
        return;
    }
    // 出現阻塞 IO, 繼續協程調度
    $ret = $mysql->query("show tables", 2);
    $response->end("swoole response is ok, result=".var_export($ret, true));
});

$server->start();

注意: 觸發一次回調函數, 就會在開始的時候生成一個協程, 結束的時候銷毀這個協程, 協程的生命周期, 伴隨此處回調函數執行的生命周期

連接池

swoft 的連接池功能實現, 主要在 src/Pool 下, 主要由三部分組成:

Connect: 連接, 值得一提的是, 為了后續使用方便, 這里同時配置了 同步連接 + 異步連接

Balancer: 負載均衡器, 目前提供 2 種策略, 隨機數 + 輪詢

Pool: 連接池, 核心部分, 負責連接的管理和調度

PS: 自由切換同步/異步客戶端非常簡單, 切換一下連接就好

直接上代碼:

// 使用 SqlQueue 來管理連接
public function getConnect()
{
    if ($this->queue == null) {
        $this->queue = new SplQueue(); // 又見 Spl
    }

    $connect = null;
    if ($this->currentCounter > $this->maxActive) {
        return null;
    }
    if (!$this->queue->isEmpty()) {
        $connect = $this->queue->shift(); // 有可用連接, 直接取
        return $connect;
    }

    $connect = $this->createConnect();
    if ($connect !== null) {
        $this->currentCounter++;
    }
    return $connect;
}

// 如果接入了服務治理, 將使用調度器
public function getConnectAddress()
{
    $serviceList = $this->getServiceList(); // 從 serviceProvider 那里獲取到服務列表
    return $this->balancer->select($serviceList);
}
服務治理熔斷、降級、負載、注冊與發現

swoft 的服務治理相關的功能, 主要在 src/Service 下:

Packer: 封包器, 和協議進行對應, 看過 swoole 文檔的同學, 就能知道協議的作用了

ServiceProvider: 服務提供者, 用來對接第三方服務管理方案, 目前已實現 Consul

Service: RPC服務調用, 包含同步調用和協程調用(deferCall()), 目前添加 callback 實現簡單的 降級

ServiceConnect: 連接池中 Connect 的 RPC Service 實現, 不過個人認為放到連接池中實現更好

Circuit: 熔斷, 在 src/Circuit 中實現, 有三種狀態, 關閉/開啟/半開

DispatcherService: 服務調度器, 在 Service 之前封裝一層, 添加 Middleware/Event 等功能

這里看看熔斷這部分的代碼, 半開狀態的邏輯復雜一些, 值得參考:

// SwoftCircuitCircuitBreaker
public function init()
{
    // 狀態初始化
    $this->circuitState = new CloseState($this);
    $this->halfOpenLock = new swoole_lock(SWOOLE_MUTEX); // 使用 swoole lock
}

// SwoftCircuitHalfOpenState
public function doCall($callback, $params = [], $fallback = null)
{
    // 加鎖
    $lock = $this->circuitBreaker->getHalfOpenLock();
    $lock->lock();
    ...
    // 釋放鎖
    $lock->unlock();
}
任務投遞 & Crontab 定時任務

swoft 任務投遞的實現機制當然離不開 SwooleTimer::tick()(SwooleServer->task() 底層執行機制是一樣的) , swoft 在實現的時候, 添加了 喜聞樂見 的 crontab 方式, 實現在 src/Crontab 下:

ParseCrontab: 解析 crontab

TableCrontab: 使用 SwooleTable 實現, 用來存儲 crontab 任務

Crontab: 連接 Task 和 TableCrontab

這里主要看一下 TableCrontab:

// 存儲原始的任務
private $originStruct = [
    "rule"       => [SwooleTable::TYPE_STRING, 100],
    "taskClass"  => [SwooleTable::TYPE_STRING, 255],
    "taskMethod" => [SwooleTable::TYPE_STRING, 255],
    "add_time"   => [SwooleTable::TYPE_STRING, 11]
];
// 存儲解析后的任務
private $runTimeStruct = [
    "taskClass"  => [SwooleTable::TYPE_STRING, 255],
    "taskMethod" => [SwooleTable::TYPE_STRING, 255],
    "minte"      => [SwooleTable::TYPE_STRING, 20],
    "sec"        => [SwooleTable::TYPE_STRING, 20],
    "runStatus"  => [SwooleTABLE::TYPE_INT, 4]
];
用戶自定義進程

自定義進程對 SwooleProcess 的封裝, swoft 封裝之后, 想要使用用戶自定義進程更簡單了:

繼承 AbstractProcess 類, 并實現 run() 來執行業務邏輯.

swoft 中功能實現在 src/Process 下, 框架自帶三個自定義進程:

Reload: 配合 ext-inotify 擴展實現自動 reload, 下面會具體講解

CronTimer: crontab 里的 task 在這里觸發 SwooleServer->tick()

CronExec: 實現協程 task, 實現中.

代碼就不貼了, 這里再擴展一個比較適合使用自定義進程的場景: 訂閱服務

Inotify 自動 Reload

服務器程序大都是常駐進程, 有效減少對象的生成和銷毀, 提供性能, 但是這樣也給服務器程序的開發帶來了問題, 需要 reload 來查看生效后的程序. 使用 ext-inotify 擴展可以解決這個問題.

直接上代碼, 看看 swoft 中的實現:

// SwoftProcessReloadProcess
public function run(Process $process)
{
    $pname = $this->server->getPname();
    $processName = "$pname reload process";
    $process->name($processName);

    /* @var Inotify $inotify */
    $inotify = App::getBean("inotify"); // 自定義進程來啟動 inotify
    $inotify->setServer($this->server);
    $inotify->run();
}

// SwoftBaseInotify
public function run()
{

    $inotify = inotify_init(); // 使用 inotify 擴展

    // 設置為非阻塞
    stream_set_blocking($inotify, 0);

    $tempFiles = [];
    $iterator = new RecursiveDirectoryIterator($this->watchDir);
    $files = new RecursiveIteratorIterator($iterator);
    foreach ($files as $file) {
        $path = dirname($file);

        // 只監聽目錄
        if (!isset($tempFiles[$path])) {
            $wd = inotify_add_watch($inotify, $path, IN_MODIFY | IN_CREATE | IN_IGNORED | IN_DELETE);
            $tempFiles[$path] = $wd;
            $this->watchFiles[$wd] = $path;
        }
    }

    // swoole Event add
    $this->addSwooleEvent($inotify);
}
private function addSwooleEvent($inotify)
{
    // swoole Event add
    swoole_event_add($inotify, function ($inotify) { // 使用 SwooleEvent
        // 讀取有事件變化的文件
        $events = inotify_read($inotify);
        if ($events) {
            $this->reloadFiles($inotify, $events); // 監聽到文件變動進行更新
        }
    }, null, SWOOLE_EVENT_READ);
}
寫在最后

再補充一點, 在實現服務管理(reload stop)時, 使用的 posix_kill(pid, sig);, 并不是用 SwooleServer 中自帶的 reload() 方法, 因為我們當前環境的上下文并不一定在SwooleServer 中.

想要做好一個框架, 尤其是一個開源框架, 實際上要比我們平時寫 業務代碼 要難很多, 一方面是業務初期的 多快好省, 往往要上一些 能跑 的代碼. 這里引入一些關于代碼的觀點:

代碼質量: bug 率 + 性能

代碼規范: 形成規范可以提高代碼開發/使用的體驗

代碼復用: 這是軟件工程的難題, 需要慢慢積累, 有些地方可以通過遵循規范走走捷徑

總結起來就一句話:

想要顯著提高編碼水平或者快速積累相關技術知識, 參與開源可以算是一條捷徑.

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/28210.html

相關文章

  • swoft| 源碼解讀系列二: 啟動階段, swoft 都干了些啥?

    摘要:源碼解讀系列二啟動階段都干了些啥閱讀框架源碼了解啟動階段的那些事兒小伙伴剛接觸的時候會感覺壓力有點大更直觀的說法是難開發組是不贊成難這個說法的的代碼都是實現的而又是世界上最好的語言的代碼閱讀起來是很輕松的之后開發組會用系列源碼解讀文章深 date: 2018-8-01 14:22:17title: swoft| 源碼解讀系列二: 啟動階段, swoft 都干了些啥?descriptio...

    hqman 評論0 收藏0
  • swoft| 源碼解讀系列一: 好難! swoft demo 都跑不起來怎么破? docker 了解

    摘要:源碼解讀系列一好難都跑不起來怎么破了解一下唄閱讀框架源碼第一步搞定環境小伙伴剛接觸的時候會感覺壓力有點大更直觀的說法是難開發組是不贊成難這個說法的的代碼都是實現的而又是世界上最好的語言的代碼閱讀起來是很輕松的開發組會用源碼解讀系列博客深 date: 2018-8-01 14:22:17title: swoft| 源碼解讀系列一: 好難! swoft demo 都跑不起來怎么破? doc...

    shenhualong 評論0 收藏0
  • swoft| 源碼解讀系列一: 好難! swoft demo 都跑不起來怎么破? docker 了解

    摘要:源碼解讀系列一好難都跑不起來怎么破了解一下唄閱讀框架源碼第一步搞定環境小伙伴剛接觸的時候會感覺壓力有點大更直觀的說法是難開發組是不贊成難這個說法的的代碼都是實現的而又是世界上最好的語言的代碼閱讀起來是很輕松的開發組會用源碼解讀系列博客深 date: 2018-8-01 14:22:17title: swoft| 源碼解讀系列一: 好難! swoft demo 都跑不起來怎么破? doc...

    rollback 評論0 收藏0
  • Swoole 在 Swoft 中的應用

    摘要:在中的應用官網源碼解讀號外號外歡迎大家我們開發組定了一個就線下聚一次的小目標上一篇源碼解讀反響還不錯不少同學推薦再加一篇講解一下中使用到的功能幫助大家開啟的實戰之旅服務器開發涉及到的相關技術領域的知識非常多不日積月累打好基礎是很難真正 date: 2017-12-14 21:34:51title: swoole 在 swoft 中的應用 swoft 官網: https://www.sw...

    EscapedDog 評論0 收藏0
  • Swoft 源碼剖析 - 目錄

    摘要:作者鏈接來源簡書著作權歸作者所有,本文已獲得作者授權轉載,并對原文進行了重新的排版。同時順手整理個人對源碼的相關理解,希望能夠稍微填補學習領域的空白。系列文章只會節選關鍵代碼輔以思路講解,請自行配合源碼閱讀。 作者:bromine鏈接:https://www.jianshu.com/p/2f6...來源:簡書著作權歸作者所有,本文已獲得作者授權轉載,并對原文進行了重新的排版。Swoft...

    qpwoeiru96 評論0 收藏0

發表評論

0條評論

weij

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<