为什么没有一个 Golang 的WSGI 实现?

24
我们在Python中有并发问题。这些WSGI服务器并不那么出色。我查看了一下,没有找到像Golang编写的带有goroutine的WSGI服务器。
有什么原因吗?

2
WSGI是Python Web服务器的规范。 - Marcelo Cantos
无法使用Golang编写Python Web服务器? - fengsp
什么对你不起作用?你是在问为什么Go服务器比Python更好吗? - jwalker
Go语言拥有goroutine,它比greenlet快得多,所以想知道为什么不使用goroutine实现一个WSGI服务器... - fengsp
为什么有人想要在 Python 应用程序中使用 Go 服务器?如果你不喜欢 Python 服务器,为什么不改用 C 呢? - jwalker
@fsp:小小的挑剔:Greenlets 本身并不慢。相比之下,Python 相对于 Go 来说才是慢的。 - Marcelo Cantos
3个回答

37

WSGI协议是Python特有的。对于Go,您有三个选项(实际上是四个,但普通的CGI不应被认为适用于中高负载设置):

  • Go标准库中的内置HTTP提供设施

    在这种情况下,您的应用是一个独立的服务器。这可能是最简单的设置,但可能会有以下问题:

    • 要在特权端口号(低于1024,80在此范围内)上使用专用包装器或POSIX功能以降级权限运行应用程序,您必须这样做。
    • 为了提供优雅的重部署而不丢失连接,您需要另一个包装器(例如goagain)。
  • 与以上相同,但在反向HTTP代理后面,以Web服务器的形式。

    大多数情况下,消除了独立变体的问题,但仍具有传递完整HTTP流量的开销。

  • 通过合适的Web服务器使用FastCGINginxApache(以及众多其他)都可以使用。Go标准库中有FCGI客户端实现

    除了没有独立设置的问题之外,还实现了更高效的数据交换协议。另一个优点是,您的Go服务器可能使用Unix管道与前端Web服务器通信,这比反向HTTP代理变体涉及的TCP套接字具有更少的传输成本。

因此,如果您的设置当前使用了WSGI,我建议选择FCGI

¹ 正如几位评论者指出的那样,严格来说,这并不完全正确:WSGI允许将用任何语言编写的Web应用程序与Web服务器或应用程序服务器(反过来连接到Web服务器)解耦。
为了实现这一点,双方必须使用相同的协议WSGI,该协议是与语言无关的。 然而,似乎大多数非Python编写的软件都会使用HTTP或FastCGI与前端服务器通信。


更新于2020-11-19

正如Andrea Citrolo在他们的评论中正确指出的那样,在当前普遍存在容器化的情况下,当您部署多个相同服务的副本,并需要对它们进行负载平衡时,使用纯HTTP通常是唯一的选择。

我还要补充的是,如果您打算将用Go编写的程序暴露在互联网上(这很好),则应阅读此文


++ 对于超出问题本身的有用回答。 - twotwotwo
1
你的建议是基于基准测试吗?我猜内置方法(通过goagain)很容易就能胜过FastCGI - 但在做决定之前,我更愿意看到具体数据。在一个网站上,Go HTTP是某个特定基准测试的当前领导者(http://www.techempower.com/benchmarks/),最近超越了JVM的表现。 - Rick-777
1
@Rick-777,不幸的是,我没有硬数据来支持我的说法。 我关于更有效的数据交换协议的评论是在比较FastCGIHTTP反向代理 - 我同意您的观点,独立服务器应该是所有解决方案中最快的。 - kostix
1
WSGI[1] 不是服务器、Python 模块、框架、API 或任何类型的软件。它只是一个接口规范,用于服务器和应用程序之间的通信。服务器和应用程序接口的两侧都在 PEP 3333 中指定。如果应用程序(或框架或工具包)按照 WSGI 规范编写,则可以在任何按照该规范编写的服务器上运行。 - programaths
1
@kostix,值得指出的是,如果目标是通过容器化运行多个Go服务副本(几乎任何人现在都可能这样做),那么选项二是正确的选择。 - Andrea Citrolo
显示剩余2条评论

3
虽然Go本身可能不支持WSGI协议,但uWSGI是一个相当流行的WSGI服务器,具有对Go的支持。目前看来支持有限且更新不频繁,但这可能值得研究。

默认情况下,uWSGI Go插件支持http.DefaultServeMux处理程序,因此如果您的应用程序已经基于它,那么在uWSGI中运行它应该非常简单。

以下示例改编自uWSGI文档:

package main

import (
    "uwsgi"
    "net/http"
    "fmt"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "<h1>Hello, World!</h1>")
}

func main() {
    http.HandleFunc("/hello/", helloHandler)
    uwsgi.Run()
}

1
uwsgi并不是你想象中的那样。我很惊讶人们会点赞这个回答。uwsgi是一个多用途工具,可以运行多种脚本语言或编译语言。它与手头的问题几乎没有关系。 你发布的示例将使用uwsgi运行go程序。因此,您可以使用uwsgi.Run()代替http.ListenAndServe()。 uwsgi就像一个适配器,可以让你插入不同的语言。 WSGI是一种协议。uwsgi只共享"wsgi"这几个字母。 这就像说香蕉和芭蕉是一样的,如果你需要保姆,你应该买香蕉。这是不合适的。 - user2312578
@dalu 现在重新阅读这个问题,1.5年后,我发现我误解了问题。我知道uwsgi是什么,现在我看到OP实际上是在问是否有一个用Go编写的WSGI服务器(可以运行Python WSGI应用程序)。 - korylprince

3

这里有一个Go WSGI服务器:

http://bitbucket.org/classroomsystems/wsgi

然而,它的目的不是为了使Python服务器更快 - 它运行单个带有GIL的CPython解释器。我编写它是为了在我们的产品从Python移动到Go时,为我的客户提供平稳的过渡。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接