duanjiaolia97750 2018-05-15 13:16
浏览 27
已采纳

如何与大猩猩Mux建立无状态连接?

My program are running fine with one connection per time, but not with concurrent connections.

I need all connections being rendered by one function, which will have all data I need in my service, and that is not working fine, so I ilustrated with the simple code below:

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)
}

If you run this code, you won't see anything wrong in one connection per time, but if you run it in another tab/browser/etc, at same time, because of the delay, the status code will not be from 1 to 10, but it will be shuffled with all calls.

So I guess that means it's not stateless, and I need it to be, so even with 300 connections at same time, it will always return status code from 1 to 10 in each one.

How can I do it? (As I said, it's a simple code, the structure and the render functions are in separeted packages from each other and of all data collection and)

  • 写回答

3条回答 默认 最新

  • dongzhoulong1797 2018-05-16 16:51
    关注

    First I would like to thanks ThunderCat and Ramil for the help, yours answers gave me a north to find the correctly answer.

    A short answer is: Go don't have stateless connections, so I can't do what I was looking for.

    Once that said, the reason why I think (based on RFC 7230) it doesn't have is because:

    • In a traditional web server application we have a program that handle the connections (Apache, nginx etc) and open a thread to the routed application, while in Go we have both in same application, so anything global are always shared between connections.
    • In languages that may work like Go (the application that opens a port and stay listen it), like C++, they are Object Oriented, so even public variables are inside a class, so you won't share it, since you have to create an instance of the class each time.

    Create a thread would resolve the problem, but Go don't have it, instead it have Goroutines, more detail about it in:

    https://translate.google.com/translate?sl=ko&tl=en&u=https%3A%2F%2Ftech.ssut.me%2F2017%2F08%2F20%2Fgoroutine-vs-threads%2F

    After days on that and the help here, I'll fix it changing my struct to type and put it local, like that:

    package main
    
    import (
        "encoding/json"
        "fmt"
        "github.com/gorilla/mux"
        "github.com/rs/cors"
        "net/http"
        "reflect"
        "time"
    )
    
    type 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) {
        localOut := Out{0,nil}
    
        // 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++ {
            localOut.Code = localOut.Code + 1
            localOut.Message = append(localOut.Message, "Running...")
            time.Sleep(1000 * time.Millisecond)
    
            if err := json.NewEncoder(w).Encode(localOut)
            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{"X-Session-Token","Content-Type"},
            AllowedMethods: []string{"GET","POST","PUT","DELETE"},
        }).Handler(r)
    
        fmt.Println("Working in localhost:5000")
        http.ListenAndServe(":5000", handler)
    }
    

    Of course that will take some weeks, so for now I put my application behind nginx and now it works as expected.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 基于卷积神经网络的声纹识别
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题