Description
This articleArticleA theoretical solution for using comet in Asp.net. It includes the implementation of the comet technology on the server and how to solve the scalability problem. I will post a general article soon, using the comet thread pool technology I will talk about next to demonstrate a small game to provide the clientCode. It may bring you some ideas to solve the problem in a real environment.
Introduction
Over the past six months, I have been investing in developing an online chess app.Program. It allows players to register and log on to the game, and performs the same actions in the real world. One obstacle that I have to overcome is how to implement a similar communication between the server and the client in the real world. To overcome this obstacle, consider the following factors:
(1) scalability-I want it to work in a server Load balancer environment without occupying huge server resources.
(2) Compatibility-I want it to work in browsers with many different features and do not need any browser plug-ins.
(3) Performance-I hope to provide the fastest response possible between any opponent that a player can communicate. This allows me to control the time more effectively and provide a more friendly user experience.
(4) Simple-I want to implement a communication layer that does not involve third-party service applications. In general, it should only work in the host environment, such as www.discountasp.net
I evaluated all the options listed above. The first prototype I built was to use standard Ajax as a solution. It pulls data from the server. This causes too long latency and too many times of communication. Therefore, I quickly removed it from the feasibility plan. I have investigated other communication solutions. For example, a hidden flash applet is used for socket communication. This requires a browser plug-in, so it is not the answer I want. Then I found comet and thought it was the solution I wanted. So I did some research and built a prototype.
Technical Principles of comet
Comet uses a continuous connection between the client (Web browser, XMLHttpRequest) and the server. This persistent connection remains open to the server for a predefined period of time (for example, 5 seconds), and the client will respond in two ways: either timeout information, either it is the information that the logic of some parts of the server application wants to send. Once the client receives the information, it can be processed logically by any application on the client. This continuous connection will be re-opened and the above process will be repeated.
This solution solves the performance issues. It means that a message can be sent to the client whenever it needs to be sent. And if this persistent connection is opened, the client only needs a short delay to receive it, almost instantly.
Another connection is used to send messages to the server. This connection is not "continuous. And return immediately after processing. From the point of view of this chess game, this continuous connection has been waiting for the movement of the opponent's pawns. The non-persistent connection only sends my mobile messages.
A comet request returns timeout sequence diagram
Sequence diagram of messages returned by a comet
Use comet in real environment
So far, everything looks beautiful on paper. We have a solution that provides the ability to send information to a browser without the need for plug-ins in a real environment. But in practice, there will be more troubles. Many articles describe the fact that the "hack" of a continuous connection is used ". I am not inclined to agree with this idea.
Comet runs in Some browsers, and it does encounter some problems (mainly because the HTTP protocol stipulates that each browser only supports two connections at the same time and is restricted to the same host ). This limit of HTTP protocol is used to provide better performance for browsing under low-bandwidth connections, which leads to performance problems when running the comet Program (there are some solutions ). This problem only needs to be noticed by IE (I guess IE has strictly implemented the standard until version 8.0 ). Firefox 2 runs more connections and manages them better. In addition, Firefox 3 even allows more connections, which means that the prospect of a comet-style application is bright.
The second problem is the scalability of this technology. This is also a remedy in this article. This problem is due to the lack of good support for the comet style protocol on various platforms at this stage, which may result in applications that use persistent connections that may not have good scalability in the future. I would like to say that this is not a failure of the comet technical idea, but a special failure of the comet server.
Many other developers have put the servers that sit before our platform together. This allows us to separate the comet request method from the web server. And they can achieve expansion by managing their own persistent connections. In this article, I clarify the situations in which you should not use Comet in Asp.net and provide possible solutions.
Start testing comet
The main drawback of using persistent connections in Asp.net is that every connection in Asp.net occupies a working thread in Asp.net (those connections may last for five seconds and remain open ). Therefore, each client connection occupies one thread in the Asp.net thread pool. Eventually, the server stops responding if it cannot be uninstalled.
To demonstrate this situation, let me give a very simple example. It uses a simple persistent connection to initiate a request to Asp.net. Use a handler to occupy the request and keep it open for five seconds before returning to the client.
This handler is very simple. It holds the request execution for 5 seconds. Then return. This simple comet request will eventually be returned to the client due to request timeout.
I also wrote a console program. Use webrequest to call cometsynchandler. As expected, every client occupies an Asp.net working thread, and the website cannot be mounted at 40 or more connections, and the page response is slow.
The screenshot below shows what happened:
As you can see clearly, it is not suitable for any real application. So I did some "mining" and designed a solution.
Ihttpasynchandler
This is the first part of the solution. This little magic is used when we send a request to a handler.
Allows us to run code asynchronously on the server. If you are not familiar with iasynchttphandler, read the following explanation to learn how it works:
Ihttpasynchandler opens two main methods to be implemented. They are: beginprocessrequest and endprocessrequest. The general practice is: we put the processing logic at the beginning of the request in beginprocessrequest, And then we execute a series of asynchronous methods, such as database query or. NET asynchronous methods. After these asynchronous methods are executed, the client-side response is processed in endprocessrequest.
The following sequence diagram shows how it works:
Cometthreadpool
The sequence diagram above describes a custom thread pool used to process comet requests. The reason for this is that we do not want Asp.net to enable one of its own threads for every such request, knowing that it needs to wait for the timeout of a comet request.
The implementation technology of this thread pool technology is located in the cometasync folder of the website. It contains the following files:
Cometasynchandler-this is the implementation of an ihttpasynchandler interface.
Cometasyncresult-this is the custom implementation of the iasyncresult interface. It contains the state of a comet asynchronous operation.
Cometthreadpool-this is a static class used to manage the comet thread pool.
Cometwaitrequest-this is an object that represents a request from the client. They are arranged in the Custom thread pool for processing.
Cometwaitthread-this is a thread used to process the cometwaitrequest object from the queue.
This implementation creates a series of background cometwaitthread objects for the first time. Each of these objects contains a separate thread for cometwaitrequest processing. In our web application, we will instantiate a thread pool in application_start.
The five created threads remain idle in the background until the cometwaitrequest instance arrives to provide services for these instances.
Then cometasynchandler waits for the request from the client. It is responsible for arranging these requests in the thread pool.
To fully track which threads exist, beginprocessrequest outputs some debug information. Then an instance of the cometasyncresult class is created to track httpcontext and return it to Asp.net, indicating that it has started an asynchronous process. Before returning, it calls beginwaitrequest to add the request to the thread pool.
This Code creates a new instance of the cometwaitrequest class and arranges it in the thread pool.
In this Code logic, a cometwaitthread is selected and cometwaitrequest is allocated based on the cyclic method (for example, if thread 1 receives a previous request, thread 2 will receive the second one ).
Cometwaitthread class
The request is added to a list of selected threads used to store the cometwaitrequest object.
At this moment, cometasynchandler has returned ASP and net threads to the thread pool. And waiting for cometwaitthread to complete asynchronous processing, then it can complete the client request. The cometwaitthread code looks like the following:
Queuecometwaitrequest_waitcallback is the entry point of this thread. It starts execution when the application_start method returns. It executes a loop and waits for a cometwaitrequest object to be added to its queue. Once a client requests cometasynchandlerhandler, it will appear in the queue.
It processes every object in the queue sequentially in every loop. For example, if there are three requests. It checks requests 1, 2, 3, and then continues to process and continues to process requests 1, 2, 3. This ensures that each request is processed as quickly as possible, rather than waiting for the completion of its 5-second timeout.
Check whether cometwaitrequest has been arranged in the queue for more than 5 seconds. Otherwise, it checks whether an event is waiting to be returned to the client. If neither of the two cases is involved, it completes cometwaitrequest processing and returns the required response object. Then remove it from the queue.
The queuecometwaitrequest_finished method performs asynchronous operations by calling the setcompleted method of the cometasyncresult object. Then, call the callback Method on cometasyncresult. It points to the endprocessrequest method of the cometasynchandler object. The following code will be executed.
This method serializes any object that we set to the request's httpcontext output stream to respond to the client.
One thing that needs to be mentioned is that, no matter what processing the request is finally processed by those threads, when it reaches the beginprocessrequest method, it is an Asp.net working thread being executed. When the cometwaitthread is completed, either a timeout message or a response message is returned, and the endprocessrequest method is executed by a thread in the cometthreadpool thread pool. This means that Asp.net only uses a thread in its thread pool to initialize comet requests. The remaining five seconds are not processed by the Asp.net thread.
During execution, we can see in the screen:
From this point of view, it is worth mentioning that the output from the website is very good. Considering that there are 200 persistent connections, we can see that the CPU/memory data of the task manager is also very normal (and the client is also running on this machine ).
In order to check that everything works normally, I set a counter for each request/response pair to ensure that each request has a response. The following shows the five-minute test output of the 200 clients.
It shows that all requests are successfully completed.
Conclusion
By implementing a client thread pool, we can build a comet solution in our Asp.net server code instead of implementing a custom server, or even implementing any complicated messaging program. A simple thread pool is used to manage requests. For example, we use five threads to manage all 200 comet requests.
Link: http://www.codeproject.com/KB/aspnet/CometAsync.aspx