本篇文章,咱們將要在說明另一個在 php 實現 reactor 模式的東西swoole。 本篇文章分為以下幾個章節 : Swoole 的架構 Swoole 非阻塞 I/O 的處理 Swoole 的 Coroutine Swoole 實際使用的注意事項 swoole 的架構 swoole 官網寫到 : event-driven asynchronous & coroutine-based concurrency networking communication engine with high performance written in C and C++ for PHP. swoole 它是一個用 c++ 所寫的 php extension,一個非常高效能的通訊引擎,而它能達到高效能的基礎在於以下幾個重點 : event-drivent coroutine 一句話來說他可以幹麻。 它可以讓我們建立一個高效能的網路服務 下面就是它實現非阻塞 I/O 的架構圖。 當它建立一個 http server 以後,你會看到產生出下圖這些 process 與 thread,基本上可以分為幾個部份 :
上一篇文章PHP 的 Web 運行原理 ( 2 ) - 非阻塞 I/O 之 Reactor 模式我們理解到實現非阻塞 I/O 的 reactor 模式以後,接下來本篇文章我們將來要說明,在 php 中的 reactor 實現reactPHP。 本篇文章分為以下三個章節 : reactPHP 基本概念 reactPHP 非阻塞 I/O 實現 reactPHP 使用時注意事項 reactPHP 基本概念 reactPHP 官網寫這一段話 : Event-driven, non-blocking I/O with PHP 它是一個用 php 所寫的 libaray,可以幫助我們做以下的事情 : 可以建立一個非阻塞 I/O 的網路服務。 可以建立一個定時排程服務。 http server 的範例 下面就是官網首頁的範例,我們可以用它簡單的建立一個非阻塞 I/O 的 http server,就如同 nodejs 一樣。 $loop = React\EventLoop\Factory::create(); $server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) { return new React\Http\Response( 200, array('Content-Type' => 'text/plain'), "Hello World!
前篇: PHP 的 Web 運行原理 ( 1 ) 上面一篇文章中,我們有提到兩種 php 的 web 運行模式moduel與fast_cgi模式,它們在某種情況下,都會有些問題,而我們這篇文章就是要來理解是碰到什麼問題,然後又是如何解決呢 ? Reactor 模式想解決的問題 Reactor 模式原理 Reactor 的使用注意事項 Reactor 模式想解決的問題 使用 moduel 與 fast_cgi 模式 的 web server 模式基本上會有兩個問題存在。 1. 高併發請求,會爆 ! 如下面這張圖一樣,它每一個 http 請求都需要使用一個 process 或是 thread 來進行處理,而每一台機器的 process 與 thread 的數量都有限制,且操作系統進行 process 或 thread 上文文切換時非常耗的資源。 2. 服務如果是大量 I/O 操作會很浪費資源 ! ex. 讀 db 或 redis 啥的 主要耗資源的地方在於,每個 process 開啟後,大部份的時間者是在等待 I/O 的處理,而 CPU 都是閒在那。 上面兩個是看到的現象,而真正的問題點在於 : 為什麼每個請求都需要開啟一個 process 或 thread 來處理呢 ?
Nodejs 出來時它的官網寫這以下的描述 : Node.js is a JavaScript runtime built on Chrome’s V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js’ package ecosystem, npm, is the largest ecosystem of open source libraries in the world. 簡而言之 Nodejs 是運行在 V8 javascript 引擎,並且使用 Event driven 與 non-blocking I/O 模式所建立出來的東東。 而這裡我們就要深入的來理解 Nodejs 的運行機制。 Nodejs 核心設計 - 非阻塞 I/O 模式 Nodejs 架構與運行 Nodejs 為什麼需要使用 thread ?
socket.io 是一套可以讓我們快速與簡單的建立一套,讓 client 與 server 可以雙向溝通的 Libary,而當我們使用它來建立一個 message server 後,通常在一定的使用量以後,會開始的考慮要加機器來進行擴展,同時間也會建立一台 load balance 的應用來分散請求。 而這時如果你選擇使用AWS ALB (Application Load Balancer)來建立 load balance 你會發現它有個很大的問題,那就是 : 使用非瀏覽器(未處理 cookie )的 client 無法使用 polling 來建立連線 接下來我們將慢慢的來探討原因為何,並且來想想是否有什麼解法呢 ? 本篇文章架構如下 : 原因 解法 原因 為什麼非瀏覽器的 Client 無法使用 polling 來建立連線呢 ? 這裡我們就要先從 socket.io 建立連線的流程開始說啟。 Socket.io 建立連線原理 假設我們在已經在 server 端使用 socket.io 來建立起 message server,然後接下來我們要在 client 端使用socket.io client來建立連線。 var socket = require('socket.io-client')('http://localhost'); 而 socket.io client 這裡主要提供了兩種 transport 讓我們 client 與 server 可以互相的傳遞資料 :
這篇文章雖然主題為PHP 的 Web 運行原理,但是比較白話文的說,事實上是想要理解這件事情 : 一個 http 請求進來後,php 到底是如何運行呢 ? 要理解這件事情,有個最基本的觀念要先理解,那就是下面這段指令,它到底是如何運行的。 php index.php 然後接下來才能在理解 Web 是如何用 php 來處理。 這篇文章將分為以下幾個章節 : 執行 php index.php 它是如何運行的呢 ? 三種用 PHP 來處理 HTTP 的模式 Web PHP 應用組合與問題 執行 php index.php 它是如何運行的呢 ? 假設我們在 Terminal 執行了如下的指令。 php index.php 那實際上它的運行流程會如下圖,而這張圖也代表 PHP 的基本運行架構。 SAPI ( Server Application Programming Interface ) : 它就是一個應用環境與PHP 核心的一個 Interface,會有這層主要的原因在於,不同的應用環境,例如命令行環境(就是在 Terminal 執行 php) 或 Web 環境都需要不同的 PHP 環境配置,如果沒有這一層就代表 PHP 本身要針對不同的環境來考慮設計兼容,這也是為什麼會有 SAPI 的目的。 main : 它是 php 所有操作的整合者。 Zend 引擎 : 它就是將咱們編寫的 PHP 程式碼解釋成可以執行的 opcode 碼,其中 PHP7 與 PHP5 有速度上的飛升原因就在於此,PHP7 大幅度的優化了 Zend 引擎。 Extension : 它是 PHP 內核所提供的一套擴充 PHP 功能的方式,大部份都是使用 C/C++ 所撰寫,基本上可以分為 PHP extension 與 Zend extension。 三種用 PHP 來處理 HTTP 的模式 那如果改成 Web 情況下,上面那張圖會變成什麼樣子呢 ?
什麼是 Laravel Facade ? 在一般情況咱們如果要使用物件的某個方法可能會寫成如下 : <?php $userService = $app->make('UserService'); $userService->createUser(); 但是有時後你會看到如下的程式碼 : <?php UserService::createUser(); 而這就是 Laravel 所提供的 Facade 語法糖,而 Facade 實際上是一種設計模式。 Facade(外觀) 設計模式 Facade 設計模式基本的定義如下 : 定義一個高層級的接口,客戶端只能透過它來與子系統進行溝通。 畫成概念圖大概長的如下,客戶端當要使用某個子系統所提供的功能時,不會直接去使用,而是會透過 Facade 來進行操作。 程式碼範例 假設咱們現在有個功能是用使用 LineSDK 來將訊息推送到 Line 取,然後咱們假設 sdk 的程式碼如下。 <?php interface IMessage { public function push(); } class LineSDK implements IMessage { public function push() { var_dump('I push a message to line'); } } 然後我們這裡會在寫一個 Facade 來讓我們的系統來使用。 <?php class MessageFacade { private $sdk; public function __construct(IMessage $sdk) { $this->sdk = $sdk; } public function push() { $this->sdk->push(); } } 最後這個時候客戶端想要使用時,就會透過 Facade 來進行發送訊息,如下程式碼。
什麼是 Laravel Service Provider ? 上一篇文章『PHP Laravel 的 Container 理解』中咱們學習到了 Laravel 的 Container 是一種用來解決依賴與耦合的概念,它建立了一個容器並且在裡面定義好抽像與實際類別的對應,最後就可以自動的進行依賴性注入。如下偽程式碼。 <?php $containter = require('Container'); // 建立抽象與實體類別的對應 $containter->bind(ILogService, AWSLogServcie::class); $log = $container->make(Log::class); $log->send('log....'); 其中上面的bind就是可以在這個容器內建立一個抽象類別舉實體類別的對應,也就是說如果後來要實體化有實作 ILogService 的類別,那他就會實體化 AWSLogServcie 出來。 那 Service Provider 是什麼 ? 它就個註冊與管理 Container 內服務的地方。 下面的程式碼為 Laravel 專案的 Service Provider,其中有兩個重要的方法boot與register。 register : 它就是用來寫 bind 的地方。 boot : 它就是當 register 結束以後會執行的方法。 <?php namespace App\Providers; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * Bootstrap any application services.
Container 是什麼 ? Laravel Container 是什麼呢 ? 我們先來理解 Container 容器 是什麼。 容器抽象一點概念是指用來裝東西的載體,向菜籃也算個容器,而在 Laravel 中所代表的意思就是指 : 裡面裝了一堆可以用的服務載體,就叫 Container。 像我們每當要執行 Laravel 時,都會先執行下面這段程式碼,其中 $app 就是我們的 Container,然後接下來會使用 Container 來實體化一些物件,例如 $kernel。 <?php public/index.php $app = require_once __DIR__.'/../bootstrap/app.php'; /* |-------------------------------------------------------------------------- | Run The Application |-------------------------------------------------------------------------- | | Once we have the application, we can handle the incoming request | through the kernel, and send the associated response back to | the client's browser allowing them to enjoy the creative | and wonderful application we have prepared for them.
前言 這辛苦的三十天總於結束了,當初原本只是想要理解直播相關協議的東西一下,但是卻發現越來越多奇怪的名詞跑了出來,就算大概的知道 HLS 是要做什麼,但你總是會覺得前後知識好像缺了什麼,別人問你一下沒有 HLS 前是如何處理直播傳輸你大概就會倒了,然後上網查查相關知識,但卻發現總是沒有連貫起來的知識,越看越冒出更多的名詞,這對一名想入門影音直播開發的初學者,真的非常的辛苦。 因此最後就想說當個好人將這方面的知識都整理成一條線好了,因此就產生了這三十篇的文章。 這三十天的文章基本上理解完後,要開發出一個直播應用事實上就不是太難的事情了,而且你有了這三十篇的知識你接下來要將直播應用開發的更好,你就也更有本錢去學習更進階的東西囉。 接下來這篇文章就來總結一下這三十天咱們學習了那些東西。 影音直播開發的 Junior 工程師攻略本 基本上前二十篇是最基礎的東西,這幾篇文章就在說明,如何將一個人的聲音或影像傳遞給對方。。 ! 聲音與影像的採集、編碼與封裝 首先這五篇文章我們學習了聲音與影像是如何的儲放在電腦裡面,並且因為原始的聲音與影像太大,所以我們需要使用編碼來進行壓縮,最後就準備需要將聲音與影像進行封裝,為了可以讓別人一打開來知道要如何處理這一段聲音或影像編碼。 30-02之聲音的採集與原理 30-03之聲音的編碼與壓縮 30-04之影像的採集與原理 30-05之影像的編碼與壓縮 30-06之聲音與影像的封裝 接下來的兩篇文章,咱們就使用 WebRTC 的一些東西,來實作如何的採集聲音與影像,並且最後將它封裝成一個檔案。 30-07之Web 如何進行語音與影像採集 ? 30-08之 WebRTC 採集的詳細說明與聲音的加工 聲音與影像的傳輸 咱們已經可以將聲音與影像封裝後,就可以開始傳輸給遠方的某個人。 我們一開始先探討讓對方收到聲音與影像的方法有那些。 30-09之別人要如何聽到我的聲音呢 ? 接下來花了幾篇文章來理解網路傳輸協議。 30-10之通訊協議的基本常識 30-11之 TCP 與 UDP 協議 30-12之 RTP/RTCP 傳輸協議 30-13之 RTSP 傳輸協議 30-14之 RTMP 傳輸協議 30-15之 HLS 傳輸協議 30-16之 HTTP-FLV 傳輸協議 30-17之 MPEG-DASH 傳輸協議 30-18之影音傳輸協議總整理 在理解完上面幾篇文章以後,我們應該是可以將聲音與影像傳輸給遠方的某個人。
正文開始 上一篇文章中,咱們已經理解了為什麼 P2P 連線如此的困難,接下來這篇文章咱們將要學習: WebRTC 是如何進行打洞與連線呢 ? WebRTC 的打洞流程 ICE WebRTC 它主要使用一個名為ICE ( Interactive Connectivity Establishment ) 的框架來進行打洞,它內部整合了 STUN 與 TURN 協議,下面簡單的說明一下這兩個協議。 STUN ( Session Traversal Utilities for NAT ) 中文為 NAT 對談穿透應用程式,它的最主要用處就是幫助在 NAT 內的用戶找到可以連到它的位置。 STUN-RFC3489 STUN-RFC5389 TURN ( Traversal Using Relay NAT ),它也是一種穿透 NAT 的一樣協議,不過它是使用中繼的方式來進行,通常都是 STUN 的候選位置都無法連線時,才會使用它。 TURN-RFC5766 WebRTC 連線流程 假設目前要連線的雙方情況如下: A 內網位置:192.168.1.1:5555 B 內網位置:10.10.1.1:7777 A 外網位置(經過 NAT 轉換):310.110.1.1:9000 B 外網位置(經過 NAT 轉換):210.210.1.1:7000 TURN Server:111.111.111.111 下圖為示意圖。表示雙方去外部連 Server 時對外的的位置。
正文開始 在開始說明 WebRTC 如何建立 P2P 連線前,咱們要先理解一件事情,那就是 WebRTC 要使用非常多的 P2P 連線技術,那位啥它需要使用如此多的技術呢 ? 那就是本篇文章要探討的主題: 為什麼 P2P 連線很麻煩呢 ? 因為如果你理解了這個問題,你就會知道為什麼 WebRTC 要使用怎麼多的技術來進行 P2P 連線囉,這也是為什麼我們會先說明這篇文章。 本篇文章的問題,為什麼 P2P 的連線會很麻煩呢 ? 最主要的問題在於: NAT 與防火牆的存在。 因此本篇文章將針對這兩個東西來理解 NAT 與防火牆是啥 ? NAT 的運作原理。 為什麼有了 NAT 後 P2P 會很麻煩 ? NAT 的分類。 NAT 與防火牆是啥 ? NAT NAT (Network Address Translation) 中文就做網路位置轉換,它是用來將私網 IP 轉換成公網 IP 的技術。 為啥會有 NAT ? 先說說它的起源。 在咱們世界裡有個叫 IPV4 的地址規則,由於它數量稀少,不可能讓每一台電腦都有一個地址,因此就有了以下的解法如下圖,就是每個家庭或公司只有一組地址,然後公司內的電腦就使用這位置來上網。 其中常用的私有 IP 段為:
正文開始 上一篇文章中,咱們已經學習完了 WebRTC 的一些基本知識,接下來咱們要針對 Signaling Server 這東東來做做一些比較深的的探討。 Signaling Server 要做的事情。 WebRTC 與 SDP。 Signaling Server的實作選擇。 Signaling Server 要做的事情 在上一篇文章,我們大概知道了 Signaling Server 要做的事情,它要做的就是: 在建立 WebRTC 時,讓不認識的雙方可以相互的認識 (也就是知道對方的位置) 順到說一下 WebRTC 並沒有定議 Signaling Server 的標準。 那 Signaling 是如何讓雙方知道對方的位置呢 ? Signaling 是如何讓雙方認識呢 ? 它就像是一個交友仲介商,每當某位用戶要進行聯誼時,用戶會提交一份履歷,這裡面就寫這他家在那,然後有配對到時,就會將這份履歷交給配對者,然後配對者如果覺得可以認識看看,他也會提供一份履歷給 Signaling Server,這樣雙向就可以進行面談了,其中已 Signaling 角度而言,履歷就是指 SDP。 什麼是 SDP ? 下章節在說。 為啥 WebRTC 不建立 Signaling Server 的標準呢 ? 因為事實上要讓兩個瀏覽器能進行溝通,可以不需要 Signaling Server,如果你知道對方在那的情況下,在筆者的『30-10之通訊協議的基本常識』這篇文章中有提到,假設你知道了對方的 port 就代表你可以找到對方電腦內某個應用程式的位置,而你知道了 ip 那就代表你知道對方在那,所以這時你事實上就可以與對方溝通。 WebRTC 與 SDP SDP (Session Description Protocol) 中文叫會話描述協議,在一段會話建立起來前,咱們需要一些建立這會話雙方的資訊,假設 A 與 B 要建立會話,所以這時 A 會發送一個 SDP 給 Signaling,內容包含了 A 的地址、媒體類型、傳輸協議、媒體格式等或是一些它所在的時區資訊,然後 Signaling 會將 A 發送的 SDP 給 B,這樣雙方就知道如何建立連線了。
正文開始 在很前面的文章中,咱們有簡單的介紹如何使用 WebRTC 來採集聲音與影像,但那時只是很簡單的介紹一下而以,所以接下來的幾篇文章,咱們將要來深入的了解 WebRTC。 這篇文章將要介紹幾個 WebRTC 的基概念,大約分成以下幾個章節: WebRTC 的誕生與內部架構。 WebRTC 所支援的語音視編碼與傳輸協議。 WebRTC 提供的基本 P2P 功能。 WebRTC 的簡單通訊實作。 WebRTC 的誕生與內部架構 首先在 Web 通信的世界中,基本上都是所謂的 C/S 架構,也就是所謂的 client 與 server 架構,通常 client 要取資料時就是發送一個請求給 server 然後它會回傳資料回去,其中 ajax 的出現讓我們更能以少量的資源來取得資料,在這階段時都部份都是單向溝通,也就是 client 請求 server。 而在二階段能,人們開始有種需求,例如股票報價網站,人們希望可以看到當有股價變動時,網頁可以也同時更動,這時如果用上面那種模式,那就只能 client 定時的去 server 拿資料,也就是咱們所謂的輪詢,但這種方法很明顯的非常的浪費資源,你可以呼叫 server 十次,但只有一次才真的有新的資料。而這時webSocket就用來解決這向事情,它提供了雙向溝通功能,server 就可以透過它,來將資料推給 client。 基本上以上已經解決了 client 與 server 的雙向互動,但這時人們又在想,假設我是做個一對一的聊天工具,那為什麼還需要 server 呢? 不能直接 client 與 client 進行溝通就好呢 ? WebRTC 就是可以幫助我們完成的工具,它就是用來專門處理瀏覽器與瀏覽器之間的即時溝通。 備註:雖然說是 cleint 與 client 直接進行溝通,但不是說不需要 server,後面會說明。
正文開始 現今大部份的直播咱們要可以與漂亮的直播主姐姐或硬漢大叔進行互動,基本上咱們只能使用文字,也就是所謂的聊天室,而這篇文章咱們將要介紹另一種互動方式,那就是直播連麥,也就是直播主與聽眾可以進行語音溝通,更白話文的是說可以和漂亮姐姐進行語音聊天。這也就是本篇文章的主題。 可以和漂亮姐姐進行語音聊天的難題與方案。 本篇文章將分成兩個章節: 直播連麥的挑戰 直播連麥的架構 直播連麥的挑戰 直播連麥最大的難題就是『 延遲 』問題。 假設我們在一般直播時,以比較低的延遲 2 秒來計算的話 ( 就是主播說話聽眾 2 秒鐘後才能聽到 ),那這樣在直播連麥時會發生什麼事情呢 ? 如下圖所示,直播主說話以後,要經過 4 秒以後才會聽到連麥者的回復,而連麥者也相同的要等 4 秒後才能聽到直播主的回應,你覺得這樣還可以對話嗎 ? 這裡來問個問題。 為什麼直播會延遲呢 ? 基本上可以分四個部份,如下圖。呃下面兩個箭頭算一部份,所以分別為直播主處理、網路傳輸、CDN 與 Media Server 處理、聽眾端處理。 首先第一個部份是直播主 Client 它需要花時間來進行聲音與影像的採集,接下來進行編碼,最後就準備封裝然後準備送貨。 這部份有沒有可以優化的地方呢 ? 基本上可以在編碼上加速,網路上有提到說硬編碼與軟編碼這兩個聽起來很硬東西,其中軟編碼就是使用 CPU 來編碼,而硬編碼就是使用非 CPU 來進行編碼,例如使用 GPU。 而硬編碼效能優於軟編碼,不過需要硬體支援,這方面我沒很熟,請當參考。 第二部份為網路傳輸 只要實用網路進行傳輸,基本上都一定會發生延遲問題,而最主要產生的原因有兩個: 距離。 傳輸時的封包維護。 首先距離是不用說的,直播主離你越遠,它的聲音要傳到你的小耳朵裡,一定比較花時間。 然後第二點是傳輸時的封包維護,在網路傳輸時基本上會發生兩件事情網路抖動與網路掉包。 網路抖動就是你傳送 A、B、C 封包給某個人,但某個人收到的封包為 C、B、A,那這時就要針對這狀態做一些處理,方法可能是緩存等到某段時間後,在根據封包裡面的時間來依順序播放,但緩存那邊就會產生延遲時間囉。 而網路掉包就是你傳送 A、B、C 但實際上對方只收到 A、B,而這時如果是 TCP 的話,它就會一段時間後,會在發送一次封包 C,然後這段時間也就產生延遲囉。
正文開始 上一篇文章中咱們學習完了 CDN 的相關知識以後,接下來這篇文章,我們將要將上一篇所學的來改善咱們以下兩篇文章可動版的架構。 使用 CDN 來調整可動版的架構 30-20之如何建立像 KKTV 一樣的點播功能呢 ? 30-21之如何建立的像 17 一樣的直播功能呢 ? 點播 直播 本篇文章會分成以下幾個章節: 可動版本的問題。 點播的架構改善版本。 直播的架構改善版本。 可動版本的問題 在筆者這篇文章中『30-22之點播與直播可動版問題探討』,我們探討了可動版有以下的問題: 人多時連線數限制問題。 人多時頻寬問題。 人多時效能消耗問題。 遠距離看片卡頓的問題。 基本上 1、3 我們可以用傳統的方法(加機器)來解決,而 2、4 就無法使用加機器來進行解決,因為以 2 的頻寬問題,就算你加了在多的機器,如果你在出去的網路還是在同一條,那頻寬還是沒加大,問題還是沒解決。而 4 的話就更不用說,只能讓使用者離機器更近一點才能解決。 點播架構的改善版本 基本上點播的架構會改成如下圖,它會將 CDN 加上去,而這樣就可幫助我們解決頻寬與距離看片卡頓的問題。 先來說說頻寬的部份, CDN 基本上分散在不同的地方,這也代表這基本上它們的頻寬是各別獨立的,所以不太會發生搶頻寬的問題,而另一點距離的問題,由於大部份的 CDN 都會搭配使用智能 DNS 來幫助找到最近的 CDN,因此可以解決因為離影片來源太遠,而容易造成封包遺失與封包順序不一致問題。 而且用了 CDN 事實上還有一個好處,那就是可以保證接近 100 的機率可以看片,你想想如果是自已建的一台 Media Server 來提供看片,如果它倒了,不就不能看片了,而有 CDN 就可以自動的轉到另一個臨近的 CDN 來取得資料。 接下來說說它的運行流程,基本上如下 (以 HLS 拉流為範例):
正文開始 上一篇文章中,咱們有提到點播與直播可動版本的一些問題,如下所列。 人多時連線數限制問題。 人多時頻寬問題。 人多時效能消耗問題。 遠距離看片卡頓的問題。 接下來咱們要來理解一下,解這上述問題的關鍵技術 CDN 是什麼東西 ? 本編文章將分為以下幾個章節: 什麼是 CDN 呢 ? 它又是用來解決啥呢 ? CDN 的請求運作方式。 使用 AWS CloudFront 來建立 CDN。 什麽是 CDN 呢 ? 它又是用來解決啥呢 ? 在開始理解 CDN 之前,咱們先來說說傳統上一個 client 連線到一個網站的流程。 首先看看下面這張圖,這張圖說明了每當一個 client 發送一個請求到 web 網站時,web 網站會回傳 html、css 與 javascript 回來,這裡假設咱們的 web 網站還在台灣,然後回應時間大約在 100 ms 以內 (假設)。 然後呢 ~ 這時付你錢的老大叫你將 web 網路架設到美國,因爲免費,然後這時發現回應時間變成 1000 ms 左右。 然後開始了有以下的對話 : 老大:回應時間怎麼回事 ? 碼農仔:老大你叫我架到美國啊 !? 老大:我要的不是這回答,而是問你為啥回應時間你沒修改回來 ?
正文開始 前面文章中咱們簡單了可以動的點播 ( like KKTV )與直播 ( like 17 )的功能,那接下來這篇文章主題要探討的目問題為: 這兩篇文章實際上應用會有什麼問題 ? 30-20之如何建立像 KKTV 一樣的點播功能呢 ? 30-21之如何建立的像 17 一樣的直播功能呢 ? 點播可動版架構 直播可動版架構 本篇文章分根據問題分成以下幾個章節: 人多時連線數限制問題。 人多時頻寬問題。 人多時效能消耗問題。 遠距離看片卡頓的問題。 人多時連線數限制問題 咱們都知道,每當 Client 要和 Server 要資料時,如果是以 TCP 傳輸為基礎的,那就一定要建立一條連線,那對 Server 而言連線是啥了 ? 在 unix 中每一個 TCP 連線都要占用一個 file descriptor,而它有一定的限制數量,當使用完後,新的 TCP 連線到來就會發生錯誤以下的錯誤訊息 : Socket/File: Can't open so many files。 那一個 process 我們可以開啟幾個檔案呢 ? 我們可以用以下的指令來看看 : ulimit -n 那這個最大值為多少呢 ? 這個我不確定,像我家用的 Aws Elasticsearch 就有 128000。
正文開始 上一篇文章中,咱們已經學習了如何建立點播這種類型的網站應用,接下咱們要來學學如何建立直播應用。 在筆者的30-09之別人要如何聽到我的聲音呢 ?有提到三種影音的傳遞方式,分別為: 將聲音檔案直接丟給對方 ( 方法 1 ) 將聲音檔案以串流的方式傳送給對方 ( 方法 2 ) 像直播或網路電話一樣即時的將聲音傳送給對方 ( 方法 3 ) 接下來我們將來實作方法 3 的選項,而這東西事實上就是直播網站的應用,像 17 就是這種類型的應用,本篇文章將會說明: 如何建立的像 17 一樣的直播功能呢 (可以動就好版) ? 本篇將分為以下幾個章節: 直播架構原理。 實作 - 建立 Media Server。 實作 - 網頁用戶端取得串流影像。 直播架構原理 直播的架構最基本的如下圖,基本上和點播很相似,只差了直播主推送聲音到 Media Server 這個步驟。 然後基本上推流的協議,應該是只有一種選擇RTMP,網路上看到有人說 HLS 這點我還要待調查,我先打個問號, 然後還有提到 WebRTC 這個可以當推流 (不過它應該不算傳輸協議),這理論上應該是行,這之後 WebRTC 的文章會來聊聊。 而拉流就有不少RTMP、HLS、HTTP-FLV、MPEG-DASH。 老樣子問個問題。 那要選擇那個協議來當拉流呢 ? 首先我覺得要先看你的直播應用是否為互動性很要求的,如果是它就只有兩個選擇 RTMP 與 HTTP-FLV。不過 RTMP 拉流應該會有不少設備無法使用(果粉),所以最後應該會選 HTTP-FLV 吧。 而如果是不會太在意互動性的直播,例如運動賽事直播這種,那選那個,我覺得就看用戶那的支援度吧。
正文開始 前面聲音與影像的基本原理都學習完後,咱們接下來要來實作一些東西。 在筆者的30-09之別人要如何聽到我的聲音呢 ?有提到三種影音的傳遞方式,分別為: 將聲音檔案直接丟給對方 ( 方法 1 ) 將聲音檔案以串流的方式傳送給對方 ( 方法 2 ) 像直播或網路電話一樣即時的將聲音傳送給對方 ( 方法 3 ) 接下來我們將來實作方法 2 的選項,而這東西事實上就是點播網站的應用,像 KKTV、楓林網就是這種類型的應用,本篇文章將會說明: 如何建立的像 KKTV 一樣的點播功能呢 (可以動就好版) ? 先說好,如果真的要建立像 KKTV 一樣的可營運的應用,還需要做不少架構的調整,這裡就是只是學習如何做出可以動的點播網站,也就是可以看片 (不是全部下載完才可以看)。 本篇將分為以下幾個章節: 點播架構原理。 實作 - 建立 Media Server。 實作 - 網頁用戶端取得串流影像。 架構原理 基本上點播的架構,最基本(不管流量或 CDN 這些鬼)的樣貌會如下: 然後基本上可以選擇的協議有RTMP、HLS、HTTP-FLV、MPEG-DASH。 那這裡問個問題 ? 我要選擇那個協議呢 ? 基本上我覺得是要看你的用戶端的裝置取向,基本上以現在的狀態選擇 HLS 與 MPEG-DASH 在點播類的應用,應該是最安穩的,最主要我覺得有以下三個原因: 這兩個都是使用 HTTP 來傳輸,不太會發生有的用戶可以看有的不行。 大部份的平台都可以找到方法支援。 這兩種都有支援依劇網路狀況,來自動調整畫質的功能,這在看影片時尤其有用。 這兩個協議可以去參考筆者的以下兩篇文章。
正文開始 在前面的文章中,咱們咱們已經會了如何將聲音傳送給對方,而接下來這篇文章咱們就要來學習 收到了聲音已後,要如何的播出呢 ? 咱們收到聲音以後(檔案或串流) 那接下來要如何播出了 ? 答案就是使用播放器,而接下來我們就要來介紹大部份播放器的內核ffmpeg。 基本上本篇分成以下的章節來理解 ffmpeg 這好用的東東: ffmpeg 是啥 ? ffmpeg 的基本架構。 ffmpeg 的簡單使用範例。 FFMpeg 是啥 ? 它就是可以幫咱們進行一些影音的奇技淫巧 (ex. 解碼、編碼、轉碼、抽取、串流) FFmpeg (Fast Forward MPEG) 它是一個開源的影音多媒體的火藥庫,有了它我們可以很簡單的將前面幾個章節中提到的採集、編碼、封裝內容給串連起來。 它最核心的應用是當播放器的核心。 前面的章節有提到,我們將一段聲音從麥克風採集下來後,先經過編碼將它縮小,然後在封裝成一個容器,最後在透過網路傳輸協議,將它丟到對方的電腦後,接下要如何處理呢 ? 對方電腦的處理過程如下圖,它會先解析容器,然後進行解碼,最後在輸出聲音到對方的耳機或啥的。 其中處理解析容器與協定,然後再進行解碼的就是咱們電腦中所使用的播放器,像是 KMPlayer、千千靜聽、QuickTime Player,而有不少的播放器裡面都是以 ffmpeg 為內核,像是 KMPlayer 與 QQ 影音。 當然 ffmpeg 還有很多的使用功能,下面簡單的列幾個例子: 它可以將一個影音檔,轉換成多張的圖片與分割出聲音。 它將某個影音檔的編碼轉換成其它的編碼。 它可以將影音檔使用 RTMP 推送到 Server ( 就是可以模擬直播主推聲音到 Server ) 它可以使用 HLS、RTMP 這些傳輸協議將聲音拉下來。 總而言之,它就是個影音軍火庫。 FFMpeg 的基本架構 它事實上是一系列的工具,基本上是由以下幾個組合而成。
正文開始 30-12之 RTP/RTCP 傳輸協議 30-13之 RTSP 傳輸協議 30-14之 RTMP 傳輸協議 30-15之 HLS 傳輸協議 30-16之 HTTP-FLV 傳輸協議) 30-17之 MPEG-DASH 傳輸協議) 前面的幾面文章,咱們學習了各種型的影音傳輸媒體,接下來將會在這一篇文章中,進行這些協議的總結。 各種影音傳輸協議之比較與整理 一張圖來簡單的理解各種協議的運作方式 RTSP RTMP HLS HTTP-FLV MPEG-DASH 特點整理 協議 傳輸層選擇 聲音編碼 影像編碼 延遲性 RTSP RTP、TCP、UDP RTP 可支援的都行 RTP 可支援的東行 低 RTMP TCP AAC、MP3 H.26X 系列 低 HLS TCP (因為它是用 HTTP ) AAC、MP3 H.26X 系列 高 HTTP-FLV TCP (因為它是用 HTTP ) AAC、MP3 H.
正文開始 接下來咱們要來介紹 MPEG-DASH協議。 MPEG-DASH 協議 本篇文章將會分成幾個章節來理解 MPEG-DASH 協議: MPEG-DASH 協議是要用來完成什麼事情呢 ? MPEG-DASH 協議如何完成它想做的事情呢 ? 建立 MPEG-DASH 的串流傳輸流程。 MPEG-DASH 的特點總結。 MPEG-DASH 協議是要用來完成什麼事情呢 ? 讓 client 與 server 可以透過 Http 來進行流媒體的傳輸 嗯事實上它想完成的事情和 HLS 事實上是相同的,那為啥他會誕生出來呢 ? 比較大的問題是 HLS 是由蘋果所主導的協議,而不是國際通用協議,這也代表蘋果怎麼改,其它人也要一起動,也就是說一切蘋果說的算。 因此在 MPEG 的主導下在與一些大廠合作下 MPEG-DASH 這種國際標準的協議就誕生了。 ISO/IEC 23009-1:2012 MPEG-DASH 協議如何完成它想做的事情呢 ? 它將聲音切成一小個一小個檔案,然後 client 就一個一個發 http 去下載。 就如同 HLS 一樣。 建立 MPEG-DASH 的串流傳輸流程 它的基本流程如下圖。 1. 直播主將聲音或影像傳輸到 Server 這裡可以使用 RTMP 來將聲音推收到 Server,又或是如果不是直播情況可以直接將聲音檔例如 .
正文開始 接下來咱們要來介紹 HTTP-FLV 協議。 HTTP-FLV 協議 本篇文章將會分成幾個章節來理解 HTTP-FLV 協議: HTTP-FLV 協議是要用來完成什麼事情呢 ? HTTP-FLV 協議如何完成它想做的事情呢 ? 建立 HTTP-FLV 的串流傳輸流程。 HTTP-FLV 的特點總結。 HTTP-FLV 協議是要用來完成什麼事情呢 ? 可以使用 HTTP 來完成低延遲的串流媒體傳輸。 那為啥他想使用 HTTP 呢 ? 先來說說 RTMP,它不是基於 Http 來進行傳輸,所以他個缺點,那就是有一定的機率被封,而且還有另外一點,通常使用 Http 的來進行傳輸的 html5 會支援的不錯,像在 chrome 比較新的幾個版本就有開始支援 HLS,而當然 RTMP 不支援。 那為啥不用 HLS 呢 ? 使用 HLS 的極大缺點就是它的延遲問題,可能直播主說個話後,大約要 10 秒左右聽眾才可以聽到,而 HTTP-FLV 就是想要解決這件事情。 HTTP-FLV 協議如何完成它想做的事情呢 ? 將聲音與影像封裝成 FLV 流容器,然後在使用 Http 進行流式傳輸。 以直播情況來看,直播主會將聲音用任何方式 ( RTMP 或啥的 ) 傳送到 Server,然後 Server 會將它轉換成 FLV 檔,然後 Client 會使用 Http 來請求這個畫面,請求如下,然後 Server 就會用 Http 流的方式就影像一段一段的傳輸過去。
正文開始 接下來咱們要來介紹 HLS 協議。 HLS 協議 本篇文章將會分成幾個章節來理解 HLS 協議: HLS 協議是要用來完成什麼事情呢 ? HLS 協議如何完成它想做的事情呢 ? 建立 HLS 的串流傳輸流程。 HLS 的延遲問題。 HLS 的特點總結。 HLS 協議是要用來完成什麼事情呢 ? 讓 client 與 server 可以透過 Http 來進行流媒體的傳輸 HLS ( HTTP Live Streaming ) 是由高大尚的蘋果公司所開發,再 HLS 還沒誕生之前,這世界大部份的流媒體傳輸都是被 RTMP 所佔據,最主要的原因在於當時,大部份的電腦都有裝 Flash Player。 而蘋果開發出 HLS 主要有兩個原因: 不想被 Flash 綁死,所以它大部份的設備都慢慢的把 Flash 拔掉(當時)。 RTMP 有個問題就是,它不是透過 HTTP 來進行傳輸,所以它很有可能會被一些防火墻防掉。 HLS 協議如何完成它想做的事情呢 ? 它將聲音切成一小個一小個檔案,然後 client 就一個一個發 http 去下載。
正文開始 接下來咱們要來介紹 RTMP 協議。 RTMP 協議 本篇文章將會分成幾個章節來理解 RTMP 協議: RTMP 協議是要用來完成什麼事情呢 ? RTMP 協議如何完成它想做的事情呢 ? 建立 RTMP 的串流傳輸流程。 RTMP 的特點總結。 RTMP 協議是要用來完成什麼事情呢 ? 它當初的動機為: 在 Flash 平台與伺服器進行串流媒體傳輸的協議 RTMP( Real-Time Messaging Protocol ),為 Adode 所開發,它就是要用來讓 Server 可以與 Flash 平台進行串流傳輸。 這裡問個問題。 為什麼不要用 RTSP 來進行傳輸呢 ? 這裡我覺得有兩個原因: 因為 RTSP 大部份還是基於 RTP over UDP 上,由於當時 RTSP 大部份都用在 IPTV 或 VOD 上這些都是有專門一條線給它用,所以網路很穩定。但是 RTMP 當初是希望開發在互聯網上,所以不能保證網路很穩定,因此它選擇用 TCP 來傳輸。2. 因為想建立一個更符合 Flash 用途的協議。我猜的。 更多有支援的請參考RTMP Spec在 31、32 頁。
正文開始 本篇文章咱們將要開始介紹第一個應用層的流通訊協議 RTSP,別忘了上一篇介紹的 RTP 是傳輸層。 RTSP 協議 本篇文章將會分成幾個章節來理解 RTSP 協議: RTSP 協議是要用來完成什麼事情呢 ? RTSP 協議如何完成它想做的事情呢 ? 建立 RTSP 的串流傳輸流程。 RTSP 的特點。 RTSP 協議是要用來完成什麼事情呢 ? 它是被設計出來為,為了控制串流媒體 Sever 的協議 (ex. 快轉、暫停影片之類) RTSP 它被設計出來是為了可以控制串流媒體伺服器的協議 (所以他是 C/S 架構),例如我們先發送一個觀看影片的請求給 Server,然後它就開始以串流型式來傳輸影片,然後這時我們可以用 RTSP 所提供的一些方法,來進行影片的快轉或暫停,為了能控制串流就是它被設計出來的原理。 就如同下圖所示,RTSP 讓我們可以操控串流媒體。 RTSP 協議如何完成它想做的事情呢 ? 那它要如何控制呢串流呢 ? 它定義了控制的方法與參數 就如同 HTTP 一樣,它定義了一些方法可以給我們控制,例如 Play 這個動作,當串流 Server 看到這個動詞後,就會開始傳輸影片給請求者。 建立 RTSP 的串流傳輸流程 我們直接去使用網路上所提供的 RTSP 進行請求看看。這個連結你可以使用 ffplay 來開啟 (ffplay 之後會提)。
正文開始 在前一篇學習完了 TCP 與 UDP 協議以後,咱們要介紹另一個傳輸層協議: RTP 協議 (RTCP 後來會提到) 本篇文章將會分成幾個章節來理解 RTP 協議: RTP 協議是要用來完成什麼事情呢 ? RTP 協議如何完成它想做的事情呢 ? RTP 協議的基本概念與封包組成。 RTP 要如何進行 Qos 的保證呢 ? RTP 協議是要用來完成什麼事情呢 ? RTP 協議想可以完成『 端點到端點的串流媒體傳輸 』 (ex. 聲音、影像) 它目前廣泛的使用於流通訊領域,例如 VOIP、網路會議,網路電視等。 這裡問個問題,為什麼 RTP 是傳輸層的呢 ? 因為它只是專門用來傳輸串流媒體的協議,而不管實際如何應用。你列出幾個傳輸層應用想完成的事情,大概就可以理解為啥它是傳輸層的。 傳輸層 UDP:傳輸資料 TCP:可靠的傳輸資料 RTP:傳輸多媒體資料 應用層 HTTP:HTTP server 與客戶端的表準應答 RTP 協議如何完成它想做的事情呢 ? 它定義了要傳輸串流媒體的參數標準 (封包標準) RTP 協議它定議好了多媒體傳輸的參數標準,咱們來思考一下,如果直接使用 UDP 或 TCP 來傳送媒體資料會發生什麼事情。 先以簡單的 UDP 為例子,它的封包大約會長的如下:
正文開始 上一文章中咱們理解了每一層通訊協議大約是在做什麼事情以後,咱們這篇文章中將專門來說明,在傳輸層的兩個協議TCP與UDP。 為什麼會選這兩個出來說呢 ? 因為在即時影音傳輸的世界中,這兩個協議常常拿出來進行比較(雖然大部份還是 TCP),而且這兩個是所有資料傳輸的基本,不論是要傳輸文字、檔案、語音都一定會透過這兩個來傳送資料,所以這兩個很重要。 這篇文章的主是題就是: 什麼是 TCP 和 UDP 呢? 這協議到底用來做啥的 ? 接下來會就簡單的分成兩個章節: UDP (User Datagram Protocol) TCP (Transmission Control Protocol) UDP (User Datagram Protocol) 首先我們已經知道協議是用做完成某事件的過程,那 UDP 是想用來做什麼呢 ? 咱們已經知道傳輸層主要是處理應用程式與應用程式如何進行傳輸,而要送到某個應用程式最基本所需要的東西就是 Port。 UDP 就是符合咱們最低需求的東西。 UDP 就是用來傳輸資料到某台電腦中的應用程式 (有沒有收到不用管) 它的封包長的如下。 UDP 封包 = 表頭 + 資料 其中表頭欄位如下,事實上也就只是加上 Port 而以,其中 length 只是用來說明它是資料有多大。 Source Port: 55084 Destination Port: 443 Length: 31 (byte) UDP 注意事項 UDP 的特點就是射後不理,他不會管對方有沒有收到的 (不可靠傳輸)。 它有可能會發生到達順序不一致問題。 Ex.
正文開始 在開始進行流媒體通訊協議前,咱們要先來學習什麼是通訊協議,這個東西沒有學習好,雖然你還是可以幹出一個直播服務器,但就只是做出來,但是當你碰到問題時,或是想要追求更高的效能時,一定卡關。 通訊協議的基本常識 接下來本篇文章會分成以下的章節,為了來理解上面的主題: 什麼是通訊協議呢 ? TCP/IP 通訊協議架構。 從 A 到 B 發送數據的流程。 什麼是通訊協議呢 ? 我相信很多人都已經有使用過很多 http、tcp、udp 這些東東,但是我相信還是有人應該只是懂的在瀏覽器打個 http 網址而以,然後說這就是通訊協議,某些方面不能說錯,但是我相信你這樣說給一個初學者聽一定很難理解的。接下來咱們來理一理到底什麼是通訊協議。 先來理理什麼是協議呢 ? 簡單的用白話文就是: 協議就是 A 與 B 雙方要完成某件事情,所約定好的處理流程。 咱們來舉個例子,假設有位仁兄,雙方住在一間屋子裡面,然後他們只有一把鑰匙,所以這時他們就在思考,一個人已經在房子裡面了,然後另一個回來以後就要敲門,然後在家的人就打開來。 但這時要如何確保敲門的人是室友呢 (先假設看不到外面) ? 如果是壞人敲門你直接開門,那你就準備呵呵呵了,所以 A 與 B 就約定好了一個確認室友協議,這個協議如下: 協議想完成事項:確認對方是不是室友 協議標準: 假設 B 在家,A 在外面。 A 敲 3 下門。 B 聽到後,要求 A 說暗語 (你今天真帥) A 說暗語(你今天真帥) B 收到後,就開門。 先不管上面的協議是否真的實用,只要知道它就是個協議就好囉。 最後所謂的通訊協議就是: 所謂的『 通訊協議 』就是網路上 A 與 B 雙方要進行溝通所約定好流程。