Domain | IP | Description |
imserver.p2pvpn.com | 172.0.7.205 | 基于openfire的im server |
cm1.p2pvpn.com | 172.0.7.206 | Connection Manager |
cm2.p2pvon.com | 172.0.7.205 | Connection Manager |
dns | 172.0.7.206 | dns服务器 |
一.配置dns服务器(这里的dns仅用于内网测试)
1.db.p2pvpn.com文件,用于正向解析
代码
$TTL
604800
@ IN SOA dns.p2pvpn.com. root.p2pvpn.com. (
1
604800
86400
2419200
604800 )
@ IN NS dns
dns IN A 172.0 . 7.206
imserver IN A 172.0 . 7.205
cm IN A 172.0 . 7.206
cm IN A 172.0 . 7.205
@ IN SOA dns.p2pvpn.com. root.p2pvpn.com. (
1
604800
86400
2419200
604800 )
@ IN NS dns
dns IN A 172.0 . 7.206
imserver IN A 172.0 . 7.205
cm IN A 172.0 . 7.206
cm IN A 172.0 . 7.205
2.db.7.0.172文件用于反向解析(可有可无,一般反向解析很少用)
代码
$TTL
604800
@ IN SOA dns.p2pvpn.com. root.p2pvpn.com. (
1
604800
86400
2419200
604800 )
@ IN NS dns
206 IN PTR dns
@ IN SOA dns.p2pvpn.com. root.p2pvpn.com. (
1
604800
86400
2419200
604800 )
@ IN NS dns
206 IN PTR dns
3.修改named.conf.local
zone
"
p2pvpn.com
"
{
type master;
file " /etc/bind/db.p2pvpn.com " ;
};
zone " 7.0.172.in-addr.arpa " {
type master;
file " /etc/bind/db.7.0.172 " ;
};
type master;
file " /etc/bind/db.p2pvpn.com " ;
};
zone " 7.0.172.in-addr.arpa " {
type master;
file " /etc/bind/db.7.0.172 " ;
};
通过上面的配置, 只需要im client通过cm.p2pvpn.com这个domain就能轮询二台Connection Manager
dns配置注意:
sudo /etc/init.d/bind9 restart
sudo vim /etc/resolv.conf:指向本地dns.
二.配置Connection Manager
1.修改cm1的manager.xml
代码
<?
xml version="1.0" encoding="UTF-8"
?>
<!--
This file stores bootstrap properties needed by Connection Managers.
Property names must be in the format: "prop.name.is.blah=value"
That will be stored as:
<prop>
<name>
<is>
<blah>value</blah>
</is>
</name>
</prop>
-->
<!-- root element, all properties must be under this element -->
< jive >
< xmpp >
<!-- Name of the server to connect. This property is required. -->
< domain > imserver.p2pvpn.com </ domain >
<!-- IP address or hostname of the XMPP server. If not defined then a DNS SRV lookup
of the domain will be performed. -->
<!-- <hostname></hostname> -->
<!-- TCP port to connect to the XMPP server on. -->
< port > 5262 </ port >
<!-- Password to use to log into the server. This property is required. -->
< password > 1qaz2wsx </ password >
< manager >
<!-- Name of the connection manager that uniquely identifies this manager.
This property is optional. A random name is generated if none was defined. -->
< name > cm1 </ name >
<!-- Number of connections to establish to the server. -->
< connections > 1 </ connections >
<!-- Number of threads for processing incoming server traffic per connection. -->
< incoming >
< threads > 5 </ threads >
</ incoming >
</ manager >
< server >
< certificate >
<!-- Flag that indicates if certificates of the server should be validated. -->
< verify > false </ verify >
< verify >
<!-- Flag that indicates if certificates chain should be validated. -->
< chain > true </ chain >
<!-- Verify that the the last certificate in the chain was issued by
a third-party that we trust. -->
< root > true </ root >
<!-- For every certificate in the chain, verify that the certificate
is valid at the current time. -->
< validity > true </ validity >
</ verify >
<!-- Flag that indicates if self-signed certificates are accepted. -->
< accept-selfsigned > false </ accept-selfsigned >
</ certificate >
</ server >
< client >
<!-- Milliseconds a client connection has to be idle to be closed.
Default is 30 minutes. -->
< idle > 1800000 </ idle >
</ client >
< socket >
< default >
< active > false </ active >
<!-- Default port to use for plain/TLS client connections. -->
< port > 5222 </ port >
</ default >
< ssl >
< active > false </ active >
<!-- Default port to use for client connections using old SSL method. -->
< port > 5223 </ port >
< storeType > jks </ storeType >
<!-- <keystore></keystore>
<keypass></keypass>
<truststore></truststore>
<trustpass></trustpass> -->
</ ssl >
<!-- Listen on a specific network interface. -->
<!-- <network>
<interface></interface>
</network> -->
<!-- Low level socket settings. Use this section to finetune sockets based on load. -->
<!-- Maximum number of outstanding connection requests is set. This can be considered a backlog
of requests waiting on the TCP/IP port for the listener to accept the request. -->
< backlog > 50 </ backlog >
< buffer >
<!-- Hint the size of the underlying buffers used by the platform for incoming network I/O -->
< receive > -1 </ receive >
<!-- Hint the size of the underlying buffers used by the platform for outgoing network I/O -->
< send > -1 </ send >
</ buffer >
<!-- Specifies a linger-on-close timeout. This option disables/enables immediate return
from a close() of a TCP Socket. -->
< linger > -1 </ linger >
<!-- This option causes packets to be flushed on to the network more frequently. If you are
streaming large amounts of data, there is no buffering and hence no delay. -->
<!-- <tcp-nodelay>false</tcp-nodelay> -->
</ socket >
< processor >
<!-- Number of processors that will be listening for incoming traffic. The optimal number is related
to the number of CPUs. Each processor will run in its own thread. -->
<!-- <count>1</count> -->
<!-- Number of threads that will process incoming traffic detected by processors. Note that
threads will be shared among processors. -->
<!-- <threads>
<standard>16</standard>
<ssl>16</ssl>
</threads> -->
</ processor >
<!-- Configure http binding. -->
< httpbind >
< enabled > true </ enabled >
< port >
< plain > 7071 </ plain >
< secure > 7443 </ secure >
</ port >
<!-- Script syntax allows BOSH to be used in environments where clients may be restricted to using a particular server -->
< scriptSyntax >
< enabled > true </ enabled >
</ scriptSyntax >
< client >
< requests >
<!-- Longest time (in seconds) to wait before responding to any request during the session -->
<!-- <wait></wait> -->
<!-- Maximum allowable seconds over which a client can send empty requests to the server -->
< polling > 5 </ polling >
<!-- Limit number of simultaneous requests the client makes with the 'requests' attribute -->
< max > 2 </ max >
</ requests >
<!-- Seconds a session has to be idle to be closed -->
< idle > 30 </ idle >
</ client >
</ httpbind >
</ xmpp >
<!-- Configure debug logger. -->
< log >
< debug >
< enabled > false </ enabled >
</ debug >
</ log >
</ jive >
<!--
This file stores bootstrap properties needed by Connection Managers.
Property names must be in the format: "prop.name.is.blah=value"
That will be stored as:
<prop>
<name>
<is>
<blah>value</blah>
</is>
</name>
</prop>
-->
<!-- root element, all properties must be under this element -->
< jive >
< xmpp >
<!-- Name of the server to connect. This property is required. -->
< domain > imserver.p2pvpn.com </ domain >
<!-- IP address or hostname of the XMPP server. If not defined then a DNS SRV lookup
of the domain will be performed. -->
<!-- <hostname></hostname> -->
<!-- TCP port to connect to the XMPP server on. -->
< port > 5262 </ port >
<!-- Password to use to log into the server. This property is required. -->
< password > 1qaz2wsx </ password >
< manager >
<!-- Name of the connection manager that uniquely identifies this manager.
This property is optional. A random name is generated if none was defined. -->
< name > cm1 </ name >
<!-- Number of connections to establish to the server. -->
< connections > 1 </ connections >
<!-- Number of threads for processing incoming server traffic per connection. -->
< incoming >
< threads > 5 </ threads >
</ incoming >
</ manager >
< server >
< certificate >
<!-- Flag that indicates if certificates of the server should be validated. -->
< verify > false </ verify >
< verify >
<!-- Flag that indicates if certificates chain should be validated. -->
< chain > true </ chain >
<!-- Verify that the the last certificate in the chain was issued by
a third-party that we trust. -->
< root > true </ root >
<!-- For every certificate in the chain, verify that the certificate
is valid at the current time. -->
< validity > true </ validity >
</ verify >
<!-- Flag that indicates if self-signed certificates are accepted. -->
< accept-selfsigned > false </ accept-selfsigned >
</ certificate >
</ server >
< client >
<!-- Milliseconds a client connection has to be idle to be closed.
Default is 30 minutes. -->
< idle > 1800000 </ idle >
</ client >
< socket >
< default >
< active > false </ active >
<!-- Default port to use for plain/TLS client connections. -->
< port > 5222 </ port >
</ default >
< ssl >
< active > false </ active >
<!-- Default port to use for client connections using old SSL method. -->
< port > 5223 </ port >
< storeType > jks </ storeType >
<!-- <keystore></keystore>
<keypass></keypass>
<truststore></truststore>
<trustpass></trustpass> -->
</ ssl >
<!-- Listen on a specific network interface. -->
<!-- <network>
<interface></interface>
</network> -->
<!-- Low level socket settings. Use this section to finetune sockets based on load. -->
<!-- Maximum number of outstanding connection requests is set. This can be considered a backlog
of requests waiting on the TCP/IP port for the listener to accept the request. -->
< backlog > 50 </ backlog >
< buffer >
<!-- Hint the size of the underlying buffers used by the platform for incoming network I/O -->
< receive > -1 </ receive >
<!-- Hint the size of the underlying buffers used by the platform for outgoing network I/O -->
< send > -1 </ send >
</ buffer >
<!-- Specifies a linger-on-close timeout. This option disables/enables immediate return
from a close() of a TCP Socket. -->
< linger > -1 </ linger >
<!-- This option causes packets to be flushed on to the network more frequently. If you are
streaming large amounts of data, there is no buffering and hence no delay. -->
<!-- <tcp-nodelay>false</tcp-nodelay> -->
</ socket >
< processor >
<!-- Number of processors that will be listening for incoming traffic. The optimal number is related
to the number of CPUs. Each processor will run in its own thread. -->
<!-- <count>1</count> -->
<!-- Number of threads that will process incoming traffic detected by processors. Note that
threads will be shared among processors. -->
<!-- <threads>
<standard>16</standard>
<ssl>16</ssl>
</threads> -->
</ processor >
<!-- Configure http binding. -->
< httpbind >
< enabled > true </ enabled >
< port >
< plain > 7071 </ plain >
< secure > 7443 </ secure >
</ port >
<!-- Script syntax allows BOSH to be used in environments where clients may be restricted to using a particular server -->
< scriptSyntax >
< enabled > true </ enabled >
</ scriptSyntax >
< client >
< requests >
<!-- Longest time (in seconds) to wait before responding to any request during the session -->
<!-- <wait></wait> -->
<!-- Maximum allowable seconds over which a client can send empty requests to the server -->
< polling > 5 </ polling >
<!-- Limit number of simultaneous requests the client makes with the 'requests' attribute -->
< max > 2 </ max >
</ requests >
<!-- Seconds a session has to be idle to be closed -->
< idle > 30 </ idle >
</ client >
</ httpbind >
</ xmpp >
<!-- Configure debug logger. -->
< log >
< debug >
< enabled > false </ enabled >
</ debug >
</ log >
</ jive >
2.修改cm2的manager.xml
代码
<?
xml version="1.0" encoding="UTF-8"
?>
<!--
This file stores bootstrap properties needed by Connection Managers.
Property names must be in the format: "prop.name.is.blah=value"
That will be stored as:
<prop>
<name>
<is>
<blah>value</blah>
</is>
</name>
</prop>
-->
<!-- root element, all properties must be under this element -->
< jive >
< xmpp >
<!-- Name of the server to connect. This property is required. -->
< domain > imserver.p2pvpn.com </ domain >
<!-- IP address or hostname of the XMPP server. If not defined then a DNS SRV lookup
of the domain will be performed. -->
<!-- <hostname></hostname> -->
<!-- TCP port to connect to the XMPP server on. -->
< port > 5262 </ port >
<!-- Password to use to log into the server. This property is required. -->
< password > 1qaz2wsx </ password >
< manager >
<!-- Name of the connection manager that uniquely identifies this manager.
This property is optional. A random name is generated if none was defined. -->
< name > cm2 </ name >
<!-- Number of connections to establish to the server. -->
< connections > 1 </ connections >
<!-- Number of threads for processing incoming server traffic per connection. -->
< incoming >
< threads > 5 </ threads >
</ incoming >
</ manager >
< server >
< certificate >
<!-- Flag that indicates if certificates of the server should be validated. -->
< verify > false </ verify >
< verify >
<!-- Flag that indicates if certificates chain should be validated. -->
< chain > true </ chain >
<!-- Verify that the the last certificate in the chain was issued by
a third-party that we trust. -->
< root > true </ root >
<!-- For every certificate in the chain, verify that the certificate
is valid at the current time. -->
< validity > true </ validity >
</ verify >
<!-- Flag that indicates if self-signed certificates are accepted. -->
< accept-selfsigned > false </ accept-selfsigned >
</ certificate >
</ server >
< client >
<!-- Milliseconds a client connection has to be idle to be closed.
Default is 30 minutes. -->
< idle > 1800000 </ idle >
</ client >
< socket >
< default >
< active > false </ active >
<!-- Default port to use for plain/TLS client connections. -->
< port > 5222 </ port >
</ default >
< ssl >
< active > false </ active >
<!-- Default port to use for client connections using old SSL method. -->
< port > 5223 </ port >
< storeType > jks </ storeType >
<!-- <keystore></keystore>
<keypass></keypass>
<truststore></truststore>
<trustpass></trustpass> -->
</ ssl >
<!-- Listen on a specific network interface. -->
<!-- <network>
<interface></interface>
</network> -->
<!-- Low level socket settings. Use this section to finetune sockets based on load. -->
<!-- Maximum number of outstanding connection requests is set. This can be considered a backlog
of requests waiting on the TCP/IP port for the listener to accept the request. -->
< backlog > 50 </ backlog >
< buffer >
<!-- Hint the size of the underlying buffers used by the platform for incoming network I/O -->
< receive > -1 </ receive >
<!-- Hint the size of the underlying buffers used by the platform for outgoing network I/O -->
< send > -1 </ send >
</ buffer >
<!-- Specifies a linger-on-close timeout. This option disables/enables immediate return
from a close() of a TCP Socket. -->
< linger > -1 </ linger >
<!-- This option causes packets to be flushed on to the network more frequently. If you are
streaming large amounts of data, there is no buffering and hence no delay. -->
<!-- <tcp-nodelay>false</tcp-nodelay> -->
</ socket >
< processor >
<!-- Number of processors that will be listening for incoming traffic. The optimal number is related
to the number of CPUs. Each processor will run in its own thread. -->
<!-- <count>1</count> -->
<!-- Number of threads that will process incoming traffic detected by processors. Note that
threads will be shared among processors. -->
<!-- <threads>
<standard>16</standard>
<ssl>16</ssl>
</threads> -->
</ processor >
<!-- Configure http binding. -->
< httpbind >
< enabled > true </ enabled >
< port >
< plain > 7071 </ plain >
< secure > 7443 </ secure >
</ port >
<!-- Script syntax allows BOSH to be used in environments where clients may be restricted to using a particular server -->
< scriptSyntax >
< enabled > true </ enabled >
</ scriptSyntax >
< client >
< requests >
<!-- Longest time (in seconds) to wait before responding to any request during the session -->
<!-- <wait></wait> -->
<!-- Maximum allowable seconds over which a client can send empty requests to the server -->
< polling > 5 </ polling >
<!-- Limit number of simultaneous requests the client makes with the 'requests' attribute -->
< max > 2 </ max >
</ requests >
<!-- Seconds a session has to be idle to be closed -->
< idle > 30 </ idle >
</ client >
</ httpbind >
</ xmpp >
<!-- Configure debug logger. -->
< log >
< debug >
< enabled > false </ enabled >
</ debug >
</ log >
</ jive >
<!--
This file stores bootstrap properties needed by Connection Managers.
Property names must be in the format: "prop.name.is.blah=value"
That will be stored as:
<prop>
<name>
<is>
<blah>value</blah>
</is>
</name>
</prop>
-->
<!-- root element, all properties must be under this element -->
< jive >
< xmpp >
<!-- Name of the server to connect. This property is required. -->
< domain > imserver.p2pvpn.com </ domain >
<!-- IP address or hostname of the XMPP server. If not defined then a DNS SRV lookup
of the domain will be performed. -->
<!-- <hostname></hostname> -->
<!-- TCP port to connect to the XMPP server on. -->
< port > 5262 </ port >
<!-- Password to use to log into the server. This property is required. -->
< password > 1qaz2wsx </ password >
< manager >
<!-- Name of the connection manager that uniquely identifies this manager.
This property is optional. A random name is generated if none was defined. -->
< name > cm2 </ name >
<!-- Number of connections to establish to the server. -->
< connections > 1 </ connections >
<!-- Number of threads for processing incoming server traffic per connection. -->
< incoming >
< threads > 5 </ threads >
</ incoming >
</ manager >
< server >
< certificate >
<!-- Flag that indicates if certificates of the server should be validated. -->
< verify > false </ verify >
< verify >
<!-- Flag that indicates if certificates chain should be validated. -->
< chain > true </ chain >
<!-- Verify that the the last certificate in the chain was issued by
a third-party that we trust. -->
< root > true </ root >
<!-- For every certificate in the chain, verify that the certificate
is valid at the current time. -->
< validity > true </ validity >
</ verify >
<!-- Flag that indicates if self-signed certificates are accepted. -->
< accept-selfsigned > false </ accept-selfsigned >
</ certificate >
</ server >
< client >
<!-- Milliseconds a client connection has to be idle to be closed.
Default is 30 minutes. -->
< idle > 1800000 </ idle >
</ client >
< socket >
< default >
< active > false </ active >
<!-- Default port to use for plain/TLS client connections. -->
< port > 5222 </ port >
</ default >
< ssl >
< active > false </ active >
<!-- Default port to use for client connections using old SSL method. -->
< port > 5223 </ port >
< storeType > jks </ storeType >
<!-- <keystore></keystore>
<keypass></keypass>
<truststore></truststore>
<trustpass></trustpass> -->
</ ssl >
<!-- Listen on a specific network interface. -->
<!-- <network>
<interface></interface>
</network> -->
<!-- Low level socket settings. Use this section to finetune sockets based on load. -->
<!-- Maximum number of outstanding connection requests is set. This can be considered a backlog
of requests waiting on the TCP/IP port for the listener to accept the request. -->
< backlog > 50 </ backlog >
< buffer >
<!-- Hint the size of the underlying buffers used by the platform for incoming network I/O -->
< receive > -1 </ receive >
<!-- Hint the size of the underlying buffers used by the platform for outgoing network I/O -->
< send > -1 </ send >
</ buffer >
<!-- Specifies a linger-on-close timeout. This option disables/enables immediate return
from a close() of a TCP Socket. -->
< linger > -1 </ linger >
<!-- This option causes packets to be flushed on to the network more frequently. If you are
streaming large amounts of data, there is no buffering and hence no delay. -->
<!-- <tcp-nodelay>false</tcp-nodelay> -->
</ socket >
< processor >
<!-- Number of processors that will be listening for incoming traffic. The optimal number is related
to the number of CPUs. Each processor will run in its own thread. -->
<!-- <count>1</count> -->
<!-- Number of threads that will process incoming traffic detected by processors. Note that
threads will be shared among processors. -->
<!-- <threads>
<standard>16</standard>
<ssl>16</ssl>
</threads> -->
</ processor >
<!-- Configure http binding. -->
< httpbind >
< enabled > true </ enabled >
< port >
< plain > 7071 </ plain >
< secure > 7443 </ secure >
</ port >
<!-- Script syntax allows BOSH to be used in environments where clients may be restricted to using a particular server -->
< scriptSyntax >
< enabled > true </ enabled >
</ scriptSyntax >
< client >
< requests >
<!-- Longest time (in seconds) to wait before responding to any request during the session -->
<!-- <wait></wait> -->
<!-- Maximum allowable seconds over which a client can send empty requests to the server -->
< polling > 5 </ polling >
<!-- Limit number of simultaneous requests the client makes with the 'requests' attribute -->
< max > 2 </ max >
</ requests >
<!-- Seconds a session has to be idle to be closed -->
< idle > 30 </ idle >
</ client >
</ httpbind >
</ xmpp >
<!-- Configure debug logger. -->
< log >
< debug >
< enabled > false </ enabled >
</ debug >
</ log >
</ jive >
注意:
由于使用grinder进行bosh的测试.所以开放了端口7071(默认是7070,但是该端口在我的机器上被占用)
三.启动imserver.在管理控制台-server settings-connection managers里面可以看到已经有cm1,cm2连接到imserver上.
四.设置grinder
1.修改one2one.py文件.
代码
#
The Grinder 3.0.1
# HTTP script recorded by TCPProxy at 09.Haz.2008 01:32:23
from net.grinder.script import Test
from net.grinder.script.Grinder import grinder
from net.grinder.plugin.http import HTTPPluginControl, HTTPRequest
from HTTPClient import NVPair, Codecs
from java.util import Random
from org.xml.sax import InputSource
from org.apache.xerces.parsers import DOMParser
# A shorter alias for the grinder.logger.output() method.
log = grinder.logger.output
connectionDefaults = HTTPPluginControl.getConnectionDefaults()
httpUtilities = HTTPPluginControl.getHTTPUtilities()
# To use a proxy server, uncomment the next line and set the host and port.
# connectionDefaults.setProxyServer("localhost", 8001)
# These definitions at the top level of the file are evaluated once,
# when the worker process is started.
connectionDefaults.defaultHeaders = \
( NVPair( ' User-Agent ' , ' Mozilla/5.0 (Windows; U; Windows NT 5.1; tr; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14 ' ),
NVPair( ' Accept-Encoding ' , ' gzip,deflate ' ),
NVPair( ' Accept-Language ' , ' tr-TR,tr;q=0.8,en-us;q=0.5,en;q=0.3 ' ),
NVPair( ' Accept-Charset ' , ' ISO-8859-9,utf-8;q=0.7,*;q=0.7 ' ),
NVPair( ' Cache-Control ' , ' no-cache ' ),
NVPair( ' Accept ' , ' text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 ' ), )
agentID = int(grinder.properties[ " grinder.agentID " ])
processID = int(grinder.processName.split( " - " ).pop())
host = ' 172.0.7.206 '
# 为了使用dns的负载均衡,使用domain.
domain = ' cm.p2pvpn.com '
boshUrl = ' http:// ' + domain + ' :7071/http-bind/ '
boshWait = 1
userPrefix = ' user '
# numThreads = 1
# 从配置文件里读取每个process下面启动多少个thread.而不是使用写死的值.
numThreads = int(grinder.properties[ " grinder.threads " ])
# Create an HTTPRequest for each request, then replace the
# reference to the HTTPRequest with an instrumented version.
# You can access the unadorned instance using request101.__target__.
request101 = Test( 101 , ' Initiate a BOSH session ' ).wrap(HTTPRequest(url = boshUrl))
request201 = Test( 201 , ' Authenticate ' ).wrap(HTTPRequest(url = boshUrl))
request301 = Test( 301 , ' Bind resource ' ).wrap(HTTPRequest(url = boshUrl))
request401 = Test( 401 , ' Request a session from the server ' ).wrap(HTTPRequest(url = boshUrl))
request501 = Test( 501 , ' Get roster ' ).wrap(HTTPRequest(url = boshUrl))
request601 = Test( 601 , ' Change presence ' ).wrap(HTTPRequest(url = boshUrl))
request701 = Test( 701 , ' Send one to one message ' ).wrap(HTTPRequest(url = boshUrl))
request801 = Test( 801 , ' Make an empty request to the server ' ).wrap(HTTPRequest(url = boshUrl))
request901 = Test( 901 , ' Terminate the session ' ).wrap(HTTPRequest(url = boshUrl))
class TestRunner:
""" A TestRunner instance is created for each worker thread. """
def __init__ (self):
log( " agentID %s, processID %s, threadID %s ,numThreads %s " % (agentID, processID, grinder.threadNumber,numThreads))
# agentID通过./startAgent.sh 0来指定.
self.userID = (agentID * 1000 ) + (processID * numThreads) + grinder.threadNumber
self.targetUserID = (agentID * 1000 ) + (processID * numThreads) + (grinder.threadNumber + 1 ) % numThreads
log( " userID %s, targetUserID %s " % (self.userID, self.targetUserID))
self.username = userPrefix + str(self.userID)
self.password = userPrefix + str(self.userID)
log( " username %s, password %s " % (self.username, self.password))
self.targetUser = userPrefix + str(self.targetUserID)
self.sid = ""
self.rid = Random().nextInt( 1000000 )
self.inactivity = 0
def initSession(self):
result = request101.POST( '' ,
' <body xmlns=\"http://jabber.org/protocol/httpbind\" rid=\" ' + str(self.rid) + ' \" content=\"text/xml; charset=utf-8\" to=\" ' + domain + ' \" secure=\"true\" wait=\" ' + str(boshWait) + ' \" ack=\"1\" hold=\"1\" xml:lang=\"en\" xmpp:version=\"1.0\" xmlns:xmpp=\"urn:xmpp:xbosh\" /> ' ,
( NVPair( ' Content-Type ' , ' text/plain; charset=utf-8 ' ), ))
self.rid += 1
body = getXMLcontent(result)
self.sid = body.getAttribute( ' sid ' )
self.inactivity = int(body.getAttribute( ' inactivity ' ))
log( " sid: %s, inactivity: %s " % (self.sid, self.inactivity))
log( " getSession response: %s " % result.getText())
return result
def auth(self):
authtext = Codecs.base64Encode( ' %s\x00%s\x00%s ' % (self.username + ' @ ' + domain, self.username, self.password)).strip()
log( " authtext: " + authtext)
# if authtext[-1] == '\n':
# authtext = authtext[:-1]
result = request201.POST( '' ,
' <body xmlns=\"http://jabber.org/protocol/httpbind\" rid=\" ' + str(self.rid) + ' \" sid=\" ' + self.sid + ' \"><auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"PLAIN\"> ' + authtext + ' </auth></body> ' ,
( NVPair( ' Content-Type ' , ' text/plain; charset=utf-8 ' ), ))
self.rid += 1
log( " auth response: %s " % result.getText())
return result
def bind(self):
result = request301.POST( '' ,
' <body xmlns=\"http://jabber.org/protocol/httpbind\" rid=\" ' + str(self.rid) + ' \" sid=\" ' + self.sid + ' \" xmpp:restart=\"true\" xmlns:xmpp=\"urn:xmpp:xbosh\" xml:lang=\"en\" to=\" ' + domain + ' \"><iq type=\"set\" id=\"bind_1\"><bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"><resource>Home</resource></bind></iq></body> ' ,
( NVPair( ' Content-Type ' , ' text/plain; charset=utf-8 ' ), ))
self.rid += 1
log( " bind response: %s " % result.getText())
return result
def requestSession(self):
log( " rid = " + str(self.rid))
result = request401.POST( '' ,
' <body xmlns=\"http://jabber.org/protocol/httpbind\" rid=\" ' + str(self.rid) + ' \" sid=\" ' + self.sid + ' \"><iq type=\"set\" from=\" ' + self.username + ' @ ' + domain + ' /Home\" to=\" ' + domain + ' \" id=\"session_2\"><session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\" /></iq></body> ' ,
( NVPair( ' Content-Type ' , ' text/plain; charset=utf-8 ' ), ))
self.rid += 1
log( " requestSession response: %s " % result.getText())
return result
def getRoster(self):
log( " rid = " + str(self.rid))
result = request501.POST( '' ,
' <body xmlns=\"http://jabber.org/protocol/httpbind\" rid=\" ' + str(self.rid) + ' \" sid=\" ' + self.sid + ' \"><iq type=\"get\" id=\"roster_3\"><query xmlns=\"jabber:iq:roster\" /></iq></body> ' ,
( NVPair( ' Content-Type ' , ' text/plain; charset=utf-8 ' ), ))
self.rid += 1
log( " getRoster response: %s " % result.getText())
return result
def changePresence(self, show):
result = request601.POST( '' ,
' <body xmlns=\"http://jabber.org/protocol/httpbind\" rid=\" ' + str(self.rid) + ' \" sid=\" ' + self.sid + ' \"><presence from=\" ' + self.username + ' @ ' + domain + ' /Home\"><show> ' + show + ' </show></presence></body> ' ,
( NVPair( ' Content-Type ' , ' text/plain; charset=utf-8 ' ), ))
self.rid += 1
log( " changePresence %s response: %s " % (show, result.getText()))
return result
def sendMessage(self, message, target):
result = request701.POST( '' ,
' <body xmlns=\"http://jabber.org/protocol/httpbind\" rid=\" ' + str(self.rid) + ' \" sid=\" ' + self.sid + ' \"><message type=\"chat\" from=\" ' + self.username + ' @ ' + domain + ' /Home\" to=\" ' + target + ' @ ' + domain + ' \"><body> ' + message + ' </body></message></body> ' ,
( NVPair( ' Content-Type ' , ' text/plain; charset=utf-8 ' ), ))
self.rid += 1
log( " sendMessage response: %s " % result.getText())
return result
def poll(self):
result = request801.POST( '' ,
' <body xmlns=\"http://jabber.org/protocol/httpbind\" rid=\" ' + str(self.rid) + ' \" sid=\" ' + self.sid + ' \" /> ' ,
( NVPair( ' Content-Type ' , ' text/plain; charset=utf-8 ' ), ))
self.rid += 1
log( " poll response: %s " % result.getText())
return result
def terminate(self):
result = request901.POST( '' ,
' <body xmlns=\"http://jabber.org/protocol/httpbind\" rid=\" ' + str(self.rid) + ' \" sid=\" ' + self.sid + ' \" type=\"terminate\"><presence type=\"unavailable\" from=\" ' + self.username + ' @ ' + domain + ' /Home\" to=\" ' + domain + ' \" /></body> ' ,
( NVPair( ' Content-Type ' , ' text/plain; charset=utf-8 ' ), ))
self.rid += 1
log( " terminate response: %s " % result.getText())
return result
def __call__ (self):
""" This method is called for every run performed by the worker thread. """
self.initSession()
self.auth()
self.bind()
self.requestSession()
self.getRoster()
message = " Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis rutrum porttitor ante. Nunc arcu leo. "
show = " chat "
# for i in range(2):
while (True):
if show == " dnd " :
show = " chat "
else :
show = " dnd "
self.changePresence(show)
if grinder.statistics.forLastTest.time < 5000 :
grinder.sleep( 5000 - grinder.statistics.forLastTest.time)
for j in range( 5 ):
self.sendMessage(message, self.targetUser)
if grinder.statistics.forLastTest.time < 5000 :
grinder.sleep( 5000 - grinder.statistics.forLastTest.time)
self.terminate()
def getXMLcontent(result):
parser = DOMParser()
parser.reset()
parser.parse(InputSource(result.inputStream))
root = parser.getDocument().getDocumentElement()
return root
def instrumentMethod(test, method_name, c = TestRunner):
""" Instrument a method with the given Test. """
unadorned = getattr(c, method_name)
import new
method = new.instancemethod(test.wrap(unadorned), None, c)
setattr(c, method_name, method)
# Replace each method with an instrumented version.
# You can call the unadorned method using self.getSession.__target__().
instrumentMethod(Test( 100 , ' Initiate a BOSH session ' ), ' initSession ' )
instrumentMethod(Test( 200 , ' Authenticate ' ), ' auth ' )
instrumentMethod(Test( 300 , ' Bind resource ' ), ' bind ' )
instrumentMethod(Test( 400 , ' Request a session from the server ' ), ' requestSession ' )
instrumentMethod(Test( 500 , ' Get roster ' ), ' getRoster ' )
instrumentMethod(Test( 600 , ' Change presence ' ), ' changePresence ' )
instrumentMethod(Test( 700 , ' Send one to one message ' ), ' sendMessage ' )
instrumentMethod(Test( 800 , ' Make an empty request to the server ' ), ' poll ' )
instrumentMethod(Test( 900 , ' Terminate the session ' ), ' terminate ' )
# HTTP script recorded by TCPProxy at 09.Haz.2008 01:32:23
from net.grinder.script import Test
from net.grinder.script.Grinder import grinder
from net.grinder.plugin.http import HTTPPluginControl, HTTPRequest
from HTTPClient import NVPair, Codecs
from java.util import Random
from org.xml.sax import InputSource
from org.apache.xerces.parsers import DOMParser
# A shorter alias for the grinder.logger.output() method.
log = grinder.logger.output
connectionDefaults = HTTPPluginControl.getConnectionDefaults()
httpUtilities = HTTPPluginControl.getHTTPUtilities()
# To use a proxy server, uncomment the next line and set the host and port.
# connectionDefaults.setProxyServer("localhost", 8001)
# These definitions at the top level of the file are evaluated once,
# when the worker process is started.
connectionDefaults.defaultHeaders = \
( NVPair( ' User-Agent ' , ' Mozilla/5.0 (Windows; U; Windows NT 5.1; tr; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14 ' ),
NVPair( ' Accept-Encoding ' , ' gzip,deflate ' ),
NVPair( ' Accept-Language ' , ' tr-TR,tr;q=0.8,en-us;q=0.5,en;q=0.3 ' ),
NVPair( ' Accept-Charset ' , ' ISO-8859-9,utf-8;q=0.7,*;q=0.7 ' ),
NVPair( ' Cache-Control ' , ' no-cache ' ),
NVPair( ' Accept ' , ' text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 ' ), )
agentID = int(grinder.properties[ " grinder.agentID " ])
processID = int(grinder.processName.split( " - " ).pop())
host = ' 172.0.7.206 '
# 为了使用dns的负载均衡,使用domain.
domain = ' cm.p2pvpn.com '
boshUrl = ' http:// ' + domain + ' :7071/http-bind/ '
boshWait = 1
userPrefix = ' user '
# numThreads = 1
# 从配置文件里读取每个process下面启动多少个thread.而不是使用写死的值.
numThreads = int(grinder.properties[ " grinder.threads " ])
# Create an HTTPRequest for each request, then replace the
# reference to the HTTPRequest with an instrumented version.
# You can access the unadorned instance using request101.__target__.
request101 = Test( 101 , ' Initiate a BOSH session ' ).wrap(HTTPRequest(url = boshUrl))
request201 = Test( 201 , ' Authenticate ' ).wrap(HTTPRequest(url = boshUrl))
request301 = Test( 301 , ' Bind resource ' ).wrap(HTTPRequest(url = boshUrl))
request401 = Test( 401 , ' Request a session from the server ' ).wrap(HTTPRequest(url = boshUrl))
request501 = Test( 501 , ' Get roster ' ).wrap(HTTPRequest(url = boshUrl))
request601 = Test( 601 , ' Change presence ' ).wrap(HTTPRequest(url = boshUrl))
request701 = Test( 701 , ' Send one to one message ' ).wrap(HTTPRequest(url = boshUrl))
request801 = Test( 801 , ' Make an empty request to the server ' ).wrap(HTTPRequest(url = boshUrl))
request901 = Test( 901 , ' Terminate the session ' ).wrap(HTTPRequest(url = boshUrl))
class TestRunner:
""" A TestRunner instance is created for each worker thread. """
def __init__ (self):
log( " agentID %s, processID %s, threadID %s ,numThreads %s " % (agentID, processID, grinder.threadNumber,numThreads))
# agentID通过./startAgent.sh 0来指定.
self.userID = (agentID * 1000 ) + (processID * numThreads) + grinder.threadNumber
self.targetUserID = (agentID * 1000 ) + (processID * numThreads) + (grinder.threadNumber + 1 ) % numThreads
log( " userID %s, targetUserID %s " % (self.userID, self.targetUserID))
self.username = userPrefix + str(self.userID)
self.password = userPrefix + str(self.userID)
log( " username %s, password %s " % (self.username, self.password))
self.targetUser = userPrefix + str(self.targetUserID)
self.sid = ""
self.rid = Random().nextInt( 1000000 )
self.inactivity = 0
def initSession(self):
result = request101.POST( '' ,
' <body xmlns=\"http://jabber.org/protocol/httpbind\" rid=\" ' + str(self.rid) + ' \" content=\"text/xml; charset=utf-8\" to=\" ' + domain + ' \" secure=\"true\" wait=\" ' + str(boshWait) + ' \" ack=\"1\" hold=\"1\" xml:lang=\"en\" xmpp:version=\"1.0\" xmlns:xmpp=\"urn:xmpp:xbosh\" /> ' ,
( NVPair( ' Content-Type ' , ' text/plain; charset=utf-8 ' ), ))
self.rid += 1
body = getXMLcontent(result)
self.sid = body.getAttribute( ' sid ' )
self.inactivity = int(body.getAttribute( ' inactivity ' ))
log( " sid: %s, inactivity: %s " % (self.sid, self.inactivity))
log( " getSession response: %s " % result.getText())
return result
def auth(self):
authtext = Codecs.base64Encode( ' %s\x00%s\x00%s ' % (self.username + ' @ ' + domain, self.username, self.password)).strip()
log( " authtext: " + authtext)
# if authtext[-1] == '\n':
# authtext = authtext[:-1]
result = request201.POST( '' ,
' <body xmlns=\"http://jabber.org/protocol/httpbind\" rid=\" ' + str(self.rid) + ' \" sid=\" ' + self.sid + ' \"><auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"PLAIN\"> ' + authtext + ' </auth></body> ' ,
( NVPair( ' Content-Type ' , ' text/plain; charset=utf-8 ' ), ))
self.rid += 1
log( " auth response: %s " % result.getText())
return result
def bind(self):
result = request301.POST( '' ,
' <body xmlns=\"http://jabber.org/protocol/httpbind\" rid=\" ' + str(self.rid) + ' \" sid=\" ' + self.sid + ' \" xmpp:restart=\"true\" xmlns:xmpp=\"urn:xmpp:xbosh\" xml:lang=\"en\" to=\" ' + domain + ' \"><iq type=\"set\" id=\"bind_1\"><bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"><resource>Home</resource></bind></iq></body> ' ,
( NVPair( ' Content-Type ' , ' text/plain; charset=utf-8 ' ), ))
self.rid += 1
log( " bind response: %s " % result.getText())
return result
def requestSession(self):
log( " rid = " + str(self.rid))
result = request401.POST( '' ,
' <body xmlns=\"http://jabber.org/protocol/httpbind\" rid=\" ' + str(self.rid) + ' \" sid=\" ' + self.sid + ' \"><iq type=\"set\" from=\" ' + self.username + ' @ ' + domain + ' /Home\" to=\" ' + domain + ' \" id=\"session_2\"><session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\" /></iq></body> ' ,
( NVPair( ' Content-Type ' , ' text/plain; charset=utf-8 ' ), ))
self.rid += 1
log( " requestSession response: %s " % result.getText())
return result
def getRoster(self):
log( " rid = " + str(self.rid))
result = request501.POST( '' ,
' <body xmlns=\"http://jabber.org/protocol/httpbind\" rid=\" ' + str(self.rid) + ' \" sid=\" ' + self.sid + ' \"><iq type=\"get\" id=\"roster_3\"><query xmlns=\"jabber:iq:roster\" /></iq></body> ' ,
( NVPair( ' Content-Type ' , ' text/plain; charset=utf-8 ' ), ))
self.rid += 1
log( " getRoster response: %s " % result.getText())
return result
def changePresence(self, show):
result = request601.POST( '' ,
' <body xmlns=\"http://jabber.org/protocol/httpbind\" rid=\" ' + str(self.rid) + ' \" sid=\" ' + self.sid + ' \"><presence from=\" ' + self.username + ' @ ' + domain + ' /Home\"><show> ' + show + ' </show></presence></body> ' ,
( NVPair( ' Content-Type ' , ' text/plain; charset=utf-8 ' ), ))
self.rid += 1
log( " changePresence %s response: %s " % (show, result.getText()))
return result
def sendMessage(self, message, target):
result = request701.POST( '' ,
' <body xmlns=\"http://jabber.org/protocol/httpbind\" rid=\" ' + str(self.rid) + ' \" sid=\" ' + self.sid + ' \"><message type=\"chat\" from=\" ' + self.username + ' @ ' + domain + ' /Home\" to=\" ' + target + ' @ ' + domain + ' \"><body> ' + message + ' </body></message></body> ' ,
( NVPair( ' Content-Type ' , ' text/plain; charset=utf-8 ' ), ))
self.rid += 1
log( " sendMessage response: %s " % result.getText())
return result
def poll(self):
result = request801.POST( '' ,
' <body xmlns=\"http://jabber.org/protocol/httpbind\" rid=\" ' + str(self.rid) + ' \" sid=\" ' + self.sid + ' \" /> ' ,
( NVPair( ' Content-Type ' , ' text/plain; charset=utf-8 ' ), ))
self.rid += 1
log( " poll response: %s " % result.getText())
return result
def terminate(self):
result = request901.POST( '' ,
' <body xmlns=\"http://jabber.org/protocol/httpbind\" rid=\" ' + str(self.rid) + ' \" sid=\" ' + self.sid + ' \" type=\"terminate\"><presence type=\"unavailable\" from=\" ' + self.username + ' @ ' + domain + ' /Home\" to=\" ' + domain + ' \" /></body> ' ,
( NVPair( ' Content-Type ' , ' text/plain; charset=utf-8 ' ), ))
self.rid += 1
log( " terminate response: %s " % result.getText())
return result
def __call__ (self):
""" This method is called for every run performed by the worker thread. """
self.initSession()
self.auth()
self.bind()
self.requestSession()
self.getRoster()
message = " Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis rutrum porttitor ante. Nunc arcu leo. "
show = " chat "
# for i in range(2):
while (True):
if show == " dnd " :
show = " chat "
else :
show = " dnd "
self.changePresence(show)
if grinder.statistics.forLastTest.time < 5000 :
grinder.sleep( 5000 - grinder.statistics.forLastTest.time)
for j in range( 5 ):
self.sendMessage(message, self.targetUser)
if grinder.statistics.forLastTest.time < 5000 :
grinder.sleep( 5000 - grinder.statistics.forLastTest.time)
self.terminate()
def getXMLcontent(result):
parser = DOMParser()
parser.reset()
parser.parse(InputSource(result.inputStream))
root = parser.getDocument().getDocumentElement()
return root
def instrumentMethod(test, method_name, c = TestRunner):
""" Instrument a method with the given Test. """
unadorned = getattr(c, method_name)
import new
method = new.instancemethod(test.wrap(unadorned), None, c)
setattr(c, method_name, method)
# Replace each method with an instrumented version.
# You can call the unadorned method using self.getSession.__target__().
instrumentMethod(Test( 100 , ' Initiate a BOSH session ' ), ' initSession ' )
instrumentMethod(Test( 200 , ' Authenticate ' ), ' auth ' )
instrumentMethod(Test( 300 , ' Bind resource ' ), ' bind ' )
instrumentMethod(Test( 400 , ' Request a session from the server ' ), ' requestSession ' )
instrumentMethod(Test( 500 , ' Get roster ' ), ' getRoster ' )
instrumentMethod(Test( 600 , ' Change presence ' ), ' changePresence ' )
instrumentMethod(Test( 700 , ' Send one to one message ' ), ' sendMessage ' )
instrumentMethod(Test( 800 , ' Make an empty request to the server ' ), ' poll ' )
instrumentMethod(Test( 900 , ' Terminate the session ' ), ' terminate ' )
2.修改grinder.properties文件
代码
#
每个agent启动10个进程
grinder.processes = 10
# 每个进程启动100个线程.
grinder.threads = 100
# A Python object is callable if it defines a __call__ method. Each worker thread performs a number of runs of the test script, as configured by the property #grinder.runs. For each run, the worker thread calls its TestRunner; thus the __call__ method can be thought of as the definition of a run.
grinder.runs = 1
# grinder.processIncrement=1
# grinder.processIncrementInterval=10000
# grinder.initialProcesses=1
# grinder.useConsole=false
grinder.consoleHost = 172.0 . 7.206
grinder.consolePort = 6372
grinder.logDirectory = .. / logs
grinder.numberOfOldLogs = 0
# grinder.initialSleepTime=500
# grinder.sleepTimeFactor=0.01
# grinder.sleepTimeVariation=0.005
grinder.jvm.arguments =- Dpython.cachedir = .. / tmp
grinder.script = .. / tests / one2one.py
grinder.processes = 10
# 每个进程启动100个线程.
grinder.threads = 100
# A Python object is callable if it defines a __call__ method. Each worker thread performs a number of runs of the test script, as configured by the property #grinder.runs. For each run, the worker thread calls its TestRunner; thus the __call__ method can be thought of as the definition of a run.
grinder.runs = 1
# grinder.processIncrement=1
# grinder.processIncrementInterval=10000
# grinder.initialProcesses=1
# grinder.useConsole=false
grinder.consoleHost = 172.0 . 7.206
grinder.consolePort = 6372
grinder.logDirectory = .. / logs
grinder.numberOfOldLogs = 0
# grinder.initialSleepTime=500
# grinder.sleepTimeFactor=0.01
# grinder.sleepTimeVariation=0.005
grinder.jvm.arguments =- Dpython.cachedir = .. / tmp
grinder.script = .. / tests / one2one.py
3.启动./startConsole.sh
4.启动./startAgent.sh 0