A SOAP based COM+ component Stress Tool





5.00/5 (1 vote)
Jul 31, 2002
6 min read

57133

853
This tool parses a SOAP request and calls the COM+ component to stress test it.
Introduction
COM+ is there for developing scalable applications. You have finished your component, and you have put it into COM+. Now you want to know how scalable is your component? The question arises, how to measure the scalability of your COM+ application? Basically there two major metrics to measure a COM+ application’s scalability: The latency and the throughput under different user load.
Latency is often called response time. From a client's perspective, it is the delay experienced between the point when a request is made and the server's response at the client is received. It is usually measured in units of time, such as seconds. In certain testing tools, such as the Microsoft® Web Application Stress (WAS) tool, latency is best represented by the metric "time to last byte" (TTLB), which calculates the time between sending out a Web page request and receiving the last byte of the complete page content.
Below is a typical latency versus user load curve.
Figure 1. Typical characteristics of latency versus user load
Throughput is another one of the most useful metrics to measure a distributed application’s scalability. It is the number of client requests the application can process within a certain unit of time. Typically, the unit of measurement is requests per second. It can help to identify performance bottlenecks and improving application and system performance. Figure 2 demonstrates typical characteristics of throughput versus user load.
Figure 2. Typical characteristics of throughput versus user load
Given the metrics, how can we know them of our COM+ application? The answer is to stress test it. But how? Microsoft and other vendors provide testing tools such as Web Application Stress (WAS) tool, but they are mainly focused on the Web application stress testing. They send http request to the web application to test it, and basically interact with the Presentation layer of the distributed application. Unfortunately it is usually too late when the presentation layer is finished and if we found the metrics don’t meet our design goal. We need to test the Data Layer and the Business Logical Layer before testing the web application as a whole to ensure bad performance is not propagated into the next layer.
That's why this stress testing tool comes into play. It is mainly focused on the Data Layer and Business Layer stress testing. It can be used in at least two scenarios. The first is to stress test Data Layer and business Layer after they are finished to make sure that they meet the design goal. The other is to trouble shoot the Data Layer and Business Layer if other stress testing tools such WAS found that the Web application's scalability is not so good.
Techniques used in this tool
One of
the design goal is to make this tool suitable for all the Components that
support IDispatch
.
To make this tool powerful, flexible yet easy to use, I make it based on the
SOAP protocol. SOAP protocol is ideal for describing method calls to the
component. It uses a rich type system which includes most of the types that you
may use in your programming language. Yet it is easy to use and parse. As for a
SOAP request, it can specify which component it is for, which method it is
calling, and what are the types and values of the input parameters. I use the
component's ProgID
as the URI of the namespace for the request message. For example the SOAP
request below is to call a component with ProgID
PooledObjTest.IpooledObjTest
.
It is calling the component’s GetDataset
method, passing a SQL query string to the parameter strSQL.
<?xml version="1.0" standalone="yes" ?>
- <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
- <SOAP-ENV:Body>
- <m:GetDataset xmlns:m="PooledObjTest.IPooledObjTest">
<strSQL xsi:type="xsd:string">select * from orders</strSQL>
</m:GetDataset>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
For more information about the SOAP protocol, you can have a look at the SOAP : http://www.w3.org/TR/SOAP/
To parse
the SOAP request, which is a XML file, I use the MSXML library to read the
XMLDOM object tree. There are couple of important interfaces in the library such
as IXMLDOMDocument
and IXMLDOMNode
. The IXMLDOMDocument
interface represent a
XML document. And the IXMLDOMNode
interface represents a node in the tree. The
code snippet below parse a IXMLDOMNode
to yield out a Method call.
void CSoapRequestParser::ParseACall(IXMLDOMNodePtr pChild) { GetNodeInfo(pChild); CSoapRequestCall cSoapMethod; CSoapRequestCall cPreSoapMethod; int nStartIdx = m_strName.Find(':'); if(nStartIdx != -1) cSoapMethod.SetMethodName(m_strName.Right(m_strName.GetLength() - nStartIdx - 1)); else cSoapMethod.SetMethodName(m_strName); //if there is no attributes if(m_AttribNames.GetSize()== 0) { cPreSoapMethod = m_cSoapReq.GetMethodCall(m_cSoapReq.GetMethodCount() -1); cSoapMethod.SetProgID(cPreSoapMethod.GetProgID()); } else { //find the progid in the attributes; for(int i = 0; i< m_AttribNames.GetSize(); i++) { nStartIdx = m_AttribNames[i].Find("xmlns"); if(nStartIdx != -1) { CString strTemp = m_AttribValues[i]; strTemp.TrimLeft(); strTemp.TrimRight(); cSoapMethod.SetProgID(strTemp); break; } else { //if we omit the prog id, we set it to the same as the prevous one. cPreSoapMethod = m_cSoapReq.GetMethodCall(m_cSoapReq.GetMethodCount() -1); cSoapMethod.SetProgID(cPreSoapMethod.GetProgID()); } } } //parse the parameters. ParseParams(pChild, cSoapMethod); m_cSoapReq.AddMethodCall(cSoapMethod); }
After the SOAP request file is parsed, we need to create
and call the component. To achieve the flexibility of calling different
components based on the ProgID, I use late binding. To call IDispatch
directly from VC++ is not so easy in my opinion. The most tedious task is to
package the parameters into a
DISPPARAMS
parameter.
Thanks to Xiangyang Liu’s cool article
Getting the most out of IDispatch, it make the task much easier. It uses ITypeInfo
interface to read the type library of the component and
generate the necessary information to call the IDispatch
interface. I modified the code to load the type library information from
Xiangyang Liu's article.
To simulate multiple connections at the same time, I use the multiple-threads to create the COM+ component and to call its methods. To display the result, I use the MsChart control, which is ideal for displaying charts. The code below calls the MsChart control to display the Request Per Second (RPS) result.
void CTestClientDlg::UpdateChartRPS(int nFinished) { COleSafeArray saRet; DWORD numElements[] = {TESTROUNDS, 2}; // 10x10 // Create the safe-array... saRet.Create(VT_VARIANT, 2, numElements); // Initialize it with values... long index[2]; for(index[0]=0; index[0]< TESTROUNDS; index[0]++) { for(index[1]=0; index[1]<2; index[1]++) { if(index[1] == 0) { VARIANT v; CString str; str.Format("%u Threads", m_uThreadNum[index[0]]); v.vt = VT_BSTR; v.bstrVal = _bstr_t(str); saRet.PutElement(index, &v); } else { VARIANT v; v.vt = VT_I4; if(index[0] <= nFinished) v.lVal = m_dwRPSResult[index[0]]; else v.lVal = 0; saRet.PutElement(index, &v); } } } // Return the safe-array encapsulated in a VARIANT... m_ctlChart.SetChartData(saRet.Detach()); m_ctlChart.Refresh(); UpdateWindow(); }
How to use this tool
To use this SOAP based COM+ component stress tool, you need to:
-
Create a XML file to describe what component and what methods you want to call in a round of test. You can do it with any XML editor, or you can use the Notepad if you like. You can start with the sample SOAP request described in the previous section, but be sure to change the
xmlns:m
namespace to the ProgID of your component, and change theGetDataSet
node name to the name of the method. Also be sure to change the strSQL to the name of the parameter. You can check the component’s parameter names with the OLEView tool. Next you need to change "xsd:string
" to the type of your parameter. Finally you need to change to the text of the strSQL node to the appropriate parameter value.Though there is only one method call in the sample SOAP request, you can add more method calls to it to make it like a typical client session.
NOTE: All the names in the SOAP request file is case-sensitive.
-
Start
TestClient.exe and click on the Open File button. Select the XML file you have
created in step 1 and click Open button.
Figure3. Open the XML file.
-
Specify the Thread numbers in the textbox controls. Or you can use the
default thread numbers. The TestClient will start the number of threads at the
same time to call the COM+ component’s methods simultaneously.
- Click on the Latency Test, or the Throughput test button to start test. It will report the testing result with the MsChart control.
Sample Test Results
Figure 4. A sample Latency test result .
Figure 5. A sample Throughput test result .
Known Limitations and issues
There are a couple of the known limitations and issues
about this SOAP based stress testing tool. First of all, since it uses IDispatch
to
invoke the methods of the component, it requires that your component to support IDispatch
. Next, for the time being it doesn’t
support all the parameter types that the SOAP supports. For example it doesn’t
supports arrays and structures. Finally it reports the result on the screen and
doesn’t save the result on the disk. You can extend it to add that feature.