You use the following code to create the endpoint: CREATE ENDPOINT SSBEndpointI1 STATE = STARTED AS TCP LISTENER_PORT = 4022 -- the default SSB port; TCP-based FOR SERVICE_BROKER ENCRYPT
Trang 1received within the specified time, the code successfully locks that conversation group
(that is, locks the specified queue for receiving) If not,@ConversationGroupIdisNULL
After this call, the program attempts to receive the next message in the queue by using the
RECEIVEstatement, whose syntax is similar to that of SELECT, except that instead of
speci-fying a table name, you specify a queue name
Next, the code checks the received message type and takes the appropriate action If the
message type is Error, it ends the dialog, reporting the error If the message type is
EndDialog, it simply ends its side of the dialog If it is a catalog change message, it updates
Publication.Productso that the related row in Publication.ProductCatalog(which
associates products with catalogs) now points to the newest data
Just as with the initiator code, the target code first declares its outgoing messages as a
typed XML variable (@AckXml) This helps in making sure that the outgoing message will
be received without error
One issue to be mindful of is that all this code is executing in the scope of a single
trans-action If any part of the code fails, the ROLLBACKstatement rolls back any DML as well as
message sends and receives To test the code, you can execute the following statement:
EXEC Production.ProductModelUpdate 749, ‘A Super Product’
NOTE
You might want to come up with a clever way of populating the body of the responding
Production.CatalogChangeAckQueueReaderstored procedure to deal with the
incom-ing acknowledgment messages sent by the target
Prioritizing Services
The next issue to consider is conversation priority A safe assumption is that some of your
software applications are more important than others Likewise, some of your SSB services
are mission-critical (and should be configurable as such) and others may be only for casual
use You can easily set a numeric priority for these services so that when system resources
are scarce (during periods of high server and network utilization), messages for your
criti-cal applications are processed first
SQL Server 2008 offers a simple syntax for accomplishing this The following example
illustrates how to set the priority to level 1 for messages transmitted from our SSB initiator
(local) service to our target (remote) service:
CREATE BROKER PRIORITY CatChangeInitToTarget
FOR CONVERSATION
SET
(
CONTRACT_NAME =
[//samspublishing.com/SS2008/SSB/Contracts/BasicCatalogChangeContract],
LOCAL_SERVICE_NAME =
Trang 2[//samspublishing.com/SS2008/SSB/Services/CatalogChangeInitiatorService],
REMOTE_SERVICE_NAME =
N’//samspublishing.com/SS2008/SSB/Services/CatalogChangeNotifyTarget’,
PRIORITY_LEVEL = 1
)
Next, you need to learn how to set up Service Broker messaging applications to run on
multiple instances of SQL Server
Service Broker Routing and Security
The following sections detail how to set up the Service Broker constructs you need for
your applications to work in a secure, distributed environment
Using Certificates for Conversation Encryption
In Listing 49.4, you might have noticed that you set theENCRYPTION = OFFflag in the
code of the initiator You had to do this because Service Broker relies heavily on
certifi-cate-based encryption If you had left the encryption flag set to its default ofON, your
messages would not have left their transmission queue, and Service Broker would have
raised an error
Service Broker services running on multiple SQL Server instances communicate across the
network via endpoints that are secured using certificates Certificates are the foundation of
secure network communications They are used for securing email (PGP), FTP (S/FTP),
HTTP (SSL), NET assemblies (strong naming), and more The basic premise of certificates
is the use of public key cryptography: When a digital certificate is created, a public key
(shared openly) and a private key (never shared) are created simultaneously via a special
algorithm such as RSA Data to be securely transmitted is first encrypted by the sender,
using the receiver’s public key, acquired either through a registration authority (RA) or
otherwise When the encrypted data is received, the receiver decrypts the data by using its
private key
SQL Server provides the DDL statementCREATE CERTIFICATEfor creating certificates This
statement provides several methods for doing so, but in this chapter you use it only to
create self-signed certificates—that is, certificates signed by their creator, not by a trusted
external authority (such as VeriSign), known as a certificate authority (CA)
Before you create a certificate, you need to create a master key for the masterdatabase
(just as you did with AdventureWorks2008andXCatMgmt) that can be used to protect the
private keys you’ll create You also need to create certificates on masterfor use with the
endpoint you need (as described later in this section) Note that you have to perform this
step and subsequent steps on all the instances of SQL Server that will be communicating
via Service Broker In the sample code, by convention, the objects created on the first
instance all terminate with the string I1, and in the second instance, they terminate with
I2 In addition, we refer to the first SQL Server instance as I1and the second as I2
Trang 3The following T-SQL creates a master key in the masterdatabase:
USE master
GO
CREATE MASTER KEY ENCRYPTION BY PASSWORD = ‘masterI1’
Now you can create your first certificate in masteronI1 (Note that SUBJECTis a metadata
field defined in the certificate standard X.509.) Here’s how you do it:
CREATE CERTIFICATE SSBMasterCertI1
WITH SUBJECT = ‘SSBMasterCertOnInstance1’,
START_DATE = ‘2008-10-02 07:30:35’;
Note: The start date must not be in the future,
or the certificate is not useful
Next, you need to create a TCP endpoint that enables Service Broker in I1to
communi-cate with Service Broker in I2 (The CREATE ENDPOINTsyntax is shown in Chapter 54,
“Managing Linked and Remote Servers,” for use in creating web services.) This endpoint
uses the keys in the certificate you just created to communicate securely You use the
following code to create the endpoint:
CREATE ENDPOINT SSBEndpointI1
STATE = STARTED
AS TCP (LISTENER_PORT = 4022) the default SSB port; TCP-based
FOR SERVICE_BROKER
(ENCRYPTION = REQUIRED, AUTHENTICATION = CERTIFICATE SSBMasterCertI1)
GO
GRANT CONNECT ON ENDPOINT::SSBEndpointI1
TO [SSBTestUserName]
ForI2to encrypt messages using the public key that resides in MasterCertI1, that public
key must be exported from the database to a file and then imported into a new certificate
onI2 You can use the newBACKUP CERTIFICATEcommand to accomplish the export to
file, and then you can perform the same steps on I2to import MasterCertI1’s public key
into a matching certificate:
BACKUP CERTIFICATE SSBMasterCertI1 TO FILE = ‘c:\temp\MasterCertI1_PK.cer’
Now you need to switch over to the second SQL Service instance and run the following
code:
USE master
GO
CREATE MASTER KEY ENCRYPTION BY PASSWORD = ‘masterI2’
GO
CREATE CERTIFICATE SSBMasterCertI2
WITH SUBJECT = ‘MasterCertOnInstance2’,
START_DATE = ‘2008-10-02 07:30:35’;
Trang 4GO
CREATE ENDPOINT SSBEndpointI2
STATE = STARTED
AS TCP (LISTENER_PORT = 4022)
FOR SERVICE_BROKER
(ENCRYPTION = REQUIRED, AUTHENTICATION = CERTIFICATE SSBMasterCertI2)
GO
GRANT CONNECT ON ENDPOINT::SSBEndpointI2
TO [SSBTestUserName]
GO
BACKUP CERTIFICATE SSBMasterCertI2
TO FILE = ‘c:\temp\SSBMasterCertI2_PK.cer’
GO
CREATE CERTIFICATE SSBMasterCertI1
AUTHORIZATION [SSBTestUserName]
FROM FILE = ‘C:\temp\SSBMasterCertI1_PK.cer’
The last statement in this code creates a certificate on I2that has the same name and
contains the same public key as SSBMasterCertI1 It also performs an essential function: it
assigns that public key to SSBTestUserNameby using theAUTHORIZATIONkeyword
Now you can return to the first instance to do the same there, using SSBMasterCertI2’s
public key:
CREATE CERTIFICATE SSBMasterCertI2
AUTHORIZATION [SSBTestUserName]
FROM FILE = ‘C:\temp\SSBMasterCertI2_PK.cer’
Note that you set up SSBTestUserNameas a domain user and then add this user as a login
withdb_ownerpermissions on both instances You don’t need to create SSBTestUserName
inXCatMgmtbecause this user is already (or should be) there For purposes of this
discus-sion, you can assume that both instances can use the path c:\temp
The next step is to create a new database on I2calledXBikeDistribution The concept
behind this database is that XBikeDistributionis a subscriber to one of the catalogs
published by XCatMgmt When a product in that catalog changes, XBikeDistribution
needs to know about it You can use the following code to create this database so that it is
as lean as possible:
USE master
GO
CREATE DATABASE XBikeDistribution
WITH TRUSTWORTHY ON
GO
ALTER DATABASE XBikeDistribution SET ENABLE_BROKER
GO
USE XBikeDistribution
GO
Trang 5CREATE MASTER KEY ENCRYPTION BY PASSWORD = ‘XBikeDistributionPW’
GO
CREATE SCHEMA Cataloging
CREATE TABLE Cataloging.CatalogSimple
(
CatalogId int IDENTITY(1,1) PRIMARY KEY,
CatalogXml xml NOT NULL,
LastUpdateDate datetime DEFAULT GETDATE()
)
GO
CREATE USER [SSBTestUserName]
The next step is to add the XML schema collection you used in previous examples
(GenericAcknowledgementSchema; found in Listing 49.2) to XBikeDistribution Then you
need to set up certificates for use in the Service Broker dialogs that will take place between
the catalog change service running in XCatMgmtand a new service you need to set up in
XBikeDistribution On I2, you run the following code to set up a certificate for use in
Service Broker conversations:
CREATE CERTIFICATE SSBDialogCertI2
WITH SUBJECT = ‘SSBDialogCertOnInstance2’,
START_DATE = ‘2008-10-02 07:30:35’
ACTIVE FOR BEGIN_DIALOG = ON;
GO
BACKUP CERTIFICATE SSBDialogCertI2
TO FILE = ‘c:\temp\SSBDialogCertI2_PK.cer’
Now you need to switch back to I1, change to XCatMgmt, and create two more certificates,
one for each side of the exchange:
USE XCatMgmt
GO
CREATE CERTIFICATE SSBDialogCertI1
WITH SUBJECT = ‘SSBDialogCertOnInstance1’,
START_DATE = ‘2008-10-02 07:30:35’
ACTIVE FOR BEGIN_DIALOG = ON;
GO
BACKUP CERTIFICATE SSBDialogCertI1
TO FILE = ‘c:\temp\SSBDialogCertI1_PK.cer’
GO
CREATE CERTIFICATE SSBDialogCertI2
AUTHORIZATION [SSBTestUserName]
FROM FILE = ‘C:\temp\SSBDialogCertI2_PK.cer’;
Note that the second certificate in this code contains the public key you just created and
exported to file in SSBDialogCertI2
Trang 6Now you need to return to I2and import the public key in SSBDialogCertI1and
associ-ate it with SSBTestUserName:
CREATE CERTIFICATE SSBDialogCertI1
AUTHORIZATION [SSBTestUserName]
FROM FILE = ‘C:\temp\SSBDialogCertI1_PK.cer’;
By the time you’re done creating all these certificates, you should have the following .cer
files in your directory: SSBMasterCertI1_PK.cer,SSBMasterCertI2_PK.cer,
SSBDialogCertI2_PK.cer, and SSBDialogCertI1_PK.cer By now, the pattern of certificate
creation and public key user association should be quite clear
The next step is to set up the Service Broker constructs You need to start on I2in
XBikeDistributionbecause it has no constructs yet First, you create the
GenericAcknowledgementSchemaXML schema collection in XBikeDistribution, as shown
earlier in Listing 49.2 Note that in this Service Broker conversation, a service in XCatMgmt
plays the role of initiator, and a service in XBikeDistributionis the target (Because
you’ve seen this all before, the following examples lump a lot of the DDL together.)
Next, you need to switch to I2and run the code in Listing 49.6
LISTING 49.6 T-SQL for Creating All the Service Broker Constructs on a Second SQL Server
Instance
USE XBikeDistribution
GO
CREATE MESSAGE TYPE
[//samspublishing.com/SS2008/SSB/MessageTypes/CatalogChangeNotifySimple]
AUTHORIZATION [SSBTestUserName] VALIDATION = WELL_FORMED_XML;
GO
CREATE MESSAGE TYPE
[//samspublishing.com/SS2008/SSB/MessageTypes/GenericAck]
AUTHORIZATION [SSBTestUserName] VALIDATION = VALID_XML
WITH SCHEMA COLLECTION GenericAcknowledgementSchema
GO
CREATE CONTRACT
[//samspublishing.com/SS2008/SSB/Contracts/SimpleCatalogNotifyContract]
AUTHORIZATION [SSBTestUserName]
(
[//samspublishing.com/SS2008/SSB/MessageTypes/CatalogChangeNotifySimple]
SENT BY INITIATOR,
[//samspublishing.com/SS2008/SSB/MessageTypes/GenericAck]
SENT BY TARGET
)
GO
CREATE PROC Cataloging.CatalogChangeNotifyQueueReader
Trang 7AS
GO
CREATE QUEUE Cataloging.CatalogChangeNotifyReceiveQueue
WITH
STATUS = ON,
ACTIVATION
(
STATUS = ON,
PROCEDURE_NAME = Cataloging.CatalogChangeNotifyQueueReader,
MAX_QUEUE_READERS = 10,
EXECUTE AS ‘SSBTestUserName’
)
GO
CREATE SERVICE
[//samspublishing.com/SS2008/SSB/Services/CatalogChangeNotifyTarget]
ON QUEUE Cataloging.CatalogChangeNotifyReceiveQueue
( [//samspublishing.com/SS2008/SSB/Contracts/SimpleCatalogNotifyContract] )
GO
CREATE ROUTE
[//samspublishing.com/SS2008/SSB/Routes/RouteToCatalogChangeNotifyInitator]
WITH
SERVICE_NAME =
‘//samspublishing.com/SS2008/SSB/Services/CatalogChangeNotifyInitiator’,
ADDRESS = ‘TCP://192.168.22.5:4022’;
GO
CREATE REMOTE SERVICE BINDING
[//samspublishing.com/SS2008/SSB/RSBindings/RSBForCatalogChangeNotifyInitator]
TO SERVICE
‘//samspublishing.com/SS2008/SSB/Services/CatalogChangeNotifyInitiator’
WITH USER = [SSBTestUserName],
ANONYMOUS = OFF
GO
GRANT SEND ON
SERVICE::[//samspublishing.com/SS2008/SSB/Services/CatalogChangeNotifyTarget]
TO [SSBTestUserName]
Listing 49.7 contains all the DDL you need to create the complementary Service Broker
objects in XCatMgmtonI1
LISTING 49.7 T-SQL for Creating All the Service Broker Constructs on the First SQL Server
Instance
USE XCatMgmt
GO
CREATE MESSAGE TYPE
Trang 8[//samspublishing.com/SS2008/SSB/MessageTypes/CatalogChangeNotifySimple]
AUTHORIZATION [SSBTestUserName] VALIDATION = WELL_FORMED_XML;
GO
CREATE CONTRACT
[//samspublishing.com/SS2008/SSB/Contracts/SimpleCatalogNotifyContract]
AUTHORIZATION [SSBTestUserName]
(
[//samspublishing.com/SS2008/SSB/MessageTypes/CatalogChangeNotifySimple]
SENT BY INITIATOR,
[//samspublishing.com/SS2008/SSB/MessageTypes/GenericAck]
SENT BY TARGET
)
GO
CREATE PROC Publication.CatalogChangeNotifyAckQueueReader
AS
GO
CREATE QUEUE Publication.CatalogChangeNotifyAckQueue
WITH
STATUS = ON,
ACTIVATION
(
STATUS = ON,
PROCEDURE_NAME = Publication.CatalogChangeNotifyAckQueueReader,
MAX_QUEUE_READERS = 10,
EXECUTE AS ‘SSBTestUserName’
)
GO
CREATE SERVICE
[//samspublishing.com/SS2008/SSB/Services/CatalogChangeNotifyInitiator]
ON QUEUE Publication.CatalogChangeNotifyAckQueue
( [//samspublishing.com/SS2008/SSB/Contracts/SimpleCatalogNotifyContract] )
GO
CREATE ROUTE
[//samspublishing.com/SS2008/SSB/Routes/RouteToCatalogChangeNotifyTarget]
WITH
SERVICE_NAME =
‘//samspublishing.com/SS2008/SSB/Services/CatalogChangeNotifyTarget’,
ADDRESS = ‘TCP://192.168.22.6:4022’;
GO
CREATE REMOTE SERVICE BINDING
[//samspublishing.com/SS2008/SSB/RSBindings/RSBForCatalogChangeNotifyTarget]
TO SERVICE
‘//samspublishing.com/SS2008/SSB/Services/CatalogChangeNotifyTarget’
WITH USER = [SSBTestUserName],
ANONYMOUS = OFF
GO
Trang 9GRANT SEND ON
SERVICE::[//samspublishing.com/SS2008/SSB/Services/CatalogChangeNotifyInitiator]
TO [SSBTestUserName]
If you look closely at Listings 49.6 and 49.7, you see that they introduce two new Service
Broker constructs: routes and remote service bindings
Building Routes to Map Conversations Between SQL Server Instances
Routes are used to map a Service Broker service to a TCP address for use when conversing
between different SQL Server instances They provide a useful level of abstraction because
the address of a route can be changed without having to change any of the constructs that
depend on it In this way, it is possible to change a route and, as long as the message
types, required XML schema collections, contracts, queues, and services exist in the
data-bases on the machines involved, only the route needs to be updated Routes can also be
used when only a single SQL Server instance is involved so that it can easily be changed to
work when a new instance comes into play
NOTE
For the routes in this example to work, the TCP port specified earlier in CREATE
END-POINT(port 4022) must be open on any firewalls involved
The routes created in Listings 49.6 and 49.7 are thus necessary because the initiator needs
to be able to locate the target service to send messages, and the target service needs to be
able to do the same
Creating Remote Service Bindings for Conversations
When initiating a conversation with a service on a nonlocal SQL Server instance, you
need to create a remote service binding A remote service binding associates a local database
user with a remote service When messages are transmitted between the instances, Service
Broker encrypts them, using the public key of the local user’s certificate They are then
decrypted on the other end, using the private key Because you have created matching
pairs of certificates and associated them with the user in the masterdatabase and in all
participating databases on both instances (and you have also turned off anonymous
access), you can be certain that communications will happen securely over the network
A Final Note on the Sample System
If you like, you can create the initiator and target service programs for the final example
in this chapter For example, you could create an update trigger (as the initiator) on
XCatMgmt.Publication.ProductCatalogthat sends a CatalogChangeNotifySimple
well-formed XML message to
XBikeDistribution.Cataloging.CatalogChangeNotifyReceiveQueue You fill in the body
of the target’s activated procedure
XBikeDistribution.Cataloging.CatalogChangeNotifyQueueReaderto receive these
Trang 10messages and reply by sending a message of type GenericAckto the existing
Production.CatalogChangeAckQueue Remember that you need to acquire the
service_broker_guidof the remote SQL Server instance’s Service Broker instance to send
messages successfully Also, you need to be sure to set the ENCRYPTIONflag to ON(the
default) when callingBEGIN DIALOG CONVERSATION
Troubleshooting SSB Applications with
ssbdiagnose.exe
SQL Server 2008 comes with a new command-line application,ssbdiagnose.exe You use
this advanced utility to monitor SSB conversations or to check application configuration
status, both across databases and between computers It supports a variety of authentication
and configuration options and generates either plain text or XML as its output
The general syntax for ssbdiagnose.exehas three parts:
Output format and error level
Connection information
Application-specific settings
You can leverage the full syntax of ssbdiagnose.exeby simply executing it from the
command line with no options (it is located in the folder [SQL Server installation
root]\[version number]\Tools\Binn) To run it, open a command window (run the
CMD.exeprogram) and then navigate to your installation location using the CDcommand
As an exercise, you can execute any of the examples that follow
In the following example, you connect to the current SSB application (as developed in
Listings 49.1 through 49.7) and check on the services’ configuration status Remember
that the application lives in two databases (AdventureWorks2008andXCatMgmt), so you
need to provide parameters to check on both sides of the service contract Because the
service and contract names are quite long, we suggest enclosing the command-line
contents in a batch file and running it from there
Execute the following command, substituting connection credentials with those
appropri-ate for your environment:
SSBDiagnose.exe
-U SSBTestUserName -P SSBTestUserName CONFIGURATION FROM SERVICE
“//samspublishing.com/SS2008/SSB/Services/CatalogChangeInitiatorService”
-S localhost\SQL08 -d AdventureWorks2008 TO SERVICE
“//samspublishing.com/SS2008/SSB/Services/CatalogMaintenanceService”
-S localhost\SQL08 -d XCatMgmt ON CONTRACT
“//samspublishing.com/SS2008/SSB/Contracts/BasicCatalogChangeContract”
If you’ve executed all the sample code and listings in this chapter, you should see no
errors in the ssbdiagnose.exeoutput For troubleshooting, refer to the next section to
learn how to explore the system catalogs for SSB