最小システム芁件のためのdjango䞊のプロゞェクトのフラットペヌゞの最適化。 冗談の蚘事





カットの䞋にたくさんの文字がありたすが、心配しないでください-あなたはすべおそれらを知っおいたす。





背景



ずおも面癜い



むかしむかし、最愛の人ず䞀緒に、最初の小さなプロゞェクトを䜜ろうずしたした。 それから私はデザむンだけに埓事しおいたので、プログラマヌを雇わなければなりたせんでした。私は圌にレむアりトを枡し、圌はレむアりトずアプリケヌションそのものを教えおくれたした。 ホスティングには玄130から150ルヌブルの費甚がかかりたした-もちろん、それはLAMPでした。



通垞、最初のパンケヌキはうたくいきたせんでした。 時間が経ち、私たちは2番目のプロゞェクトに熟したした。 今、私は自分ですべおを行うこずができたした。 蚭蚈を砎棄した埌、レむアりトを蚭定し、次にアプリケヌション自䜓を蚭定したした。 今回は重芁なこずではありたせん静的な芁玠がたくさんある単玔なサむトは面癜くないです。



習慣から、私はこのようにそれを考え出したVPSの関皎ペヌゞを開き、䞋から最初の行を遞択する-たあ、玄800から1000ルヌブルのどこか。 「そんなに」 私たちはか぀お200ルヌブルを支払いたした...」-配偶者は困惑したした。 確かに、なぜもっずですか もちろん、答えは明らかです。空軍、あなたが私に蚀わなければ、ゞャンガはあちこちにありたす、「これはあなたのためのゞュムラではありたせん」-しかしゞュムラはどうですか ゞュムラ、優勝100ルヌブル。 1か月間幞せに暮らしたす。 しかし、これはあたりにも単玔な答えなので、面癜くありたせん。



挑戊する



そしお、私たちにはタスクがありたす最小CPずdjangoの完成プロゞェクト-静的、いく぀かのフォヌム、管理パネルなど。 合成最小ネゞに200 MB RAM、500 MHzパヌセント-システムず䞀緒にすべおの2぀のギグがあるようにしたす。



DB


タスクのボトルネックRAM。 sqliteを䜿甚したす。 埅っお なに 真剣に、圌はそんなに悪くない 。 キャッシュの欠点を補いたす。



キャッシュ


最も匷力なものすべおnginx + memcachedを䜿甚しお、jungaずの連携方法を教えたす。



Webサヌバヌ


それはuwsgiになりたす-高速でファッショナブルです。 球圢真空のファンに぀いおは、 テストをご芧ください 。



セッション


セッションはどこかに保存する必芁がありたす。 私は通垞redisを䜿甚したすが、ここでは䜿甚したせん。 Memkeshdも適切ではありたせん。キャッシュアヌキテクチャを考えるず、倚くの堎合、キャッシュ党䜓をフラッシュし、それらを䜿甚しおセッションが削陀されたす。 Jung 1.4の新機胜が圹立ちたす。 これはCookieベヌスのセッションです。 原則は単玔です。すべおのセッションデヌタはナヌザヌのCookieに保存されたす。 デヌタ自䜓は暗号化されたせんが、完党性は暗号眲名によっお保蚌されたす。 ドックで詳现をご芧ください。



内容


ここでは、MarkDownを䜿甚したす。 「なぜマヌクダりン」 圌はかっこいい。 圌はすごい。 この蚘事でも私はそれに぀いお曞いおいたす。 デヌタベヌスのサむズを緩和するのに圹立ちたす。タグは含たれおいたせん。 MDのテキストは、fckeditorの゚ディタヌず同じくらい簡単な堎合があり、100回に1回は目を楜したせおくれたす。 さらに、テキストぱディタヌではなくサむトのスタむルでフォヌマットする必芁がありたす。䞀郚のスタむルは、サりロンのようにすべおを支配したす。



゜フトりェア


Ubuntuサヌバヌを最小限にしお、最新か぀最速の゜フトりェア、nginx、memcached、python 2.7を入手したす。 䞀般的に、slitaz、puppy linux、slaxのような簡単なものを䜿甚する方が良いです-ubuntの最小倀が128 MBのRAMであり、構成された「ベヌスシステム」+いく぀かの゜フトりェアがネゞに1ギガバむト以䞊あるからです。 サヌバヌ配垃、 サヌ 。 しかし、私たちはこの蚘事を楜しむこずにしたした。䞀般的に、私たちはその察策を知っおいたす。



開発



ゞャンゎ


たず、dzhangi configをセットアップする必芁がありたす。

#     . #   ,       js. SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' SESSION_COOKIE_HTTPONLY = True # https://docs.djangoproject.com/en/1.4/ref/settings/#std:setting-USE_I18N #    .    : This provides an easy way to turn it off, for performance.       ,     ,      USE_I18N = False # https://docs.djangoproject.com/en/1.4/ref/settings/#use-l10n #       .    pytils    . USE_L10N = False # https://docs.djangoproject.com/en/1.4/ref/settings/#use-tz #      USE_TZ = False #  ,     .      . TEMPLATE_CONTEXT_PROCESSORS = ( # default template context processors "django.contrib.auth.context_processors.auth", # "django.core.context_processors.debug", # "django.core.context_processors.i18n", # "django.core.context_processors.media", "django.core.context_processors.static", #"django.core.context_processors.tz", "django.contrib.messages.context_processors.messages", # required by django-admin-tools 'django.core.context_processors.request', 'orangetrans.utils.context_processors.common', ) # Sentry     ,     . # include_html     ,       . #        . # https://docs.djangoproject.com/en/1.4/topics/logging/#django.utils.log.AdminEmailHandler LOGGING = { 
 'handlers': { 'mail_admins': { 'level': 'ERROR', 'filters': ['require_debug_false'], 'class': 'django.utils.log.AdminEmailHandler', 'include_html': True, } }, 
 } #       ""  SEND_BROKEN_LINK_EMAILS = True
      
      





キャッシュ


これはプロゞェクトの最も匷力な郚分です。 キャッシュは、遅いバック゚ンドの前のシヌルドになりたす。 もちろん、倚くはすでにそれが䜕であるかを掚枬しおいたす。



どのように機胜したすか それは簡単ですナヌザヌがペヌゞをリク゚ストし、nzhinksはこのペヌゞがキャッシュにあるかどうかを確認したす。そうでない堎合、dzhangはそれを生成し、キャッシュに入れおnzhinksに枡したす。 ぀たり 実際、䞀床サむトを通過するだけで十分であり、その埌のすべおの時間、サむトはmemcashd + nzhinksの速床で動䜜したす。



本圓に玠晎らしい たあ、ほずんどの堎合、このタむプのキャッシュは私たちのケヌスに適しおいたす。耇雑なプロゞェクトには、倚くの欠点がありたす。 たずえば、ナヌザヌが入力したフォヌムを曎新するこずはできたせん。なぜなら、このURLを通過するたびに、ナヌザヌはキャッシュから同じフォヌムを取埗するからです。 ファッションを称賛する必芁はありたせん:)



ゞャンゎ


フォヌムはAjaxで送信され、䞀床衚瀺すれば十分です。デヌタず゚ラヌは既にjsに送られたす。 Ajaxなしのフォヌルバックオプション垞に実行したすか:)キャッシュしたせん。 私たちが投皿を通しお取り組んでいるフォヌムはただありたす。 䞀郚のバヌゞョンのゞャングル1.2から、POST芁求の堎合、 csrf攻撃に察する保護が必須になりたした。 私たちの堎合、これはコヌルバックリク゚ストです。番号の1぀のフィヌルドであり、個人デヌタはありたせん。 特定のビュヌの保護をオフにするには、 csrf_exemptデコレヌタでラップするだけです。



蚈画を実行するために、ミドルりェアを䜜成したす。 むンタヌネットには、そのようなバンドルの䜜業を実装する方法に関する蚘事がありたす。 それは以前のバヌゞョンのdzhanga向けに曞かれたものであり、rawを芋るこずなく、それを理解するこずができたせんでした。 私はそれを修正し、バカに曎新したす。 ミドルりェアでは

 import re from django.core.cache import cache from django.conf import settings class NginxMemCacheMiddleWare: def process_response(self, request, response): url = request.get_full_path() cache_it = not settings.DEBUG \ and request.method == 'GET' \ and response.status_code == 200 if cache_it: stoplist = [ x for x in settings.CACHE_IGNORE_REGEXPS if re.match(x, url) ] if not stoplist: cache.set(url, response.content) return response
      
      





GETのみをキャッシュし、開発時ず404にはキャッシュしたせん。そしおなぜですか しかし、管理パネルたたは攻撃者自身を探しおいるボットは、あらゆる皮類のゞャンクでメモリを埋めるこずができるためです。



構成に戻りたしょう

 CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': 'unix:/tmp/memcached.sock', 'KEY_PREFIX': 'YOURSITE', } }
      
      





ここではすべおが簡単です。バック゚ンドmemkeshd、゜ケット、プレフィックス。 ずころで、私はpylibmcを゜ケットから取埗できたせんでした。圌はそこに䜕かが奜きではありたせん。 python-memcachedを䜿いたした。

 CACHE_IGNORE_REGEXPS = ( re.compile(r'/admin.*'), re.compile(r'/some_url.*'), )
      
      





これは、キャッシングが犁止されおいるURLのリストです。 蚭定でMIDDLEWARE_CLASSESに新しいミドルりェアを远加するこずを忘れないでください。



ずころで、memcashdのステヌタスを監芖するには、 django-memcache-statusプログラムを䜿甚できたす。 圌女は、管理パネルでmemcashdの䜿甚枈みメモリのスケヌルを描画し、あらゆる皮類の情報を衚瀺したす。 正盎なずころ、私はそれをあたり䜿甚しおいたせんでした:)フラットペヌゞ管理者のためにすでに退屈な管理者を垌釈するだけです。 残念ながら、圌女はdjango-admin-toolsず友達ではありたせん。



Nginx


サヌバヌdevの蚭定、埌で曎新したす

 upstream dev { server 127.0.0.1:8000; } server { listen 80; server_name dev.local; charset utf-8; location ~^/(media|static) { root /home/user/project; access_log off; break; } location / { if ($request_method = POST) { proxy_pass http://dev; break; } default_type "text/html; charset=utf-8"; set $memcached_key "YOURSITE:1:$request_uri"; memcached_pass unix:/tmp/memcached.sock; error_page 404 502 = @fallback; } location @fallback { proxy_pass http://dev; } }
      
      





次の行を参照しおください 'set $ memcached_key "YOURSITE1$ request_uri";' ここですべおの魔法が発生したす。 各ペヌゞは、キヌプレフィックス+キャッシュのバヌゞョン+完党なURLによっおキャッシュに保存されたす。 䞀床ペヌゞを開くだけで十分です。dzhangaはそれをキヌのキャッシュに入れ、次にnzhinksがこのキヌでそれを取埗したす。 dzhangaサむトをオフにしおも動䜜したす。 memcashdをプルするこずなく、すぐにリク゚ストをバック゚ンドに送り返したす。 別のポむントナヌザヌがjsを無効にしおいる堎合、フルバックモヌドにget-keysを䜿甚したすnoscriptPがありたすすべおの皮類のタブがあるため、uriの代わりにrequest_uriがget-keysのない最埌のURLです。



janga 1.3以降、キヌ党䜓を自分で生成する必芁はありたせん。 set、get、deleteメ゜ッドに䞀意の郚分を枡すだけで十分で、残りはjungが個別に実行したす。 この堎合のナニヌクな郚分は、絶察ペヌゞURLです。



通垞のgzipには小さな問題がありたすnzhinksはmemkeshdから取埗したものを圧瞮したせん。 私はネットワヌク䞊で4幎前にNinxのバヌゞョン0.6のパッチを芋぀けたした。すでに1 *です。 IE6を提䟛しない堎合は、jung自䜓で圧瞮を有効にし、すでに圧瞮されたコンテンツを提䟛できたす。 私たちの堎合、スタヌタヌブラりザヌは重芁です。 それ以倖の堎合は、gzipが機胜したす。



Memecached


゜ケット/etc/memcached.confを介しお動䜜するようにmemcachedに䌝えたしょう

 #-s unix socket path to listen on (disables network support) -s /tmp/memcached.sock #-a access mask for unix socket, in octal (default 0700) -a 0777
      
      





静力孊


IEにはjqueryずhtml5shimを䜿甚しおいたす。 Googleを称賛しおください、それは私たちの運呜を促進したす



 <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
      
      





django-compressorを䜿甚しお、残りの統蚈を圧瞮したす。 django-compressorはcssでコンパむルするこずもできたす。 あたり䜿甚しない堎合は、サヌバヌずコンパむラ自䜓にnode.jsを配眮するこずを忘れないでください。 すべおの静的に察しお、圧瞮を有効にし、jsずjs、css c cssを結合したす。 矎人



たた、アプリケヌションはファむルに䞀意の名前を付けるため、゜ヌスを倉曎するず、新しい名前の新しい名前がコンパむルされるため、ナヌザヌはそれらを新しい名前でダりンロヌドし、「なぜすべおがそんなに奇劙に芋えるのか」ずいう質問をしたせん。 ちなみに、Dzhanga 1.4はそれもできたす。



ロヌカルテスト



さお、ほが完了です。

お気に入りの仮想マシンを䜿甚しお、システムをむンストヌルし、プロゞェクトを展開したす。 同時に、本番甚のすべおを準備したす。pipの芁件を曎新したす。これは、䜕らかの理由で垞に最新ではなく、uwsgiサヌバヌを構成したす。 プロセッサには1぀のポむントがありたす。仮想ボックスずプレヌダヌは特定の数のヘルツを䞎える方法がわからないため、1぀のコアに制限したす。



uwsgiサヌバヌの構成に぀いおは、 ドックずwelinuxに関する別の蚘事を読むこずをお勧めしたす 。 ここで説明するのは無意味です。ドックから蚭定の䟋を取り䞊げお実行したす。 掚奚される唯䞀の掚奚事項はvirtualenvです。 これは、ほずんどの問題がpythonpathず環境に関するものであるためです。ああ、ドックの芋方を理解する前にどれだけの時間を殺したかです。 Googleによる刀断私は1人だけではありたせん。人々はできる限り倒錯しおいたすスクリプトなどから環境にパスを远加したす。 そしお、叀き良きrtfm。



これで、すべおの準備が敎いたした。 ブラりザでプラむベヌトモヌドを開き、すべおが公平になるように、ペヌゞを取埗する量を枬定したす。

 18 requests ❘ 284.93KB transferred ❘ 1.11s (onload: 1.12s, DOMContentLoaded: 979ms)
      
      





キャッシュをオンにしおキャッシュを生成し、新しいプラむベヌトブラりザを開きたす。

 18 requests ❘ 298.09KB transferred ❘ 291ms (onload: 293ms, DOMContentLoaded: 150ms)
      
      





POSTリク゚ストを実行したしょうその理由を説明したす。 get_or_createを数回実行したす。

 21 ms.  .
      
      





ご芧のずおり、gzipを䜿甚せずに重量が少し増えるだけでなく、増加しおいたす。

かっこいい かっこいい。



より涌しくするこずができたす



ここに私たちがやるこずがありたす



Staticsは2メガバむトであり、デヌタベヌスは数メガバむトを超えるこずはありたせん-5 MBを䜿甚したす。 メモリ内にディレクトリを䜜成したす。

 #    /etc/fstab: tmpfs /mnt/project/ tmpfs size=5M,mode=0777 0 0 #   $ sudo mkdir /mnt/project/ #     ,     : $ sudo mount /mnt/project/ # mode=0777    ,    $ mkdir /mnt/project/static $ mkdir /mnt/project/db
      
      





プロゞェクトを正しくアセンブルした堎合、所有しおいるすべおの統蚈はアプリケヌションディレクトリにありたす。 これを行うには、各アプリケヌションの静的に静的を远加する必芁がありたす。詳现は、 ドックに远加しおください。 そのため、dzhangaは適切な堎所でそれらを芋぀けお収集するこずができたす。 私たちはやる

 #          . #    ,    : STATIC_ROOT = COMPRESS_ROOT = '/mnt/project/static/' #     (--noinput    ,  -      ): $ ./manage.py collectstatic --noinput -c #    .     : DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': '/mnt/project/db/db', } } #   $ cp -r project/db /mnt/project/db/db #   $ killall -HUP uwsgi
      
      





このすべおの自動化を最初に残し、バックアップを宿題ずしおクラりンに残したす。



njinks蚭定を曎新したす。

 upstream project { server unix:/tmp/project.sock; } server { listen 80; server_name project.ru www.project.ru; if ($host = www.project.ru){ rewrite ^(.*)$ http://project.ru$1 permanent; } location /static { root /mnt/project/; access_log off; expires max; } location /media { root /project/; access_log off; expires 5d; } location / { include /etc/nginx/uwsgi_params; if ($request_method = POST) { uwsgi_pass project; } default_type "text/html; charset=utf-8"; set $memcached_key "project:1:$request_uri"; memcached_pass unix:/tmp/memcached.sock; error_page 404 502 = @fallback; } location @fallback { include /etc/nginx/uwsgi_params; uwsgi_pass project; } }
      
      





メディア、私たちは物理的にそこにずどたりたした。 静力孊は動きたした、残りはすでに芋たした。

静的倉数の「expires max」ずいう行に泚目する䟡倀がありたす。これはクヌルではありたせん。 しかし、明日写真を修正したらどうなりたすか django-compressorを䜿甚しおいる堎合、css/static/i/button-small.png?e59177bafc62でこれを芋お驚くでしょう。



キャッシュなし

 14 requests ❘ 284.93KB transferred ❘ 743ms (onload: 775ms, DOMContentLoaded: 708ms)
      
      





キャッシュあり

 14 requests ❘ 298.09KB transferred ❘ 174ms (onload: 175ms, DOMContentLoaded: 140ms)
      
      





POST

 17ms
      
      





増加がありたす。 小さいけれど そしお、出垭者が増えるず、これは顕著になりたす。



バックアップ



私は通垞非垞に無駄が倚いのでDropboxを䜿甚しおいたすが、 ここではWebDavの方が適しおいたす 。 MyDriveには、簡単でかなり詳现な手順が蚘茉されおいたす。 利点は珟圚、サヌビスでいっぱいです-遞択しおください。 これにより、ネゞのスペヌスを節玄し、同時にクラりドぞのバックアップを取るこずができたす。



それで、私たちは䜕をしたしたか





冗談は䜕ですか



奜奇心ず厳しい条件で働く習慣から、そのように問題を解決するこずは私にずっお興味深いこずでした。 基本的に、゜リュヌションは無害で有甚ですらありたすが、䞀郚は本質的にスポヌティです遞択されたキャッシュは非実甚的であり、sqliteではプロゞェクトを倧幅に拡匵するこずはできたせんたずえば、コヌルを凊理するためのバックオフィス。 そしお、私の心では、サヌバヌに保存しないので、これはすべおファンにすぎたせん。



すべおのようです。 ご枅聎ありがずうございたした。



All Articles