Using Amazon Web Services using wikipaintings.org as an example

    I think the respected community will be interested to learn about my experience in developing an Internet project using amazon web services.

    I don’t pretend to say that the whole project is perfect, but I will try to describe the main solutions that helped to make this project. Wikipedia.org, which inspired us to work, gives out 12 billion pages a month, and so we tried to prepare the code for popularity growth from the very beginning.

    What is wikipaintings.org - www.wikipaintings.org/en/About
    Now the first stage of development and the main tasks of the next stage are ending - attracting volunteers to fill the site.

    If it seems to someone that the paintings are boring, appreciate the work of Archimboldo -www.wikipaintings.org/en/giuseppe-arcimboldo/spring-1573#supersized-artistPaintings-184903

    If you are interested in finally understanding the classification of painting styles, welcome to www.wikipaintings.org/en/paintings-by-style

    Well and now, after you put the site in Hubbraeffect (if you haven’t put it yet, we will throw a link to all your friends), let's move on to the main thing - technical tips.

    Technology platform

    This project was completed using ASP.NET MVC, LINQ2SQL, MS SQL Server 2008 R2, and JQuery. It's no secret that AWS is more focused on JAVA / PHP developers, but I did not feel particularly deprived.
    I propose to consider my advice to developers in the order of the traditional layers of web applications.

    Database

    We started with a centralized database of business objects - according to our estimates, a fairly powerful instance is able to process the required number of typical customer requests in the near future (at the moment this is High Cpu Medium Instance). For the most popular HTTP requests, we made sure that exactly 1 SQL query is executed, which returns all the necessary data - it is the database that is the most difficult to scale in this scenario.
    It is important to say a strong “no” to storing files in the database. Despite the advanced features of SQL Server 2008, this is the wrong way. It is no coincidence that EC2 stands for Elastic Computing Cloud - your server in the first place is just a processor and its main purpose is to read, not store.
    User files will initially be too many to fit on any drive - so their place in S3 is an endless and very reliable file storage. Perhaps it will seem slow at the beginning, but its speed will not change, 1 your process or 1000 will work with it.
    Cache the results of complex queries at the database level. We have all kinds of searches for paintings and artists encapsulated in one stored procedure. As a caching key, we record all its parameters and when another user clicks on the same tag or style, we already have a prepared list of IDs of suitable objects in the database. It also allows you to instantly give the result in the case of using paging.
    Pack subordinate objects together with the main. For example, the image is stored as serialized XML in the line of the Picture and the same XML in the line of the artist. Yes, this is not very beautiful, but each subquery is at least 0.0005 seconds, and when you draw all the painting on the page, you need to multiply this time by 200.
    The article “Opening hidden data to optimize application performance” is also very useful http: // msdn. microsoft.com/ru-ru/magazine/cc135978.aspx - I check weekly whether the indexes are correct (I'm sure that many have it already in the bookmarks)

    C # / Middle tier

    Keep track of page rendering time and each major operation. Recently , the stackoverflow profiler has been highlighted , but in general, you can quickly do something simpler yourself. In BeginRequest - initialization, EndRequest - we check, the page was not rendered for more than N seconds. If it is rendered more - we write an entry in the error log. Arrange the code that logs the elapsed time of the application when you need to understand how much which step takes. It does not hurt to display such a log at the end of the masterpage as an html comment in order to visually see the effect of tuning performance.
    Make “random action” controller methods - this is much easier than learning selenium or something like that, and will allow you to test the speed of various functions of the application with simple tests, such as loadimpact.
    Be careful about nested loops. A harmless-looking rendering cycle, which in each step passes through the array using Where (), takes a tenth of a second. The same cycle before which we convert the array to Dictionary - is already completed in a hundredth of a second.
    Return multiple tables from the same SP even if you use Linq2sql - this is possible and it works well. I estimate the overhead of an elementary sampling of an object by PK at 0.005 seconds; if such an operation goes in a cycle, the economy grows many times. For example, a stored procedure returns not only a picture, but also the artist who wrote it.
    Read the data in batches and not one record at a time. This is how the display of search results for paintings works. After receiving the list of pictures in C #, we build a list of id artists and read them with one subquery into the dictionary, and then assign the read objects to the corresponding pictures.
    Do not use the component approach in its natural form, grafted by ASP.NET, to page layout. This implies a minimum of parameters for each component, which in practice leads to the fact that each component reads the user, checks his rights, reads his private settings. Get a system context valid for exactly the time of the request, where, as necessary, all the necessary information is collected and read exactly 1 time.
    Do not rely on outputcache. This is cool, fast, and you need to use it - it will reduce the load on the server, but this is not a panacea. For example, on May 18, 2010 there were 19K page views, of which 8500 were DIFFERENT (according to Google analytics). In addition, each process has its own outputcache, which means that memory costs will be proportional to the number of objects in the system x the number of servers. For main pages that do not have parameters, the caching duration can be quite long (15 minutes), and for rare pages we set 30 seconds in case this link is published on the hub. On the other hand, ajax requests are well cached - they do not have so many parameters, they are often repeated, and their result, as a rule, is less than that of an HTML page.
    Take out complex parts in separate projects. A typical cloud server is rather weak, but there can be several. For example, we took out the generation of thumbnails in a separate web service, which gave us the opportunity to place it on another server and improve the speed of downloading pictures when importing.
    Put off what you can not do now - Amazon provides an excellent, fast, endless and cheap (our cost of this service is less than 10 cents per month) tool queue (see Source Code No. 2).
    Use shared memory. For example, on the picture page (http://www.wikipaintings.org/en/giuseppe-arcimboldo/portrait-of-eve-1578) we show other paintings by this artist that are the same for different pages. Having kept the minimum necessary brief information about the paintings for each artist in our memory, we reduced the generation time of this page by 2.5 times. You can, of course, use Velocity, but the lack of support for Windows 7 on which we are developing has become a problem for us. We wrote our own windows service with which web applications communicate via remoting. In fact, this is an exemplary repetition of System.Web.Caching.Cache but it supports the same dataset for all instances.

    Client part

    Test your output with different tools - utilities like YSlow, Pagespeed , Firebug are your best friends.
    All that we can shift to cloudfront. Obviously - pictures, thumbnails, but also we write there assembled in 2 CSS files - one ordinary, 1 - gzip. The .gzip extension is important because .gz Safari does not understand. This technique is demonstrated in code example No. 1.
    Assign Expiration - by default, S3 does not do this (see code example 1). You will save user time and money on traffic. For this operation and managing static files on s3 I generally recommend cloudberry.
    An important nuance for increasing the speed of loading pages was the distribution of requests across different subdomains. The http protocol does not allow more than 2 requests to one server at a time; even though browsers make up to 5 requests, loading a page with 100+ images took more than 10 seconds. We split the images into subdomains and now, subject to a good channel, the same page loads up to 8 times faster. To do this, create a set of domains in cloudfront (we have uploads0, uploads1, ... uploads8) and select the desired one in a pseudo-random way. It is even better to register a separate domain for this so that cookies are not transmitted at each request, but we considered this paranoia.
    Do not upload more information than you need to show the page - everything else can be downloaded later via ajax. The faster the page loads, the more user loyalty. The main thing is to make a nice and adequate animation when loading data.

    Deployment Recommendations

    We use 1 instance centrally for the database, and a set of micro-instances that render pages under load balancing control ( See the article on configuring Windows Server 2008 R2 Core .
    Load balancing itself is very convenient to use - there is a GUI for working with it. It is advisable to provide the system status page, which Amazon will check at intervals of 6 to 60 seconds (set). In the case of two (possibly more) negative results (timeout or error code), the instance is declared "unhealthy" and requests go to other servers. The property is restored, it is again included in the
    work.1 load balancing during the first year is provided free of charge.
    Bacup base is done daily on a separate EBS disk. Whatever happens to the host system or windows itself, using the control panel, you can disconnect this disk from one virtual server, connect it to a new one, raise the tank and continue working. As further steps to increase the resilience of the system to emergencies, you can create snapshots of this drive automatically.

    Development process

    Not the least role was played by the development process. We did not rely on the fixed cost of the project stage, we just issued a new stable working version every week (although there were delays, admittedly).
    During the iteration, the whole team was concentrated around 3-4 main tasks, which we continued to work on until we were satisfied.
    After the launch of the next version, real life and real users often made adjustments, and 1-2 functions went to the next alteration.
    Is this process terrible in terms of planning? however, it works much better than standard outsourcing, where the amount of time is pre-allocated for each task in terms of the result. It also has an excellent effect on motivation, both in terms of the fact that there are no second-rate tasks, and supports constant refactoring so that it is comfortable to make changes in the future.
    Let the client admit to himself that what matters is not the timing and construction budgets of what is unknown, but the product that will not go to the trash and then, perhaps, you will be able to work with the agile approach.

    conclusions


    In general, despite the weak, at first glance, servers and high prices, Amazon has established itself as a reliable platform that helps to build projects ready for a “bright future”, and I will definitely recommend using other cloud-based approaches.
    If you are ready to invest a little work, then you can always take the opportunity to save and bring your hosting costs to almost the level of the cost of a regular server.

    useful links
    1. Working with S3
    2. Working with SQS
    3. Tuning Windows Server 2008 R2 Core for Micro Intsance
    4. SQL Server - Opening hidden data to optimize application performance
    5. Mini profiler for web applications from stackoverflow

    Also popular now: