Web Application Performance Design Inspection Questions - Deployment and Infrastructure
- J.D. Meier, Srinath Vasireddy, Ashish Babbar, Rico Mariani, and Alex Mackman
Do You Need a Distributed Architecture?
If you host your business logic on a remote server, you need to be aware of the significant performance implications of the additional overheads, such as network latency, data serialization and marshaling, and, often, additional security checks. Figure 4.2 shows the nondistributed and distributed architectures.
Figure 4.2: Nondistributed and distributed architectures
By keeping your logical layers physically close to one another, such as on the same server or even in the same process, you minimize round trips and reduce call latency. If you do use a remote application tier, make sure your design minimizes the overhead. Where possible, batch together calls that represent a single unit of work, design coarse-grained services, and cache data locally, where appropriate. For more information about these design guidelines, see Chapter 3, "Design Guidelines for Application Performance."
The following are some sample scenarios where you would opt for a remote application tier:
- You might need to add a Web front end to an existing set of business logic.
- Your Web front end and business logic might have different scaling needs. If you need to scale out only the business logic part, but both front end and business logic are on the same computer, you unnecessarily end up having multiple copies of the front end, which adds to the maintenance overhead.
- You might want to share your business logic among multiple client applications.
- The security policy of your organization might prohibit you from installing business logic on your front-end Web servers.
- Your business logic might be computationally intensive, so you want to offload the processing to a separate server.
What Distributed Communication Should You Use?
Services are the preferred communication across application boundaries, including platform, deployment, and trust boundaries.
If you use Enterprise Services, it should be within a service implementation, or if you run into performance issues when using Web services for cross-process communication. Make sure you use Enterprise Services only if you need the additional feature set (such as object pooling, declarative, distributed transactions, role-based security, and queued components).
If you use .NET remoting, it should be for cross-application domain communication within a single process and not for cross-process or cross-server communication. The other situation where you might need to use .NET remoting is if you need to support custom wire protocols. However, understand that this customization will not port cleanly to future Microsoft implementations.
Do You Have Frequent Interaction Across Boundaries?
Ensure that your design places frequently interacting components that perform a single unit of work within the same boundary or as close as possible to each other. Components that are frequently interacting across boundaries can hurt performance, due to the increased overhead associated with call latency and serialization. The boundaries that you need to consider, from a performance perspective, are application domains, apartments, processes, and servers. These are arranged in ascending order of increasing cost overhead.
What Restrictions Does Your Infrastructure Impose?
Target environments are often rigidly defined, and your application design needs to accommodate the imposed restrictions. Identify and assess any restrictions imposed by your deployment infrastructure, such as protocol restrictions and firewalls. Consider the following:
Do you use internal firewalls?
Is there an internal firewall between your Web server and other remote servers? This limits your choice of technology on the remote server and the related communication protocols that you can use. Figure 4.3 shows an internal firewall.
Figure 4.3: Internal and external firewalls
If your remote server hosts business logic and your internal firewall opens only port 80, you can use HTTP and Web services for remote communication. This requires Internet Information Server (IIS) on your application server.
If your remote server runs SQL Server, you need to open TCP port 1433 (or an alternative port, as configured in SQL Server) on the internal firewall. When using distributed transactions involving the database, you also have to open the necessary ports for the Distributed Transaction Coordinator (DTC). For more information about configuring DCOM to use a specific port range, see "Enterprise Services (COM+) Security Considerations" in Chapter 17, "Securing Your Application Server," in "Improving Web Application Security: Threats and Countermeasures" on MSDN® at http://msdn.microsoft.com/library/en-us/dnnetsec/html/ThreatCounter.asp.
Do you use SSL for your ASP.NET application?
If your ASP.NET application uses SSL, consider the following guidelines:
- Keep page sizes as small as possible and minimize your use of graphics. Evaluate the use of view state and server controls for your Web pages. Both of these tend to have a significant impact on page size. To find out whether your page sizes are appropriate for your scenario, you should conduct tests at the targeted bandwidth levels. For more information, see Chapter 16, "Testing .NET Application Performance."
- Use client-side validation to reduce round trips. For security reasons, you should also use server-side validation. Client-side validation is easily bypassed.
Partition your secure and nonsecure pages to avoid the SSL overhead for anonymous pages.
Do You Consider Network Bandwidth Restrictions?
Consider the following questions in relation to the available network bandwidth in your particular deployment environment:
Do you know your network bandwidth?
To identify whether you are constrained by network bandwidth, you need to evaluate the size of the average request and response, and multiply it by the expected concurrent load of users. The total figure should be considerably lower than the available network bandwidth.
If you expect network congestion or bandwidth to be an issue, you should carefully evaluate your communication strategy and implement various design patterns to help reduce network traffic by making chunkier calls. For example, do the following to reduce network round trips:
- Use wrapper objects with coarse-grained interfaces to encapsulate and coordinate the functionality of one or more business objects that have not been designed for efficient remote access.
- Wrap and return the data that you need by returning an object by value in a single remote call.
- Batch your work. For example, you can batch SQL queries and execute them as a batch in SQL Server.
For more information, see "Minimize the Amount of Data Sent Across the Wire" in Chapter 3, "Design Guidelines for Application Performance."
Have you considered the client bandwidth?
Make sure you know the minimum bandwidth that clients are likely to use to access your application. With low bandwidth connections, network latency accounts for the major part of your application's response time. The following design recommendations help address this issue:
- Minimize your page size and use of graphics. Measure page sizes and evaluate performance by using a variety of bandwidths.
- Minimize the iterations required to complete an operation.
- Minimize the use of view state. For more information, see "View State" in Chapter 6, "Improving ASP.NET Performance."
- Use client-side validation (in addition to server-side validation) to help reduce round trips.
- Retrieve only the data you need. If you need to display a large amount of information to the user, implement a data paging technique.
- Enable HTTP 1.1 compression. By default, IIS uses the GZIP and DEFLATE HTTP compression methods. Both compression methods are implemented through an ISAPI filter. For more information about enabling HTTP compression, review the IIS documentation. You can find more information about the GZIP File Format Specification (RFC 1952) and DEFLATE Compressed Data Format Specification (RFC 1951) at http://www.ietf.org.
If your application is hosted by an Internet Service Provider (ISP) or runs in another hosted environment, your application shares resources — such as processor, memory, and disk space — with other applications. You need to identify the resource utilization restrictions. For example, how much CPU is your application allowed to consume?
Knowing your resource restrictions can help you during the early design and prototyping stage of your application development.
Does Your Design Support Scaling Up?
You scale up by adding resources, such as processors and RAM, to your existing servers to support increased capacity. While scaling up is usually simpler than scaling out, there are pitfalls there as well. For example, you can fail to take advantage of multiple CPUs.
Does Your Design Support Scaling Out?
You scale out by adding more servers and by using load balancing and clustering solutions to spread the workload. This approach also provides protection against some hardware failures because, if one server goes down, another takes over. A common scaling strategy is to start by scaling up, and then scaling out if it is required.
To support a scale-out strategy, you need to avoid certain pitfalls in your application design. To help ensure that your application can be scaled out, review the following questions:
Does Your Design Use Logical Layers?
You use logical layers, such as the presentation, application, and database layers, to group related and frequently interacting components. You should strive for logical partitioning and a design where interfaces act as a contract between layers. This makes it easier for you to relocate your functionality; for example, if you need to relocate computationally intensive business logic to another server. Failure to apply logical layering results in monolithic applications that are difficult to maintain, enhance, and scale. Maintenance and enhancement is a problem, because it becomes difficult to gauge the effect of change in one component on the remaining components in your application.
Note Logical layering does not necessarily mean that you will have physical partitioning and multiple tiers when you deploy your application.
Does Your Design Consider the Impact of Resource Affinity?
Resource affinity means that your application logic is heavily dependent on a particular resource for the successful completion of an operation. The resources could range from hardware resources, such as CPU, memory, disk, or network, to other dependencies, such as database connections and Web service connections.
Does Your Design Support Load Balancing?
Load balancing is an essential technique for the majority of Internet-facing Web applications. When you design an ASP.NET application, you have a number of options. You can use network load balancing to divide traffic between the multiple servers in a Web farm. You can also use load balancing at your application tier by using COM+ component load balancing or network load balancing; for example, if you use .NET remoting with the HTTP channel. Consider the following:
Have you considered the impact of server affinity on scalability goals?
Designs that most commonly cause server affinity are those that associate session state or data caches with a specific server. Affinity can improve performance in certain scale-up scenarios. However, it limits the effectiveness when scaling out. You can still scale out by using sticky sessions so that each client keeps coming to the same server it was connected to before. The limitation is that, instead of "per request," load balancing works on a "per client" basis; this is less effective in some scenarios. Avoid server affinity by designing appropriate state and caching mechanisms.
Do you use in-process session state?
In-process state is stored in the hosting Web server process. Out-of-process state moves the storage to a separate dedicated shared resource that can be shared between several processes and servers.
You cannot necessarily switch from using in-process state to out-of-process state simply by changing your Web.config file configuration. For example, your application might store objects that cannot be serialized. You need to design and plan for scaling out by considering the impact of round trips, as well as making all your types stored in the session serializable. For more information, see "State Management" later in this chapter.
Do you use a read-write cache?
A read-write cache is a server cache that is updated with user input. This cache should serve only as a means to serving Web pages faster, and should not be necessary to successfully process a request. For more information, see "Caching" later in this chapter.