There is a system whose architecture at the time of development was as follows:

+--------+ http | server | <------> +--------+ | nginx | | uwsgi | | django | | db | +--------+ 

But when starting up in the future into battle, I would like to have scalability and fault tolerance of the system, so the modules were separated from each other:

  http +-------+ +-------+ +-------+ <------> | nginx | <---> | app | <---> | db | +-------+ +-------+ +-------+ | uwsgi | | django| +-------+ 

There was a problem with loading images, or rather, in returning the image to the user after loading, since nginx out of the box does not know how to get into the file system of another server. In this regard, there were two ideas on how to solve this problem:

  • Using samba create a shared folder between nginx and the app , into which django will upload images, and from which nginx will pull them when prompted;
  • Use FileWrapper to let the app know how to send images to a request from nginx .
  • Put on the app software for issuing downloaded images: nginx or apache .

Can you give arguments, which of these solutions is better to use, or bring your decision?

  • Well, not samba. In * nix world there is NFS for this. Besides nginx all the same with a lokolny file system is guaranteed to give faster. I’d probably muddied some rsync, but the question is how often new images appear on the app and who puts them there - Mike
  • @Mike, images play a key role to the system, and their normal users download. And at the same time loading will be much more often than issue. If you think rsync better, then write what it is better for. - MichaelPak
  • That's why I asked how often. If the download is more likely to issue - from rsync of course difficult to apply. trying to synchronize the catalogs of pictures when adding each will be problematic. I don’t really like network solutions like samba and even nfs, because in the case of short-term connection breaks they can be blunt after a while. And the processes accessing the hung mount point can block the OS for minutes - Mike
  • I unfortunately did not work with nginx. Is it difficult to organize purely by his settings, what would he try to produce a picture from a local folder, and if it wasn’t climbing there on the network on the app? - Mike
  • one
    @MichaelPak, two words: slow connections . This is the death of Apache. - Pavel Mayorov

2 answers 2

Considering the fact that you want to scale by increasing the app servers, I suggest you modify the scheme as follows:

enter image description here

Add another server that will store and distribute files (on the File server scheme). The server's app must have a folder in which the remote network storage will be mounted (in the diagram it is indicated by the arrows nfs). I also propose to install nginx on the file server, which itself will distribute files to clients. For these purposes, he will need to allocate a subdomain.

Advantages of the scheme:

  • Minimum load and delay in the distribution of files. Nginx quickly distributes files from the local file system.
  • It allows you to scale the server app, solving the problem of storing files on them and the subsequent distribution from multiple servers.

Minuses:

  • Saving files to a network file system will slow down the response to the user.
  • For the file server, you will need to allocate a subdomain, and implement the formation of absolute links to files from this subdomain.
  • And if I want to do additional image processing? Maybe it makes sense to make another small application for working with images on the File server ? - MichaelPak
  • one
    I don't think this is a good idea. The main application will cope with image processing and writing to the remote storage of the already modified one. Although if the image processing will take a lot of time and you are ready to send the user further, leaving the processing in the background, you will still have to do for this some kind of task. Then it is not so important on which server it will be located. - LinnTroll
  • Fair, I agree. - MichaelPak
  • Great scheme) - Nick Volynkin

For a start, I will write what you can not do: you can not give statics to the network balls. Any access to the file over the network is a set of packages in both directions (do not forget that the file must be found, opened, sequentially read, closed! - and this is still without authorization)

In the matter of returning only the contents of the file, the HTTP protocol turns out to be more efficient than SMB or NFS, because a call using this protocol is always one request, and then one (long) response.


And so, what options remain?

  1. Store user files in the database (and normal DBMSs allow you to store files!) This method is the only way to ensure that all user files are deleted when a user is deleted. In addition, this is the easiest way to implement from scratch.

  2. Store user files on the frontend, fill them there through the network ball. The easiest way if you have already implemented file storage in the file system. In fact, you don’t even need to change the code - just mount the uploads folder on the app server so that it really is on the nginx server. Those. This is the task of the sysadmin, not the programmer.

  3. The option given by @LinnTroll. Used in all image hosting - should it at least mean something? But at the same time this option is also the most difficult to implement.

  4. Separate nginx on the app . I cite to complete the picture, the disadvantages of this option - a bunch. Chief among them is how will frontend-nginx behave when there are several app servers? And will the files be synchronized between them? Problems solved, but it is better not to create them.

  5. Modification of the option proposed by @LinnTroll: the user retrieves files from the fileserver not directly, but through the frontend. This option is similar to option 1, but more scalable: you can increase the number of file servers if necessary. You can use this option instead of the third one if you don’t issue IP addresses or subdomains.