首頁 >後端開發 >Python教學 >如何使用Nginx + UWSGI

如何使用Nginx + UWSGI

巴扎黑
巴扎黑原創
2017-04-05 14:56:181482瀏覽

  經過大量的實驗(在 disqus.com和 getsentry.com上),我可以確切的說:uwsgi應該成為Python世界的標準。 把它和nginx結合,在基於 Python的Web應用程式上你能獲得在執行緒(或非執行緒)之上更好的效能體驗。

更新:忽略古老的說法“你給任何度量是慢”,我在這裡說的請求是指後端節點,他們處理輸入事件(從20KB到1MB大小的請求),在網絡跳過數跳經過各種授權和配額策略,並最形成一些佇列操作。卸載盡可能多的工作負載。 (本段翻譯有問題,請參考原文,譯者註)

 服務策略

  目前已經有相當數量的方法可以用來運行Python應用程式。我不打算使用mod_wsgi,最重要的,我並不想說明事件模型如何運作。我不相信在Python的世界它們依舊使用,所以這篇文章的主題也不是關於傳統的線程(或多進程)的Python應用程式。

  相反,我將專注於兩個最受歡迎且我最熟悉的解決方案:gunicorn和uwsgi。

 Gunicorn(Python UNIX平台的wsgi伺服器)

#   回顧過去,Python的Web伺服器的解決方案基本上只有mod_wsgi。其中最受歡迎的(或理解為時尚)的方法是最近Gunicorn。

  實際上,我仍然建議使用gunicorn,這樣可以極大的減少不便:它可以漂亮的嵌入Django而且設定簡單。

它也有10%的配置選項和uwsgi一致(這對某些人來說是件好事),除此之外,比較看來,它提供了與uwsgi(或任何其他Python Web伺服器)幾乎相同的基本特性。

 uwsgi

  在我看來這是唯一的選擇,從Gunicorn到uwsgi。將會有更高性能的,有更多極易明白的配置選項,透過協定可以與nginx互動也增加了優勢。
它的配置也是相當簡單,找到一篇文章相關文章就可以了,後來更多。
我開始使用uwsgi來跑一些應用,使用–processes=10和–threads=10來測試伺服器的多CPU,目的有兩個:

  • 支援情況


  • # 測試降低記憶體使用量的可能性


  • # 測試線程安全的支援情況

  (對於這些測試是否值得,DISQUS是 單線程運行的,我想保持盡可能的精簡,把每個節點的能力發揮到極致)

#  不斷趨向成功的迭代

#   我們讓API平均回應時間降到40ms以內,我非常自豪。這裡我說的API對應時間是指:從請求擊中了Python伺服器到伺服器回傳回應到代理所花費的時間。

不幸的是,當我們始獲得越來越大的流量並出現訪問尖峰後響應時間出現問題了,波動的響應時間不再符合我們開始的設想,儘管服務節點上我們仍然有大約30%的內存和60%的資源空餘。

  在不少調整後,我們停用了大量uwsgi進程的方法,讓nginx的負載平衡它們(之前是讓uwsgi本身負載平衡)。

  這意味著什麼呢,是不是做uwsgi過程= 10,我們運行10個單獨的uwsgi實例代替–processes=10。

  其結果是一個美麗的,一致的20ms的平均反應時間。

#   API回應時間

#  將他們組合在一起

  我喜歡著手去做而非空談,這裡我給大家一些我們在線伺服器的實際設定。

 nginx

  配置的第一塊是Nginx的,我們需要實際計算並添加uwsgi的進程 後端數量,所以事情有點複雜。

  我們首先建立在我們的網頁配置清單:

# recipes/web.rb

hosts = (0..(node[:getsentry][:web][:processes] - 1)).to_a.map do |x|
  port = 9000 + x
  "127.0.0.1:#{port}"
end

template "#{node['nginx']['dir']}/sites-available/getsentry.com" do
  source "nginx/getsentry.erb"
  owner "root"
  group "root"
  variables(
    :hosts => hosts
  )
  mode 0644
  notifies :reload, "service[nginx]"
end

  Nginx的設定很簡單:

# templates/getsentry.erb

upstream internal {
<% @hosts.each do |host| %>
  server <%= host %>;
<% end %>
}

server {
  location / {
    uwsgi_pass         internal;

    uwsgi_param   Host                 $host;
    uwsgi_param   X-Real-IP            $remote_addr;
    uwsgi_param   X-Forwarded-For      $proxy_add_x_forwarded_for;
    uwsgi_param   X-Forwarded-Proto    $http_x_forwarded_proto;

    include uwsgi_params;
  }
}

#   現在,我們已經設定了uwsgi的主機數量並分配了權重值,從9000埠開始,它們都是被uwsgi配置使用的套接字位址。

 uwsgi

  另一方面,我們使用supervisor來控制uwsg進程,這也非常簡單:

# recipes/web.rb

command = "/srv/www/getsentry.com/env/bin/uwsgi -s 127.0.0.1:90%(process_num)02d --need-app --disable-logging --wsgi-file getsentry/wsgi.py --processes 1 --threads #{node[&#39;getsentry&#39;][&#39;web&#39;][&#39;threads&#39;]}"

supervisor_service "web" do
  directory "/srv/www/getsentry.com/current/"
  command command
  user "dcramer"
  stdout_logfile "syslog"
  stderr_logfile "syslog"
  startsecs 10
  stopsignal "QUIT"
  stopasgroup true
  killasgroup true
  process_name &#39;%(program_name)s %(process_num)02d&#39;
  numprocs node[&#39;getsentry&#39;][&#39;web&#39;][&#39;processes&#39;]
end

 位置的選擇

  除非有人想出了一個非常有說服力的論點:為什麼應該有另一種方式(或某種該情形下不能工作的情況),我希望能聽到這種模式因為Python的世界變得更標準。最起碼,我希望看到關於如何提高uwsgi內進程管理的一些辯論的火花。 ###

以上是如何使用Nginx + UWSGI的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn