2017年7月21日星期五

ASP.NET Core 正確發佈至CentOS/Apache & 解決Service Unavailable Error 503

若跟著Microsoft的教學文件,建立ASP.NET Core Project後,上傳至Apache後,應該都會跑得動。
但當你做了若干修改後,即使在本機以IISExpress運作得完美無瑕,
再次發佈可能都得以出現Http Error 503 - Service Unavailable
用GEdit打開Error log,Error message如下:

Long Term Support (LTS) releases are -

[Thu Jul 20 17:54:50.534863 2017] [proxy:error] [pid 1283] (111)Connection refused: AH00957: HTTP: attempt to connect to 127.0.0.1:5000 (127.0.0.1) failed
[Thu Jul 20 17:54:50.535276 2017] [proxy:error] [pid 1283] AH00959: ap_proxy_connect_backend disabling worker for (127.0.0.1) for 60s
[Thu Jul 20 17:54:50.535289 2017] [proxy_http:error] [pid 1283] [client 10.3.15.246:61490] AH01114: HTTP: failed to make connection to backend: 127.0.0.1



很自然就會Copy了上述幾句Google Search,得出的結果都是大概是(未打開SELinux, Firewall/iptables設置問題等等..)

如果依照這個方向去想,搞幾天都不會有什麼改變。
因為原因根本不是Apache的問題。

試試重新啟動Apache和Service,看一下Status就知道了。
[root@localhost ~]# service httpd restart
Redirecting to /bin/systemctl restart  httpd.service
[root@localhost ~]# service httpd status
Redirecting to /bin/systemctl status  httpd.service
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since 四 2017-07-20 17:24:39 HKT; 26s ago
     Docs: man:httpd(8)
           man:apachectl(8)
  Process: 1251 ExecStop=/bin/kill -WINCH ${MAINPID} (code=exited, status=1/FAILURE)
 Main PID: 3206 (httpd)
   Status: "Total requests: 4; Current requests/sec: 0.4; Current traffic: 307 B/sec"
   CGroup: /system.slice/httpd.service
           ├─3206 /usr/sbin/httpd -DFOREGROUND
           ├─3207 /usr/sbin/httpd -DFOREGROUND
           ├─3208 /usr/sbin/httpd -DFOREGROUND
           ├─3209 /usr/sbin/httpd -DFOREGROUND
           ├─3210 /usr/sbin/httpd -DFOREGROUND
           └─3211 /usr/sbin/httpd -DFOREGROUND

再看看ASP.NET Core的Service Status,找到問題原因,就是Service出現問題。
[root@localhost ~]# systemctl status kestrel-skincv.service
● kestrel-skincv.service - ASP.NET Core Application running on CentOS 7
   Loaded: loaded (/etc/systemd/system/kestrel-skincv.service; enabled; vendor preset: disabled)
   Active: activating (auto-restart) (Result: exit-code) since 四 2017-07-20 17:25:08 HKT; 6s ago
  Process: 3242 ExecStart=/usr/local/bin/dotnet /var/aspnetcore/skincv/SkinCV.dll # Restart service after 10 seconds if dotnet service crashes (code=exited, status=217/USER)
 Main PID: 3242 (code=exited, status=217/USER)

7月 20 17:25:08 localhost.localdomain systemd[1]: kestrel-skincv.service: main process exited, code=exited, status=217/USER
7月 20 17:25:08 localhost.localdomain systemd[1]: Unit kestrel-skincv.service entered failed state.
7月 20 17:25:08 localhost.localdomain systemd[1]: kestrel-skincv.service failed.

由另一個角度看,下圖的Firefox Developer Tool所見,Response headers中的Server是"Apache/2.4.6 (CentOS) OpenSSL/1.0.1e-fips",如果ASP.NET正常執行的話,應該會是"Kestrel"才對。


其實可以藉此了解一下ASP.NET Core是如何運作,為什麼我們要設定Apache的reverse proxy server。
Microsoft上有圖文並茂的解釋 -


經過一輪研究,我發現原來可以手動執行方式起動,指令如下:
[root@localhost ~]# /usr/local/bin/dotnet /var/aspnetcore/skincv/SkinCV.dll
錯誤訊息出現:
A fatal error was encountered. 
The library 'libhostpolicy.so' required to execute the application was not found in '/var/aspnetcore/skincv'.

受到Error Message引導,我又花了半天去研究什麼是"libhostpolicy.so",在這裡就略過過程,最後知道其實一開始就已經做錯了。

根本原因就是我的project.json中的runtimes,只有"win10-x86"和"win10-x64",那CentOS呢?
我們需要做的就是加入CentOS的RID (Runtime IDentifier)
請參考官方文件: .NET Core Runtime IDentifier (RID) catalog
CentOS的RID是"centos.7-x64"。
"runtimes": {
    "win10-x86": {},
    "win10-x64": {},
    "centos.7-x64": {}
  },

然後在Project Folder中打開CMD,輸入Command "dotnet publish -c release -r centos.7-x64"
C:\Users\SamSung\Documents\Visual Studio 2015\Projects\SkinCV\src\SkinCV>dotnet publish -c release -r centos.7-x64
Publishing SkinCV for .NETCoreApp,Version=v1.0/centos.7-x64
Bundling with configuration from C:\Users\SamSung\Documents\Visual Studio 2015\Projects\SkinCV\src\SkinCV\bundleconfig.json
Processing wwwroot/css/site.min.css
  Bundled
  Minified
Processing wwwroot/js/site.min.js
Project SkinCV (.NETCoreApp,Version=v1.0) will be compiled because inputs were modified
Compiling SkinCV for .NETCoreApp,Version=v1.0

Compilation succeeded.
    0 Warning(s)
    0 Error(s)

Time elapsed 00:00:14.3891842

Configuring the following project for use with IIS: 'C:\Users\SamSung\Documents\Visual Studio 2015\Projects\SkinCV\src\SkinCV\bin\release\netcoreapp1.0\centos.7-x64\publish'
Updating web.config at 'C:\Users\SamSung\Documents\Visual Studio 2015\Projects\SkinCV\src\SkinCV\bin\release\netcoreapp1.0\centos.7-x64\publish\web.config'
Configuring project completed successfully
publish: Published to C:\Users\SamSung\Documents\Visual Studio 2015\Projects\SkinCV\src\SkinCV\bin\release\netcoreapp1.0\centos.7-x64\publish
Published 1/1 projects successfully
但你會發現不再是發佈去"bin\Release\PublishOutput"資料夾,而是去了"bin\Release\netcoreapp1.0\centos.7-x64\publish",並多出了很多*.so檔案。
最後把全部檔案上傳至Apache,再次使用systemctl起動kestrel-skincv.service就OK了。

同時在VS Publish視窗中,都多了之前沒有的CentOS 7選項。


或者你想用VS2015的Publish功能,但我自己就出現了Error:

Could not find a part of the path 'C:\Users\SamSung\documents\visual studio 2015\Projects\SkinCV\src\SkinCV\bin\Release\netcoreapp1.0\centos.7-x64\SkinCV.dll'

這似乎是已知而未解決的問題 (Stackoverflow - Error “Could not find a part of the path” while publishing .NET Core Application

沒有留言:

發佈留言