所有应用程序都应该具备的基本网络调整

huangapple go评论87阅读模式
英文:

Basic web tweaks that all applications should have

问题

目前我的Web应用程序只是一个路由器和处理程序。

有哪些重要的东西我忽略了,以使其适合生产环境?

  1. 我相信我必须设置goroutine的最大数量以确保使用最大的goroutine?

  2. 我应该使用输出缓冲吗?

还有其他任何你认为缺失的最佳实践吗?

var (
  templates = template.Must(template.ParseFiles("templates/home.html"))
)

func main() {
  r := mux.NewRouter()
  r.HandleFunc("/", WelcomeHandler)

  http.ListenAndServe(":9000", r)
}

func WelcomeHandler(w http.ResponseWriter, r *http.Request) {
    homePage, err := api.LoadHomePage()
    if err != nil {
    }
    tmpl := "home"
	renderTemplate(w, tmpl, homePage)
}

func renderTemplate(w http.ResponseWriter, tmpl string, hp *HomePage) {

	err := templates.ExecuteTemplate(w, tmpl+".html", hp)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

以下是翻译好的代码部分:

var (
  templates = template.Must(template.ParseFiles("templates/home.html"))
)

func main() {
  r := mux.NewRouter()
  r.HandleFunc("/", WelcomeHandler)

  http.ListenAndServe(":9000", r)
}

func WelcomeHandler(w http.ResponseWriter, r *http.Request) {
    homePage, err := api.LoadHomePage()
    if err != nil {
    }
    tmpl := "home"
	renderTemplate(w, tmpl, homePage)
}

func renderTemplate(w http.ResponseWriter, tmpl string, hp *HomePage) {

	err := templates.ExecuteTemplate(w, tmpl+".html", hp)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}
英文:

Currently my web app is just a router and handlers.

What are some important things I am missing to make this production worthy?

  1. I believe I have to set the # of procs to ensure this uses maximum goroutines?

  2. Should I be using output buffering?

Anything else you see missing that is best-practise?

var (
  templates = template.Must(template.ParseFiles("templates/home.html")
)

func main() {
  r := mux.NewRouter()
  r.HandleFunc("/", WelcomeHandler)

  http.ListenAndServe(":9000", r)
}

func WelcomeHandler(w http.ResponseWriter, r *http.Request) {
    homePage, err := api.LoadHomePage()
    if err != nil {
    }
    tmpl := "home"
	renderTemplate(w, tmpl, homePage)
}

func renderTemplate(w http.ResponseWriter, tmpl string, hp *HomePage) {

	err := templates.ExecuteTemplate(w, tmpl+".html", hp)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

答案1

得分: 1

  1. 你不需要设置/更改runtime.GOMAXPROCS(),因为自从Go 1.5版本以来,默认值已经设置为可用CPU核心的数量。

  2. 输出缓冲?从性能角度来看,你不需要。但是可能有其他考虑因素。

例如,你的renderTemplate()函数可能会发生恐慌。如果执行模板开始写入输出,它会在写入数据之前设置HTTP响应代码和其他标头。如果在此之后发生模板执行错误,它将返回一个错误,因此你的代码会尝试发送一个错误响应。此时HTTP标头已经被写入,而这个http.Error()函数将尝试再次设置标头=>恐慌。

避免这种情况的一种方法是首先将模板渲染到缓冲区(例如bytes.Buffer),如果模板执行没有返回错误,然后你可以将缓冲区的内容写入响应写入器。如果发生错误,当然你不会写入缓冲区的内容,而是像你之前做的那样发送一个错误响应。

总之,从性能角度来看,你的代码已经准备好投入生产(不包括处理模板执行错误的方式)。

英文:
  1. You don't need to set/change runtime.GOMAXPROCS() as since Go 1.5 it defaults to the number of available CPU cores.

  2. Buffering output? From the performance point of view, you don't need to. But there may be other considerations for which you may.

For example, your renderTemplate() function may potentially panic. If executing the template starts writing to the output, it involves setting the HTTP response code and other headers prior to writing data. And if a template execution error occurs after that, it will return an error, and so your code attempts to send back an error response. At this point HTTP headers are already written, and this http.Error() function will try to set headers again => panic.

One way to avoid this is to first render the template into a buffer (e.g. bytes.Buffer), and if no error is returned by the template execution, then you can write the content of the buffer to the response writer. If error occurs, then of course you won't write the content of the buffer, but send back an error response just like you did.

To sum it up, your code is production ready performance-wise (excluding the way you handle template execution errors).

答案2

得分: 0

  1. err != nil 为真时,WelcomeHandler 应该返回。
  2. 如果遇到错误,记录错误以帮助调查。
  3. templates = template.Must(template.ParseFiles("templates/home.html")) 放在 init 中。将其拆分为单独的行。如果 template.ParseFiles 返回错误,则进行 Fatal 日志记录。如果有多个模板需要初始化,则使用共享的 WaitGroup 在 goroutine 中初始化它们,以加快启动速度。
  4. 由于你正在使用 mux,了解 HTTP Server is too clean with its URLs 也可能是一个好主意。
  5. 你可能还想重新考虑让用户知道为什么会收到 http.StatusInternalServerError 响应的决定。
  6. 如果你有多个核心,将 GOMAXPROCS 设置为大于 1 绝对是一个好主意,但我会将其保持在可用核心数量以下。
英文:
  1. WelcomeHandler should return when err != nil is true.
  2. Log the error when one is hit to help investigation.
  3. Place templates = template.Must(template.ParseFiles("templates/home.html") in the init. Split it into separate lines. If template.ParseFiles returns an then error make a Fatal log. And if you have multiple templates to initialize then initialize them in goroutines with a common WaitGroup to speed up the startup.
  4. Since you are using mux, HTTP Server is too clean with its URLs might also be good to know.
  5. You might also want to reconsider the decision of letting the user's know why they got the http.StatusInternalServerError response.
  6. Setting the GOMAXPROCS > 1 if you have more the one core would definitely be a good idea but I would keep it less than number of cores available.

huangapple
  • 本文由 发表于 2016年4月24日 05:04:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/36816412.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定