Yesterday, an old customer who has been renewing his subscription , Said there was something wrong with the website . His website is just a simple display of the company's official website , use Django It's done , Make and put products everyday , Not even a deal , yes 2016 I haven't done it in years . High quality customer feedback with positive annual renewal , Quickly ask him what happened , He sent a picture , Said he edited the details of the product today , Found that the Save button is missing , Here's the picture :
You can see that this page is over , But the Save button at the bottom is missing .
natural Django Admin Manage the background commodity editing interface , There is a row of operation buttons below .
This is very strange , Why did not change the code suddenly like this . According to the thinking of our programmers , If the code doesn't change , That must be what the customer did , Ask him , Just added some product pictures , Then it won't work . Can't , I have to go backstage to have a look .
First of all, I wonder if there is something Ajax The request didn't succeed , Click the web request of the browser to have a look , Is full of 200 Respond to , No problem at all , This is strange .
I have to take a closer look at this “ Incomplete ” Product interface , No idea. , good heavens , Click to open the drop-down selection box of the picture , I found that there are hundreds of thousands of options , Why do you think so much now ? Then right click to open the source code , It's not natural ,HTML The file is close 5000 That's ok , The drop-down box selected for each picture (Dropdown) There are thousands of options , And the source code is indeed incomplete ,Body、HTML The label is not closed .
Climb up the server and read the log , First tail -f error.log
, Found some problems , Every request has a Permission denied
, as follows ( Sensitive information has been used xxx Instead of ):2022/06/29 12:20:45 [crit] 972#0: *11 open() "/var/lib/nginx/uwsgi/2/00/0000000002" failed (13: Permission denied) while reading upstream, client: xxx, server: www.xxx.com, request: "GET /admin/xxx/goods/75/ HTTP/1.1", upstream: "uwsgi://unix:///data/xxx/xxx.sock:", host: "www.xxx.com", referrer: "http://www.xxx.com/admin/xxx/goods/"
.
I couldn't help wondering , If you don't have permission, shouldn't the whole website be unable to run , This has been running for several years , Why is there a problem of not having permission to write ? But there is no idea , Had to press ignore , First go to debug mode and run the code .
A word of python manage.py runserver
down ,Debug The process starts running with a whoop , Then click the commodity editing page in the management background , little does one think , No problem at all ! The whole page is complete ,inline admin Ten eight pictures attached 、 The next row of operation buttons , All lying on the page , One refresh, two refresh, three refresh , No problem , This confused me .
Click the web request of the browser , Suddenly found that /75
This request returns a full size 1.8MB, this HTML It's too big ! Comparison visit nginx Got “ Incomplete web pages ”, only 55KB nothing more , It seems that it is nginx The entire response body is not returned (response body). Click the web source code to have a look , Almost 3 Line ten thousand , Most of them are options in the picture selection drop-down box : Thousands of documents have been repeated a dozen times .
So he began to let the dog search , Look for it carefully , Find this question and answer nginx + uwsgi + django: Random upstream prematurely closed connection #1804(https://github.com/unbit/uwsgi/issues/1804), The title looks like , Closed the connection in advance . Take a closer look , There is one answer Sure enough, we talked about a plan , Is to put uwsgi and nginx The agreement between is made by uwsgi Agreement changed to http agreement . stay uwsgi The configuration of :
[uwsgi]
http=127.0.0.1:7020
# Others omitted
stay nginx Configuration in progress :
# Others omitted
proxy_pass http://127.0.0.1:7020;
Restart after saving uwsgi and nginx, Sure enough, it's normal . And through nginx Compressed transmission , The total data volume also ranges from 1.8MB drop to 300 many KB, The speed is still satisfactory .
however , How can technical people be satisfied with this ? I read the last question and answer carefully , And adjust the search terms , Then I found this article flask server is truncating long json responses some of the times(https://stackoverflow.com/questions/53835990/flask-server-is-truncating-long-json-responses-some-of-the-times) The problems described in it are exactly the same as those I encountered , Even error messages are Permission denied
, Look closely at the answer , The reason for this unauthorized problem is that it is not configured nginx Of proxy_temp_path
, Lead to nginx Error writing cache to the default path without permission .
Why ! It makes sense ! It seems that this puzzle can be solved . Then search for proxy_temp_path
, ad locum nginx/1.17.9 randomly truncating some large proxy responses(https://trac.nginx.org/nginx/ticket/1950#comment:2) I found the explanation ,As long as nginx cannot write temporary files, the result looks exactly as described: when a response is larger than what can be held in memory buffers, nginx tries to write extra data to a temporary file, writing fails, so nginx closes the connection. Exact amount of data sent to client may vary depending on the client bandwidth.
In short , If the response body is large , and nginx Cannot write to temporary file , that nginx Will close the link , As for how much data the browser can receive , It depends on the bandwidth of users . So the symptom looks like a random return of some data .
In that case , So as long as it is well configured proxy_temp_path
, Can solve the problem . Next reference nginx The related documents Configure it to be serious /tmp
Catalog , Then change back to use uwsgi agreement , The problem has also been solved .
It's not perfect .
Considering that users' products will continue to increase , The corresponding pictures will also be uploaded constantly , In the future, the options of the picture drop-down box will further grow ,Django
Template engine rendering 1.8MB Of HTML It must take a lot of time and memory to get the file out , It will consume more resources in the future , It needs to be solved .
Continue with django admin Search for words related to foreign keys , You can find this question and answer Many objects in Django admin with Foreign Key(https://stackoverflow.com/questions/27058986/many-objects-in-django-admin-with-foreign-key), Look at the problem , It's a replica of us . Have a good question , The answer is coming :raw_id_fields
, It can use pop-up window instead of drop-down box , It looks like this after use :
use ID Display instead of drop-down box , When you click the search button on the right , A pop-up window appears , You can find the corresponding resources and choose . Use raw_id_fields
In the future, the page size will be less than 5KB, There is no such thing as NGINX Write cache needs , The problem is solved from the root .
Because this is nginx Cache mechanism problem , So in theory , Not only affect our use Django/Flask Developed Python Program , use PHP/Java/Go The development may also affect , As long as it's app server and nginx Our agreement will not http It is estimated that there will be such a problem , Then I use PHP Went to search for , Indeed, we can find the corresponding questions and answers , Let's have a mouth here , So that when other language developers search my article , It can also help .