在 wsl 下使用 swoole 膠水專案 laravels 艱辛的問題求解之路

dreamfish發表於2019-09-04
前提概要

有一個新專案由於未知原因專案載入速度很慢 不清楚是不是 laravel 框架的原因,畢竟效能一直是它的軟肋。不管是怎麼配置優化 甚至直接寫了一個最簡單的路由到頁面輸出 hello word,問題還是依舊,頁面的載入時間都需要 1s 多。

有問題自然是要想辦法解決,這時候 laravels出現了。經過一番肉搏,測試結果頁面載入速度提升到了 100 - 200 ms。不過我還沒來的及高興多久,各種問題就接踵而至。


問題一 :

使用 laravel-menu 生成的選單會無限新增,簡直可以長到突破天際。

檢視文件發現,這是因為 單例問題 swoole 會在導致資料無線新增,要新增方法自己清理一下。

問題二 :

問題一解決還沒高興多久,問題二又來了。這次將是一個很曲折的故事。

問題概要:

當頁面過大或者介面返回的資料過的的時候 其實也有很大,也就不到1Mswoole 會出現無法返回資料的情況。而且沒過多久整個專案就 504 奔潰了。

解決過程

遇到問題不可怕,只要嘗試解決問題就好了。首先我檢視了php , nginx , swoole 的日誌檔案,沒有發現任何報錯資訊。接著配置了一個沒有使用 laravels 的域名地址,發現一切正常。

這時候基本可以確定你是 laravels 的問題,接著來到 laravels 的專案地址,檢視其他人是否遇到相同問題,並諮詢了專案作者 作者還是很 nice 的響應很快 ,也給了很多建議,然而問題還是沒有解決。 加了 laravels qq交流群,諮詢了很多大佬,得到的結構還是一樣,問題到這裡絲毫沒有進展。

當然這不是完全一無所獲,至少我可以確定我碰到的問題是非常小眾的問題。我開始懷疑是我使用的開發環境的問題。

在 github 上輸入 wsl swoole,我在 swoole/swoole-src#2386 看到了一條這樣的資訊,原來是 wsl1swoole 確實返回資料過大,會出現程式會掛起問題。

有了新的突破口,還是很開心的。不過我不知道,這只是新一輪問題求解的開始。


wsl2 安裝

wsl 安裝說明

按照教程使用 wsl --set-version Ubuntu-16.04 2 ,出現沒有相關命令的提示。

wsl -h 看了一下,果真沒有這條命令。

看了下文件 請注意,需要執行 Windows 10 版本 18917 或更高版本才能使用 WSL 2,並且需要已安裝 WSL(可在此處找到有關執行此操作的說明)
原來是系統版本太低了,只能更新到最新的預覽版才行。
百度一下更新預覽系統教程,經過一個上午的耕耘,終於更新到了最新的版本。

重新 wsl --set-version Ubuntu-16.04 2,滿懷期待的以為會成功。結果出現 正在進行轉換,這可能需要幾分鐘時間... 有關與 WSL 2 的主要區別的資訊,請訪問 https://aka.ms/wsl2 連到系統上的裝置沒有發揮作用。 的報錯。 這什麼鬼?重複測試了多次結果還是一樣。

以為是以前安裝的 wsl 無法直接切換 版本 ,檢視了文件後 wsl --set-default-version 2 重新安裝 ,結果出現 Installing, this may take a few minutes... WslRegisterDistribution failed with error: 0x8007001f Error: 0x8007001f ??????????????? Press any key to continue...


這時候 wsl1 版本是可以正常使用的。

https://github.com/microsoft/WSL 上查詢了很久也沒找到好的解決方法。

問題到這,幾乎已經到了山窮水盡的地步了(經過再次測試,此處問題是系統沒有更新完成,需要再多重啟幾次)。

不經過我還是沒有放棄,我還在思考我的問題到底出在哪裡。

回到家,坐到馬桶上我思考了半個小時。在第三次全軍出擊的提示聲中,我想到了一種可能。我是直接升級到最新的系統版本的,是不是系統還殘留有一些原來系統的設定導致了新的功能不能使用。

第二天一到公司,果斷使用重置系統的功能。再又經過了半天的肉搏後,我成功將 wsl 升級到了 wsl2


到這裡,我以為一切都要結束了。
到了熟悉的配置開發環境的環節。

當我配置好一切,輸入久違的域名的時候。我竟然看到了,域名無法訪問。一臉懵逼中!!!!

經過這麼多年的環境配置磨練,我相信我的配置是沒有問題的。那麼問題就是出在 wsl2 上面的了。


檢視文件文件發現 wsl2 的域名規則和 wsl1 。已經不一樣了

當使用遠端 IP 地址連線到應用程式時, 它們將被視為來自區域網 (LAN) 的連線。 這意味著你將需要確保你的應用程式可以接受 LAN 連線, 例如:你可能需要將應用程式繫結到0.0.0.0 , 127.0.0.1而不是。 例如, 在 python 中使用 flask, 可以使用以下命令完成此app.run(host='0.0.0.0')操作:。 進行這些更改時, 請牢記安全, 因為這將允許來自 LAN 的連線。

修改 nginx 配置,將 listen 80; 修改為 listen 0.0.0.0:80; 重啟 nginx

到這個時候前面的提到的問題 當頁面過大或者介面返回的資料過的的時候 其實也有很大,也就不到1M, swoole 會出現無法返回資料的情況。而且沒過多久整個專案就 504奔潰了,終於解決了。


你以為問題到這裡就全部結束了?

其實還遠遠沒有結束。這時候你會發現,當你想用 navicat 連線資料庫的時候,原來正常的配置會報錯 2003 - Can’t connect to MySQL server on ******* (10060 "Unknown error ")

Laravel

原因自然和前面一樣 127.0.0.1 ,已經無法訪問子系統資料庫了。

解決方法:

    //修改配置
    sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf 

    bind-address =127.0.0.1
    //修改為
    bind-address = 0.0.0.0

    //重啟mysql
    sudo service mysql restart

    // 檢視當前 wsl 系統IP
    ifconfig

    // 複製 eth0 -> inet addr: 後面的地址 作為訪問資料庫的地址

Laravel

這時候就可以正常通過 navicat 訪問 wsl2 的資料庫了。

注意:

wsl2 每次重啟後 IP 都會變化,所以每次重啟後都需要重新設定一次 navicat

wsl2 每次重啟後 IP 都會變問題解決方案

每次重啟都要重新修改 nginx ,mysql等等和 IP 相關的配置檔案,會顯得非常麻煩。不過有問題肯定就有解決方法。 有個大神 edwindijas 寫了個指令碼解決這個問題。 相關連線https://github.com/microsoft/WSL/issues/41...

//指令碼

$remoteport = bash.exe -c "ifconfig eth0 | grep 'inet '"

$found = $remoteport -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';

if( $found ){

  $remoteport = $matches[0];

} else{

  echo "The Script Exited, the ip address of WSL 2 cannot be found";

  exit;

}

#[Ports]

#All the ports you want to forward separated by coma

$ports=@(80,443,10000,3000,5000);

#[Static ip]

#You can change the addr to your ip config to listen to a specific address

$addr='0.0.0.0';

$ports_a = $ports -join ",";

#Remove Firewall Exception Rules

iex "Remove-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' ";

#adding Exception Rules for inbound and outbound Rules

iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Outbound -LocalPort $ports_a -Action Allow -Protocol TCP";

iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Inbound -LocalPort $ports_a -Action Allow -Protocol TCP";

for( $i = 0; $i -lt $ports.length; $i++ ){

  $port = $ports[$i];

  iex "netsh interface portproxy delete v4tov4 listenport=$port listenaddress=$addr";

  iex "netsh interface portproxy add v4tov4 listenport=$port listenaddress=$addr connectport=$port connectaddress=$remoteport";

}

exit 0;

可以設定一個開機任務。每次開機自動執行該指令碼。這樣不用每次都手動執行。

執行後就可以像 wsl1127.0.0.1 訪問 nginx,mysql 了。

有夢想的鹹魚

相關文章