如何在VPS Windows Server上部署Golang
如何在VPS Windows Server上部署Golang 我使用Go运行一个Web应用程序,我的代码运行正常,但在CMD中运行2到3小时后,我收到这个错误并且服务器停止了。
操作系统:Windows Server 2012 R2 Standard
C:\Users\Administrator\Desktop\Go\vt>go run main.go Service is running 2020/04/06 23:17:59 write tcp (我的服务器IP):8080->(奇怪的IP): wsasend: 您主机中的软件中止了一个已建立的连接。 exit status 1
这是我的代码:
我的 index.html:
更多关于如何在VPS Windows Server上部署Golang的实战教程也可以访问 https://www.itying.com/category-94-b0.html
请使用以下行(作为第一行)来让日志记录器输出产生错误的行。
log.SetFlags(log.LstdFlags | log.Lshortfile)
更多关于如何在VPS Windows Server上部署Golang的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这个错误通常是由于客户端异常断开连接导致的,但服务器不应该因此崩溃。以下是几种解决方案:
1. 添加连接错误处理
修改你的HTTP服务器代码,添加连接状态的错误处理:
package main
import (
"fmt"
"log"
"net/http"
"time"
)
func main() {
// 创建自定义的HTTP服务器,配置连接参数
server := &http.Server{
Addr: ":8080",
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 设置超时时间
r.Context().Done()
http.ServeFile(w, r, "index.html")
}),
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 30 * time.Second,
MaxHeaderBytes: 1 << 20,
}
fmt.Println("Service is running on port 8080")
// 启动服务器并处理错误
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Printf("Server error: %v\n", err)
}
}
2. 使用goroutine恢复panic
添加全局的panic恢复机制:
package main
import (
"fmt"
"log"
"net/http"
"runtime/debug"
)
func main() {
// 创建带panic恢复的handler
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
log.Printf("Recovered from panic: %v\n%s", err, debug.Stack())
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
}()
http.ServeFile(w, r, "index.html")
})
fmt.Println("Service is running on port 8080")
if err := http.ListenAndServe(":8080", handler); err != nil {
log.Printf("Server failed: %v\n", err)
}
}
3. 生产环境部署建议
对于Windows Server生产环境,建议:
package main
import (
"context"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
func main() {
// 创建文件日志
logFile, err := os.OpenFile("server.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
log.Fatal(err)
}
defer logFile.Close()
log.SetOutput(logFile)
server := &http.Server{
Addr: ":8080",
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "index.html")
}),
ReadTimeout: 15 * time.Second,
WriteTimeout: 15 * time.Second,
IdleTimeout: 60 * time.Second,
}
// 优雅关闭
done := make(chan bool, 1)
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-quit
log.Println("Server is shutting down...")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
log.Fatalf("Could not gracefully shutdown the server: %v\n", err)
}
close(done)
}()
fmt.Println("Service is running on port 8080")
log.Println("Server started on port 8080")
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("Could not listen on port 8080: %v\n", err)
}
<-done
log.Println("Server stopped")
}
4. 编译为可执行文件运行
不要使用go run,而是编译后运行:
# 编译
go build -o myserver.exe main.go
# 运行
myserver.exe
5. 创建Windows服务
使用sc命令创建Windows服务:
# 安装为服务
sc create MyGoWebService binPath= "C:\path\to\myserver.exe" start= auto
# 启动服务
sc start MyGoWebService
主要问题是你的服务器没有正确处理客户端异常断开连接的情况。第一种方案添加了连接超时设置,第二种方案添加了panic恢复机制,第三种方案是完整的生产环境部署方案。建议使用第三种方案,并编译为可执行文件运行。


