Open Shiou-Ju opened 1 week ago
➜ Repos curl -4 'http://localhost:8080/sum?a=100&b=23'
➜ Repos curl -6 'http://[::1]:8080/sum?a=100&b=23'
{
"sum": 123,
"serverInformation": {
"serverName": "my_actionhero_project",
"apiVersion": "0.1.0",
"requestDuration": 9,
"currentTime": 1730161396544
},
"requesterInformation": {
"id": "6e4f4a03ac6a24baf9202f5a817d0c5068951544-a80eb4e2-fc4a-4b7f-85aa-d16bb4d828ad",
"fingerprint": "6e4f4a03ac6a24baf9202f5a817d0c5068951544",
"messageId": "a80eb4e2-fc4a-4b7f-85aa-d16bb4d828ad",
"remoteIP": "::1",
"receivedParams": {
"a": "100",
"b": "23",
"action": "sum"
}
}
}%
➜ Repos
➜ Repos netstat -an | grep 8080
tcp46 0 0 *.8080 *.* LISTEN
tcp4 0 0 *.8080 *.* LISTEN
➜ Repos lsof -i :8080
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 21239 bamboo 19u IPv4 0xf6ebc2a079917c87 0t0 TCP *:http-alt (LISTEN)
node 59054 bamboo 24u IPv6 0xf6ebc29bae411177 0t0 TCP *:http-alt (LISTEN)
➜ Repos
sudo tcpdump -i lo0 port 8080
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo0, link-type NULL (BSD loopback), capture size 262144 bytes
08:40:00.415418 IP localhost.56109 > localhost.http-alt: Flags [S], seq 4184030234, win 65535, options [mss 16344,nop,wscale 6,nop,nop,TS val 2454897083 ecr 0,sackOK,eol], length 0
08:40:00.415591 IP localhost.http-alt > localhost.56109: Flags [S.], seq 2974487535, ack 4184030235, win 65535, options [mss 16344,nop,wscale 6,nop,nop,TS val 3495734361 ecr 2454897083,sackOK,eol], length 0
08:40:00.415615 IP localhost.56109 > localhost.http-alt: Flags [.], ack 1, win 6379, options [nop,nop,TS val 2454897083 ecr 3495734361], length 0
08:40:00.415630 IP localhost.http-alt > localhost.56109: Flags [.], ack 1, win 6379, options [nop,nop,TS val 3495734361 ecr 2454897083], length 0
08:40:00.415649 IP localhost.56109 > localhost.http-alt: Flags [P.], seq 1:93, ack 1, win 6379, options [nop,nop,TS val 2454897083 ecr 3495734361], length 92: HTTP: GET /sum?a=100&b=23 HTTP/1.1
08:40:00.415674 IP localhost.http-alt > localhost.56109: Flags [.], ack 93, win 6378, options [nop,nop,TS val 3495734361 ecr 2454897083], length 0
08:40:00.428735 IP localhost.http-alt > localhost.56109: Flags [P.], seq 1:152, ack 93, win 6378, options [nop,nop,TS val 3495734374 ecr 2454897083], length 151: HTTP: HTTP/1.1 404 Not Found
08:40:00.428766 IP localhost.56109 > localhost.http-alt: Flags [.], ack 152, win 6377, options [nop,nop,TS val 2454897096 ecr 3495734374], length 0
08:40:00.428926 IP localhost.56109 > localhost.http-alt: Flags [F.], seq 93, ack 152, win 6377, options [nop,nop,TS val 2454897096 ecr 3495734374], length 0
08:40:00.428949 IP localhost.http-alt > localhost.56109: Flags [.], ack 94, win 6378, options [nop,nop,TS val 3495734374 ecr 2454897096], length 0
08:40:00.429018 IP localhost.http-alt > localhost.56109: Flags [F.], seq 152, ack 94, win 6378, options [nop,nop,TS val 3495734374 ecr 2454897096], length 0
08:40:00.429049 IP localhost.56109 > localhost.http-alt: Flags [.], ack 153, win 6377, options [nop,nop,TS val 2454897096 ecr 3495734374], length 0
^C
12 packets captured
2860 packets received by filter
0 packets dropped by kernel
sudo tcpdump -i lo0 port 8080
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo0, link-type NULL (BSD loopback), capture size 262144 bytes
08:37:27.686724 IP6 localhost.54809 > localhost.http-alt: Flags [S], seq 715042300, win 65535, options [mss 16324,nop,wscale 6,nop,nop,TS val 3167191331 ecr 0,sackOK,eol], length 0
08:37:27.686875 IP6 localhost.http-alt > localhost.54809: Flags [S.], seq 3849887279, ack 715042301, win 65535, options [mss 16324,nop,wscale 6,nop,nop,TS val 3312198690 ecr 3167191331,sackOK,eol], length 0
08:37:27.686888 IP6 localhost.54809 > localhost.http-alt: Flags [.], ack 1, win 6371, options [nop,nop,TS val 3167191331 ecr 3312198690], length 0
08:37:27.686901 IP6 localhost.http-alt > localhost.54809: Flags [.], ack 1, win 6371, options [nop,nop,TS val 3312198690 ecr 3167191331], length 0
08:37:27.691014 IP6 localhost.54809 > localhost.http-alt: Flags [P.], seq 1:878, ack 1, win 6371, options [nop,nop,TS val 3167191335 ecr 3312198690], length 877: HTTP: GET /sum?a=100&b=23 HTTP/1.1
08:37:27.691115 IP6 localhost.http-alt > localhost.54809: Flags [.], ack 878, win 6358, options [nop,nop,TS val 3312198694 ecr 3167191335], length 0
08:37:27.700446 IP6 localhost.54810 > localhost.http-alt: Flags [S], seq 2454154044, win 65535, options [mss 16324,nop,wscale 6,nop,nop,TS val 1694074242 ecr 0,sackOK,eol], length 0
08:37:27.700593 IP6 localhost.http-alt > localhost.54810: Flags [S.], seq 2013867277, ack 2454154045, win 65535, options [mss 16324,nop,wscale 6,nop,nop,TS val 1554486417 ecr 1694074242,sackOK,eol], length 0
08:37:27.700611 IP6 localhost.54810 > localhost.http-alt: Flags [.], ack 1, win 6371, options [nop,nop,TS val 1694074242 ecr 1554486417], length 0
08:37:27.700620 IP6 localhost.http-alt > localhost.54810: Flags [.], ack 1, win 6371, options [nop,nop,TS val 1554486417 ecr 1694074242], length 0
08:37:27.706376 IP6 localhost.http-alt > localhost.54809: Flags [P.], seq 1:946, ack 878, win 6358, options [nop,nop,TS val 3312198709 ecr 3167191335], length 945: HTTP: HTTP/1.1 200 OK
08:37:27.706417 IP6 localhost.54809 > localhost.http-alt: Flags [.], ack 946, win 6357, options [nop,nop,TS val 3167191350 ecr 3312198709], length 0
08:37:28.553746 IP6 localhost.54810 > localhost.http-alt: Flags [F.], seq 1, ack 1, win 6371, options [nop,nop,TS val 1694075096 ecr 1554486417], length 0
08:37:28.553763 IP6 localhost.54809 > localhost.http-alt: Flags [F.], seq 878, ack 946, win 6357, options [nop,nop,TS val 3167192198 ecr 3312198709], length 0
08:37:28.553803 IP6 localhost.http-alt > localhost.54810: Flags [.], ack 2, win 6371, options [nop,nop,TS val 1554487271 ecr 1694075096], length 0
08:37:28.553816 IP6 localhost.http-alt > localhost.54809: Flags [.], ack 879, win 6358, options [nop,nop,TS val 3312199557 ecr 3167192198], length 0
08:37:28.554176 IP6 localhost.http-alt > localhost.54810: Flags [F.], seq 1, ack 2, win 6371, options [nop,nop,TS val 1554487271 ecr 1694075096], length 0
08:37:28.554214 IP6 localhost.54810 > localhost.http-alt: Flags [.], ack 2, win 6371, options [nop,nop,TS val 1694075096 ecr 1554487271], length 0
08:37:28.554322 IP6 localhost.http-alt > localhost.54809: Flags [F.], seq 946, ack 879, win 6358, options [nop,nop,TS val 3312199557 ecr 3167192198], length 0
08:37:28.554343 IP6 localhost.54809 > localhost.http-alt: Flags [.], ack 947, win 6357, options [nop,nop,TS val 3167192198 ecr 3312199557], length 0
^C
20 packets captured
415 packets received by filter
0 packets dropped by kernel
我將 bindIP: "::",
設成 bindIP: "0.0.0.0",
[ERROR] 08:54:15 Error: cannot start web server @ 0.0.0.0:8080 => Error: listen EADDRINUSE: address already in use 0.0.0.0:8080
2024-10-29T00:54:15.122Z - notice: stopping process...
2024-10-29T00:54:15.224Z - notice: Stopping server: web
2024-10-29T00:54:15.224Z - notice: Stopping server: websocket
2024-10-29T00:54:15.434Z - notice: *** my_actionhero_project Stopped ***
進程即將退出,退出碼:1
並且看了
netstat -anv | grep 8080
tcp4 0 0 *.8080 *.* LISTEN 131072 131072 21239 0 0x0100 0x00000106
原來 8080 已經有在聽了。
所以是這邊:
[INFO] 08:55:20 ts-node-dev ver. 2.0.0 (using ts-node ver. 10.9.2, typescript ver. 5.6.3)
正在啟動 Actionhero 進程...
sum action constructor initialized
2024-10-29T00:55:20.820Z - info: creating routes automatically for all actions responding to GET HTTP verb
2024-10-29T00:55:20.821Z - info: creating routes automatically for all actions responding to POST HTTP verb
2024-10-29T00:55:20.853Z - notice: pid: 45812
2024-10-29T00:55:20.853Z - notice: environment: development
2024-10-29T00:55:20.853Z - info: *** Starting my_actionhero_project ***
2024-10-29T00:55:20.859Z - info: actionhero member 192.168.8.140 has joined the cluster
2024-10-29T00:55:20.859Z - notice: Starting server: `web` @ http://:::8080
2024-10-29T00:55:20.862Z - notice: Starting server: `websocket`
2024-10-29T00:55:20.878Z - notice: server ID: 192.168.8.140
2024-10-29T00:55:20.878Z - notice: *** my_actionhero_project Started ***
Actionhero 進程已成功啟動
他應該要出現類似 0.0.0.0 但是沒有出現
[ERROR] 08:54:15 Error: cannot start web server @ 0.0.0.0:8080 => Error: listen EADDRINUSE: address already in use 0.0.0.0:8080
如果 v4 的 port 已經被 listen,他的訊息仍然會一樣
log 給使用者 還是直接 當成 error 比較好?
// Which IP to listen on (use '0.0.0.0' for the default ip stack; '::' for all on ipv4 and ipv6)
// Set to `null` when listening to socket
bindIP: "::",
// bindIP: "0.0.0.0",
如果我這邊選擇使用 v4&&v6 一起,那麼 eg. 8080 已經被使用了,那麼我的行為應該是 warn 或是 throw error 讓程序退出呢?
看規格書、協定。
錯誤
根據您的描述,當您將 bindIP
設置為 "::"
(同時監聽 IPv4 和 IPv6),但端口 8080
已經被 IPv4 使用時,伺服器在啟動時遇到了衝突。您想了解在這種情況下,伺服器應該是給出警告並繼續運行(僅監聽 IPv6),還是應該拋出錯誤並退出程序。
從規範和協議的角度來看,以下是對此問題的分析:
綁定失敗的處理方式:按照 POSIX 規範和網絡編程的慣例,如果伺服器無法綁定到指定的 IP 地址和端口(例如因為端口已被佔用),應該拋出錯誤並退出。這是因為伺服器未能滿足預期的網絡接口需求。
一致性和預期行為:開發人員和系統管理員通常預期伺服器在無法正確啟動時會退出,從而提示他們檢查問題。如果僅僅是給出警告並繼續運行,可能會導致伺服器僅在 IPv6 上監聽,從而導致部分客戶端無法連接,這可能難以及時察覺。
影響客戶端連接:如果伺服器僅在 IPv6 上監聽,而大部分客戶端仍然使用 IPv4,這將導致大量客戶端無法連接到伺服器,影響服務的可用性。
清晰的錯誤反饋:通過拋出錯誤並退出程序,能夠明確地告知系統管理員存在問題,需要立即處理。這比僅僅給出警告更能引起重視,避免長時間的服務不可用。
故障即失敗(Fail Fast):在軟體工程中,「故障即失敗」是一種最佳實踐,即當系統發生錯誤時,應該盡快停止運行並報告錯誤,避免在不完整或不可靠的狀態下繼續運行。
避免隱藏問題:如果伺服器繼續運行但未能完全提供預期的服務,可能會隱藏問題,導致更大的影響。拋出錯誤並退出可以避免這種情況。
基於以上考量,建議在伺服器無法綁定到指定的 IP 地址和端口時,拋出錯誤並退出程序。這樣可以:
在啟動時檢查端口佔用情況:在伺服器啟動時,可以增加對端口佔用情況的檢查,並提供更加友好的錯誤信息,指出是 IPv4 還是 IPv6 端口被佔用。
提供配置選項:如果有需要,您可以提供一個配置選項,允許高級用戶選擇在特定情況下僅監聽 IPv6,但默認行為應該是拋出錯誤並退出。
日誌記錄:確保在錯誤日誌中詳細記錄綁定失敗的原因,方便問題的排查和解決。
希望以上分析能夠幫助您做出決策。
[INFO] 13:19:12 ts-node-dev ver. 2.0.0 (using ts-node ver. 10.9.2, typescript ver. 5.6.3)
正在啟動 Actionhero 進程...
sum action constructor initialized
2024-10-29T05:19:13.151Z - info: creating routes automatically for all actions responding to GET HTTP verb
2024-10-29T05:19:13.152Z - info: creating routes automatically for all actions responding to POST HTTP verb
2024-10-29T05:19:13.188Z - notice: pid: 74494
2024-10-29T05:19:13.188Z - notice: environment: development
2024-10-29T05:19:13.188Z - info: *** Starting my_actionhero_project ***
2024-10-29T05:19:13.191Z - info: actionhero member 192.168.8.140 has joined the cluster
2024-10-29T05:19:13.192Z - notice: Starting server: `web` @ http://0.0.0.0:8080
2024-10-29T05:19:13.195Z - warning: [server: web] port 8080 is being used by ipv4
2024-10-29T05:19:13.196Z - emerg: Uncaught Exception stack=Error: cannot start web server @ 0.0.0.0:8080 => Error: listen EADDRINUSE: address already in use 0.0.0.0:8080
at Server.<anonymous> (/Users/bamboo/Repos/number-a-b-guess-game/node_modules/actionhero/dist/servers/web.js:149:23)
at Server.emit (node:events:519:28)
at emitErrorNT (node:net:1940:8)
at processTicksAndRejections (node:internal/process/task_queues:82:21)
[ERROR] 13:19:13 Error: cannot start web server @ 0.0.0.0:8080 => Error: listen EADDRINUSE: address already in use 0.0.0.0:8080
2024-10-29T05:19:13.196Z - notice: stopping process...
2024-10-29T05:19:13.298Z - notice: Stopping server: web
2024-10-29T05:19:13.298Z - notice: Stopping server: websocket
2024-10-29T05:19:13.523Z - notice: *** my_actionhero_project Stopped ***
進程即將退出,退出碼:1
error Command failed with signal "SIGINT".
[INFO] 13:49:06 ts-node-dev ver. 2.0.0 (using ts-node ver. 10.9.2, typescript ver. 5.6.3)
正在啟動 Actionhero 進程...
sum action constructor initialized
2024-10-29T05:49:07.335Z - info: creating routes automatically for all actions responding to GET HTTP verb
2024-10-29T05:49:07.335Z - info: creating routes automatically for all actions responding to POST HTTP verb
2024-10-29T05:49:07.365Z - notice: pid: 80189
2024-10-29T05:49:07.366Z - notice: environment: development
2024-10-29T05:49:07.366Z - info: *** Starting my_actionhero_project ***
2024-10-29T05:49:07.369Z - info: actionhero member 192.168.8.140 has joined the cluster
2024-10-29T05:49:07.369Z - notice: Starting server: `web` @ http://:::8080
2024-10-29T05:49:07.374Z - error: Error from Initializer name=servers file=/Users/bamboo/Repos/number-a-b-guess-game/node_modules/actionhero/dist/initializers/servers.js type=start stack=Error: IPv4 port 8080 is already in use
at WebServer.start (/Users/bamboo/Repos/number-a-b-guess-game/node_modules/actionhero/dist/servers/web.js:112:23)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at Servers.start (/Users/bamboo/Repos/number-a-b-guess-game/node_modules/actionhero/dist/initializers/servers.js:81:17)
at startFunction (/Users/bamboo/Repos/number-a-b-guess-game/node_modules/actionhero/dist/classes/process.js:115:29)
at Process.start (/Users/bamboo/Repos/number-a-b-guess-game/node_modules/actionhero/dist/classes/process.js:195:17)
at main (/Users/bamboo/Repos/number-a-b-guess-game/src/server.ts:27:5)
2024-10-29T05:49:07.374Z - notice: stopping process...
2024-10-29T05:49:07.476Z - notice: Stopping server: web
2024-10-29T05:49:07.476Z - notice: Stopping server: websocket
2024-10-29T05:49:07.689Z - notice: *** my_actionhero_project Stopped ***
啟動 Actionhero 進程時發生錯誤: Error: IPv4 port 8080 is already in use
at WebServer.start (/Users/bamboo/Repos/number-a-b-guess-game/node_modules/actionhero/dist/servers/web.js:112:23)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at Servers.start (/Users/bamboo/Repos/number-a-b-guess-game/node_modules/actionhero/dist/initializers/servers.js:81:17)
at startFunction (/Users/bamboo/Repos/number-a-b-guess-game/node_modules/actionhero/dist/classes/process.js:115:29)
at Process.start (/Users/bamboo/Repos/number-a-b-guess-game/node_modules/actionhero/dist/classes/process.js:195:17)
at main (/Users/bamboo/Repos/number-a-b-guess-game/src/server.ts:27:5) {
data: {
name: 'servers',
file: '/Users/bamboo/Repos/number-a-b-guess-game/node_modules/actionhero/dist/initializers/servers.js',
type: 'start',
stack: 'Error: IPv4 port 8080 is already in use\n' +
' at WebServer.start (/Users/bamboo/Repos/number-a-b-guess-game/node_modules/actionhero/dist/servers/web.js:112:23)\n' +
' at processTicksAndRejections (node:internal/process/task_queues:95:5)\n' +
' at Servers.start (/Users/bamboo/Repos/number-a-b-guess-game/node_modules/actionhero/dist/initializers/servers.js:81:17)\n' +
' at startFunction (/Users/bamboo/Repos/number-a-b-guess-game/node_modules/actionhero/dist/classes/process.js:115:29)\n' +
' at Process.start (/Users/bamboo/Repos/number-a-b-guess-game/node_modules/actionhero/dist/classes/process.js:195:17)\n' +
' at main (/Users/bamboo/Repos/number-a-b-guess-game/src/server.ts:27:5)'
},
code: 'FATAL_ACTIONHERO_ERROR'
}
✨ Done in 1.26s.
GPT 整理
描述:
在使用 Actionhero 框架開發的應用中,當通過瀏覽器訪問
http://localhost:8080/sum?a=100&b=23
時,請求能夠正常響應並返回預期的 JSON 結果。然而,使用curl
發送相同的請求卻返回 404 Not Found 錯誤,無法獲取到預期的數據。重現步驟:
啟動伺服器:
瀏覽器請求:
http://localhost:8080/sum?a=100&b=23
使用
curl
發送 GET 請求:使用
curl
發送 POST 請求:預期行為:
curl
發送的請求應該與瀏覽器中的請求類似,返回相同的 200 OK 狀態和預期的 JSON 數據。實際行為:
curl
請求返回 404 Not Found 錯誤,無法獲取到預期的數據。環境: