I think the distinguished community will be interested to learn about my experience in developing an Internet project using amazon web services.
I do not presume to say that the whole project is perfect, however, I will try to describe the main solutions that helped to make this project. Wikipedia.org, which inspired us to work, gives 12 billion pages per month and therefore we tried to prepare the code from the very beginning to increase its popularity.
What is wikipaintings.org -
www.wikipaintings.org/ru/AboutNow the first stage of development and the main tasks of the next stage are ending - attracting volunteers to filling the site.
')
If it seems to someone that the pictures are boring, rate the work of Archimboldo -
www.wikipaintings.org/ru/giuseppe-arcimboldo/spring-1573#supersized-artistPaintings-184903If you are interested in finally understanding the classification of painting styles, welcome to
www.wikipaintings.org/ru/paintings-by-styleWell, now, after you put the site Hubbraeffektsiyom (if you have not yet put - throw the link to all friends), let's move on to the main thing - technical advice.
Technology platform
This project was implemented 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 sufficiently powerful instance is able to handle the required number of typical customer requests in the near future (at the moment it 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 decisive "no" file storage in the database. Despite the advanced features of SQL Server 2008, this is a false path. It is not by chance that EC2 stands for Elastic Computing Cloud - in the first place, your server is just a processor and its main purpose is to count, not store.
There will initially be too many user files to fit on any disk - so their place in S3 is an endless and very reliable file storage. It may seem slow at the beginning, but its speed will not change. Your process or 1000 will work with it.
Cache the results of complex queries at the database level. We have all kinds of search for paintings and artists encapsulated in one stored procedure. As a caching key, we write down all its parameters and when another user clicks the same tag or style, we already have a prepared list of IDs of matching objects in the database. It also allows you to instantly give the result in the case of using paging.
Pack subordinate objects with the main one. For example, an image is stored as serialized XML in the Picture line and the same XML in the artist line. Yes, this is not very beautiful, but each subquery is at least 0.0005 seconds, and when you paint the entire painting on the page, this time must be multiplied 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 indexes are correct (I am sure that many of them have bookmarks )
C # / Middle tier
Keep track of the page rendering time and every major operation. Recently, the
stackoverflow profiler shines , but in general, you can quickly do something simpler on your own. In BeginRequest - initialization, EndRequest - we check if the page has not been rendered for more than N seconds. If rendered more - we write a record in the error log. Arrange the code that logs the elapsed time on the application when you need to understand how much it takes which step. It does not hurt to output such a log at the end of the masterpage as an html comment in order to clearly see the effect of tuning performance.
Make the controller's “random action” methods — it's much easier than studying selenium or something like that, and allow you to test the speed of the various functions of an application with simple tests such as loadimpact.
Be careful with nested loops. A seemingly harmless drawing cycle, which in each step passes through an array using Where (), takes a tenth of a second. The same cycle before which we convert the array into a Dictionary is already executed in a hundredth of a second.
Return
several tables from one SP even if you use Linq2sql - this is possible and it works well. I estimate the overhead of an elementary sample of an object by PK in 0.005 seconds; if such an operation goes on a cycle, the economy grows many times. For example, the stored procedure returns not only the picture, but also the artist who wrote it.
Read data in batches, not one record at a time. This is how the display of search results works. After receiving the list of paintings in C #, we build the list of artists' id and read them into the dictionary in one subquery, and then assign a few objects to the corresponding paintings.
Do not use the component approach in its natural form, grafted by ASP.NET, to the 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 the context of the system, valid exactly at the time of the request, where as necessary, all the necessary information is collected and read it exactly 1 time.
Do not rely on outputcache. This is cool, fast, and it needs to be used - it will reduce the load on the server, but this is not a panacea. For example, May 18, 2010 was 19K page views, of which - 8500 DIFFERENT (according to Google analyst). 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 number of servers. For the main pages that have no parameters, the duration of caching can be quite long (15 minutes), and for rare pages we set 30 seconds in case of publication of this link on the Hubbre. On the other hand, ajax requests are well cached - they have not so many parameters, they are often repeated, and their result is usually less than that of an HTML page.
Bring complex pieces to individual projects. A typical cloud server is rather weak, but there may be several. For example, we transferred the thumbnails generation to a separate web service, which gave us the opportunity to place it on another server and improve the speed of loading pictures on import.
Postpone what can not be done now - Amazon provides an excellent, fast, endless and cheap (our cost for this service is less than 10 cents per month), the tool is a queue (see Source Code No. 2).
Use shared memory. For example, on the picture page (http://www.wikipaintings.org/ru/giuseppe-arcimboldo/portrait-of-eve-1578) we show other pictures of this artist that are the same for different pages. Keeping the minimum necessary brief information about the paintings for each artist in memory, we reduced the time for generating 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 essence, this is an approximate repetition of System.Web.Caching.Cache, but it supports a data set that is the same for all instances.
Client part
Check your output with different tools - utilities such as YSlow,
Pagespeed , Firebug are your best friends.
All that we can shift to the cloudfront. Obviously - pictures, thumbnails, but we also write there the collected in 2 CSS files - one regular, 1 - gzip. It is the .gzip extension that is important, because Safari does not understand .gz. This technique is demonstrated in the example of code No. 1.
Assign Expiration — by default, S3 does not do this (see code 1 sample code). 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 to increase the speed of loading pages was the separation 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 have smashed pictures on subdomains and now, subject to the availability of a good channel, the same page loads up to 8 times faster. To do this, create a set of domains in the cloudfront (we have uploads0, uploads1, ... uploads8) and choose the desired one in a pseudo-random manner. It is even better to register a separate domain for this so that every request does not transfer cookies, but we consider it paranoid.
Do not download more information than you need to show the page - everything else can be downloaded later by ajax. The faster the page loads - the greater the user loyalty. The main thing is to make a nice and adequate animation when loading data.
Deployment Guidelines
We use 1 instance centrally for the database, and a set of micro instances that are engaged in rendering load balancing pages (
See the article on the Windows Server 2008 R2 Core setting .
Load balancing itself is very convenient to use - there is a GUI to work with it. It is advisable to provide a system status page that Amazon will check at intervals of from 6 to 60 seconds (set). In case of two (possible) negative results (timeout or error code), the instance is declared “unhealthy” and requests go to other servers. After the working capacity is restored, it is again included in the work.
1 load balancing for the first year is free.
Bacup database is done daily on a separate EBS disk. Whatever happens to the host system, or windows itself, the control panel tools can disconnect this disk from one virtual server, connect to a new one, raise the backup and continue working. As further steps to improve the system's resilience to emergencies, you can create a snapshot of this disk automatically.
Development process
Not the last 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 version every week (although, admittedly, there were delays).
During the iteration, the whole team was concentrated around 3-4 main tasks, on which we continued to work 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 for each task an amount of time is allocated in advance in terms of results. It also has an excellent effect on motivation, both in terms of the fact that there are no second-class tasks, and it also supports constant refactoring so that it is comfortable to make changes in the future.
Let the client admit to himself that what's more important is not the dates and budgets of the building, no one knows what, but a product that does not go to the trash can and then you may be able to work with the agile approach.
findings
In general, despite the seemingly weak 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 cloud approaches to other clients.
If you are ready to invest a bit of work, you can always save money and bring your hosting costs to almost the same level as a regular server.
useful links