gpt4 book ai didi

go - 如何与 gorilla 复用器建立无状态连接?

转载 作者:数据小太阳 更新时间:2023-10-29 03:31:37 25 4
gpt4 key购买 nike

我的程序在每次一个连接的情况下运行良好,但在并发连接的情况下就不行。

我需要由一个函数呈现所有连接,该函数将包含我在服务中需要的所有数据,但效果不佳,因此我用下面的简单代码进行了说明:

package main

import (
"encoding/json"
"fmt"
"github.com/gorilla/mux"
"github.com/rs/cors"
"net/http"
"reflect"
"time"
)

var Out struct {
Code int `json:"status"`
Message []interface{} `json:"message"`
}

func Clear(v interface{}) {
p := reflect.ValueOf(v).Elem()
p.Set(reflect.Zero(p.Type()))
}

func YourHandler(w http.ResponseWriter, r *http.Request) {
Clear(&Out.Message)
Out.Code = 0

// w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers","Content-Type,access-control-allow-origin, access-control-allow-headers")
w.WriteHeader(http.StatusOK)

for i:=0; i<10; i++ {
Out.Code = Out.Code + 1
Out.Message = append(Out.Message, "Running...")
time.Sleep(1000 * time.Millisecond)

if err := json.NewEncoder(w).Encode(Out)
err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
}

func main() {
r := mux.NewRouter()
r.StrictSlash(true);

r.HandleFunc("/", YourHandler)

handler := cors.New(cors.Options{
AllowedOrigins: []string{"*"},
AllowCredentials: true,
Debug: true,
AllowedHeaders: []string{"Content-Type"},
AllowedMethods: []string{"GET"},
}).Handler(r)

fmt.Println("Working in localhost:5000")
http.ListenAndServe(":5000", handler)
}

如果你运行这段代码,你不会在每次一个连接中看到任何错误,但如果你同时在另一个选项卡/浏览器/等中运行它,由于延迟,状态代码将不会从 1 到 10,但它会随着所有调用而随机播放。

所以我想这意味着它不是无状态的,我需要它,所以即使同时有 300 个连接,它也总是会在每个连接中返回从 1 到 10 的状态代码。

我该怎么做? (正如我所说,这是一个简单的代码,结构和渲染函数在彼此独立的包中以及所有数据收集和)

最佳答案

处理程序由 net/http 同时调用服务器。服务器为每个客户端连接创建一个 goroutine,并在这些 goroutine 上调用处理程序。

Gorilla Mux 在并发方面是被动的。无论调用 mux 的 goroutine,mux 都会调用已注册的应用程序处理程序。

使用 sync.Mutex限制一次只能执行一个 goroutine:

var mu sync.Mutex

func YourHandler(w http.ResponseWriter, r *http.Request) {
mu.Lock()
defer mu.Unlock()

Clear(&Out.Message)
Out.Code = 0
...

考虑到处理程序中的 time.Sleep 调用,这不是一个好的解决方案。服务器每 10 秒最多处理一个请求。

更好的解决方案是将 Out 声明为处理程序函数内的局部变量。有了这个改变,这里就不需要互斥量或清除 Out:

func YourHandler(w http.ResponseWriter, r *http.Request) {

var Out struct {
Code int `json:"status"`
Message []interface{} `json:"message"`
}


// w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.Header().Set("Access-Control-Allow-Origin", "*")
...

如果无法移动 Out 的声明,则将值复制到局部变量:

func YourHandler(w http.ResponseWriter, r *http.Request) {
Out := Out // local Out is copy of package-level Out
Clear(&Out.Message)
Out.Code = 0
...

关于go - 如何与 gorilla 复用器建立无状态连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50351263/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com