Manter a afinidade entre um grupo de assinaturas e o servidor de caixa de correio no ExchangeMaintain affinity between a group of subscriptions and the Mailbox server in Exchange

Saiba como manter a afinidade entre um grupo de assinaturas e o servidor de caixa de correio.Find out about maintaining the affinity between a group of subscriptions and the Mailbox server.

A afinidade é a associação de uma sequência de mensagens de solicitação e resposta a um servidor de caixa de correio específico.Affinity is the association of a sequence of request and response messages with a particular Mailbox server. Para a maioria das funcionalidades no Exchange, a afinidade é manipulada pelo servidor.For most functionality in Exchange, affinity is handled by the server. No entanto, as notificações são uma exceção.Notifications, however, are an exception. O cliente é responsável por manter a afinidade com o servidor de caixa de correio para assinaturas de notificação.The client is responsible for maintaining the affinity with the Mailbox server for notification subscriptions. Essa afinidade permite que o balanceador de carga e os servidores de acesso para cliente entre o cliente e o servidor direcionem as assinaturas de notificação e as solicitações relacionadas para o servidor de caixa de correio que mantém a assinatura.This affinity enables the load balancer and Client Access servers between the client and the server to route notification subscriptions and related requests to the Mailbox server that maintains the subscription. Sem a afinidade, a solicitação pode ser roteada para um servidor de caixa de correio diferente que não inclua as assinaturas do cliente, o que pode causar o retorno de um erro ErrorSubscriptionNotFound .Without affinity, the request might get routed to a different Mailbox server that does not include the client's subscriptions, which can cause an ErrorSubscriptionNotFound error to be returned.

Como a afinidade é mantida?How is affinity maintained?

A afinidade no Exchange é baseada em cookies.Affinity in Exchange is cookie based. O cliente dispara a criação do cookie incluindo cabeçalhos específicos na solicitação de assinatura e, em seguida, a resposta de assinatura contém o cookie.The client triggers the creation of the cookie by including specific headers in the subscription request, and then the subscription response contains the cookie. O cliente, em seguida, envia esse cookie em solicitações subsequentes para garantir que a solicitação seja encaminhada para o servidor de caixa de correio certo.The client then sends that cookie in subsequent requests to ensure that the request is routed to the right Mailbox server.

Mais especificamente, a afinidade no Exchange é manipulada pelo seguinte:More specifically, affinity in Exchange is handled by the following:

  • X-AnchorMailbox — um cabeçalho HTTP incluído na solicitação de assinatura inicial.X-AnchorMailbox — An HTTP header that is included in the initial subscription request. Ele identifica a primeira caixa de correio em um grupo de caixas de correio que compartilham a afinidade com o mesmo servidor de caixa de correio.It identifies the first mailbox in a group of mailboxes that share affinity with the same Mailbox server.

  • X-PreferServerAffinity — um cabeçalho HTTP que é incluído na solicitação de assinatura inicial com o cabeçalho X-AnchorMailbox e é definido como true para indicar que o cliente está solicitando que a afinidade seja mantida com o servidor de caixa de correio.X-PreferServerAffinity — An HTTP header that is included in the initial subscription request with the X-AnchorMailbox header and is set to true to indicate that the client is requesting that affinity be maintained with the Mailbox server.

  • X-BackEndOverrideCookie — um cookie incluído na resposta inicial da assinatura e contém um cookie que o balanceador de carga e o servidor de acesso para cliente usam para rotear as solicitações subsequentes para o mesmo servidor de caixa de correio.X-BackEndOverrideCookie — A cookie that is included in the initial subscription response and contains a cookie that the load balancer and Client Access server use to route subsequent requests to the same Mailbox server.

Como faço para manter a afinidade usando a API gerenciada do EWS ou o EWS?How do I maintain affinity by using the EWS Managed API or EWS?

Você pode usar as mesmas etapas para manter a afinidade para várias assinaturas de caixa de correio e seus servidores de caixa de correio, independentemente de você estar usando o streaming, pull ou notificações por push, e independente se você está direcionando um servidor local do Exchange ou o Exchange Online.You can use the same steps to maintain affinity for multiple mailbox subscriptions and their Mailbox servers, regardless of whether you are using streaming, pull, or push notifications, and regardless of whether you're targeting an Exchange on-premises server or Exchange Online.

  1. Para cada caixa de correio, ligue para descoberta automática e obtenha as configurações de usuário do GroupingInformation e do ExternalEwsUrl.For each mailbox, call Autodiscover and get the GroupingInformation and ExternalEwsUrl user settings. Para descoberta automática SOAP, você usa o elemento Setting e a descoberta automática do Pox, você usa o elemento GroupingInformation .For SOAP Autodiscover, you use the Setting element, and for POX Autodiscover, you use the GroupingInformation element.

  2. Usando as configurações do GroupingInformation e do ExternalEwsUrl das respostas da descoberta automática, coloque as caixas de correio com o mesmo valor concatenado ExternalEwsUrl e GroupingInformation no mesmo grupo.Using the GroupingInformation and ExternalEwsUrl settings from the Autodiscover responses, place mailboxes with the same ExternalEwsUrl and GroupingInformation concatenated value in the same group. Se qualquer grupo tiver mais de 200 caixas de correio, quebre os grupos para baixo, de modo que cada grupo não tenha mais de 200 caixas de correio.If any groups have more than 200 mailboxes, break the groups down further so that each group has no more than 200 mailboxes.

  3. Crie e use um objeto ExchangeService para o restante do procedimento.Create and use one ExchangeService object for the rest of the procedure. Quando você usa o mesmo objeto ExchangeService , cookies e cabeçalhos (quando são definidos) são mantidos automaticamente.When you use the same ExchangeService object, cookies and headers (when they are set) are automatically maintained. Observe que, se você não pretende agrupar assinaturas de streaming em uma única conexão, você tem liberdade para criar um objeto ExchangeService diferente para cada usuário representado.Note that if you do not intend to group streaming subscriptions into a single connection, you are free to create a different ExchangeService object for each impersonated user.

  4. Envie uma solicitação de assinatura para o usuário cujo nome de usuário aparece primeiro quando todos os usuários no grupo são classificados alfabeticamente (faremos referência a esse usuário como o usuário de caixa de correio de ancoragem).Send a subscription request for the user whose user name appears first when all users in the group are sorted alphabetically (we'll refer to this user as the anchor mailbox user). Faça o seguinte:Do the following:

  • Inclua o cabeçalho X-AnchorMailbox com um valor definido para o endereço SMTP do usuário da caixa de correio de âncora.Include the X-AnchorMailbox header with a value set to the SMTP address of the anchor mailbox user.

  • Inclua o cabeçalho X-PreferServerAffinity com um valor definido como true.Include the X-PreferServerAffinity header with a value set to true.

  • Use a função ApplicationImpersonation (o tipo ExchangeImpersonation ).Use the ApplicationImpersonation role (the ExchangeImpersonation type).

  1. Na resposta de assinatura, obtenha o valor X-BackEndOverrideCookie.In the subscription response, get the X-BackEndOverrideCookie value. Inclua esse valor em cada uma das solicitações de assinatura subsequentes para os usuários desse grupo.Include this value in each of the subsequent subscription requests for users in this group.

  2. Para cada usuário adicional no grupo, envie uma solicitação de assinatura e faça o seguinte:For each additional user in the group, send a subscription request and do the following:

  • Inclua o cabeçalho X-AnchorMailbox com um valor definido para o endereço SMTP do usuário de caixa de correio de âncora do grupo.Include the X-AnchorMailbox header with a value set to the SMTP address of the anchor mailbox user for the group.

  • Inclua o cabeçalho X-PreferServerAffinity com um valor definido como true.Include the X-PreferServerAffinity header with a value set to true.

  • Inclua o X-BackEndOverrideCookie retornado na resposta de assinatura do usuário da caixa de correio de ancoragem.Include the X-BackEndOverrideCookie that was returned in the anchor mailbox user's subscription response.

  • Use a função ApplicationImpersonation (o tipo ExchangeImpersonation ).Use the ApplicationImpersonation role (the ExchangeImpersonation type).

    Observe que o servidor usa os valores X-PreferServerAffinity e X-BackendOverrideCookie juntos para executar o roteamento para o servidor de caixa de correio.Note that the server uses the X-PreferServerAffinity and X-BackendOverrideCookie values together to perform the routing to the mailbox server. O cabeçalho X-AnchorMailbox também é necessário, mas é ignorado pelo servidor se os outros dois valores forem válidos.The X-AnchorMailbox header is also required, but is ignored by the server if the other two values are valid. Se X-AnchorMailbox e X-PreferServerAffinity estiverem em uma solicitação e X-BackendOverrideCookie não for incluído, o valor X-AnchorMailbox será usado para encaminhar as solicitações.If X-AnchorMailbox and X-PreferServerAffinity are in a request and X-BackendOverrideCookie is not included, the X-AnchorMailbox value is used to route the requests.

    Como os valores X-PreferServerAffinity e X-BackendOverrideCookie executam o roteamento, se a caixa de correio de ancoragem for movida para outro grupo ou servidor, a lógica não será alterada porque o X-BackendOverrideCookie encaminhará a solicitação para o servidor correto para o grupo.Because the X-PreferServerAffinity and X-BackendOverrideCookie values perform the routing, if the anchor mailbox ever moves to another group or server, the logic does not change because the X-BackendOverrideCookie will route the request to the correct server for the group.

  1. Envie uma única solicitação de GetStreamingEvents ou GetEvents para o grupo e faça o seguinte:Send a single GetStreamingEvents or GetEvents requests for the group, and do the following:
  • Inclua os valores SubscriptionId retornados em cada uma das respostas de assinatura individuais para caixas de correio no grupo.Include the SubscriptionId values returned in each of the individual subscription responses for mailboxes in the group.

  • Se houver mais de 200 assinaturas para o grupo, crie várias solicitações.If more than 200 subscriptions exist for the group, create multiple requests. O número máximo de valores de SubscriptionId a serem incluídos em uma solicitação é 200.The maximum number of SubscriptionId values to include in a request is 200.

  • Se você precisar de mais conexões do que as disponíveis para a caixa de correio de destino, use a conta de serviço para representar a caixa de correio de ancoragem para o grupo; caso contrário, não use representação.If you need more connections than are available to the target mailbox, use the service account to impersonate the anchor mailbox for the group; otherwise, do not use impersonation. O ideal é que você queira representar uma caixa de correio exclusiva por solicitação GetStreamingEvents ou GetEvents para que você nunca encontre limites de limitação.Ideally, you want to impersonate a unique mailbox per GetStreamingEvents or GetEvents request so that you never encounter throttling limits.

  • Use ApplicationImpersonation se você precisar de mais conexões do que estão disponíveis para a caixa de correio de destino; caso contrário, não use ApplicationImpersonation.Use ApplicationImpersonation if you need more connections than are available to the target mailbox; otherwise, do not use ApplicationImpersonation.

  • Inclua o cabeçalho X-PreferServerAffinity e defina-o como true.Include the X-PreferServerAffinity header and set it to true. Esse valor será incluído automaticamente se você estiver usando o objeto ExchangeService que você criou na etapa 2.This value is automatically included if you are using the ExchangeService object that you created in step 2.

  • Inclua o X-BackEndOverrideCookie para o grupo (o X-BackEndOverrideCookie que foi retornado na resposta de assinatura do usuário da caixa de correio de ancoragem).Include the X-BackEndOverrideCookie for the group (the X-BackEndOverrideCookie that was returned in the anchor mailbox user's subscription response). Esse valor será incluído automaticamente se você estiver usando o objeto ExchangeService que você criou na etapa 2.This value is automatically included if you are using the ExchangeService object that you created in step 2.

  1. Passe os eventos retornados para um thread separado para processamento.Pass the returned events to a separate thread for processing.

Que valores de limitação Eu preciso considerar?What throttling values do I need to take into consideration?

Ao planejar sua implementação de notificação, você deverá levar em consideração dois valores: o número de conexões e o número de assinaturas.As you plan your notification implementation, you'll want to take two values into consideration: the number of connections, and the number of subscriptions. A tabela a seguir lista os valores padrão para cada configuração de limitação e como as configurações são usadas.The following table lists the default values for each throttling setting and how the settings are used. Para cada valor, o orçamento é alocado para a caixa de correio de destino.For each value, the budget is allocated to the target mailbox. Por esse motivo, usar a representação para obter conexões adicionais é uma etapa obrigatória em muitos cenários.For this reason, using impersonation to gain additional connections is a required step in many scenarios.

Tabela 1. Valores de limitação padrãoTable 1. Default throttling values

Área de consideraçãoArea of consideration Configuração de limitaçãoThrottling setting Valor padrãoDefault value DescriçãoDescription
Conexões de streamingStreaming connections
Limite de conexão deslocada padrãoDefault hanging connection limit
10 para o Exchange Online10 for Exchange Online
3 para o Exchange 20133 for Exchange 2013
O número máximo de conexões de fluxo simultâneos que uma conta pode ter aberto no servidor de uma só vez.The maximum number of concurrent streaming connections that an account can have open on the server at one time. Para trabalhar dentro desse limite, use uma conta de serviço com a função ApplicationImpersonation atribuída às caixas de correio de destino e represente o primeiro usuário em cada grupo de ID de assinatura ao obter eventos em fluxo.To work within this limit, use a service account with the ApplicationImpersonation role assigned for the target mailboxes, and impersonate the first user in each subscription ID group when getting streamed events.
Conexões pull ou pushPull or push connections
EWSMaxConcurrencyEWSMaxConcurrency
2727
O número máximo de conexões simultâneas de pull ou push (solicitações que foram recebidas, mas que ainda não responderam a) que uma conta pode ter aberto no servidor ao mesmo tempo.The maximum number of concurrent pull or push connections (requests that have been received but not yet responded to) that an account can have open on the server at one time.
AssinaturasSubscriptions
EWSMaxSubscriptionsEWSMaxSubscriptions
20 para o Exchange Online20 for Exchange Online
5000 para o Exchange 20135000 for Exchange 2013
O número máximo de assinaturas não expiradas que uma conta pode ter ao mesmo tempo.The maximum number of nonexpired subscriptions that an account can have at one time. Esse valor é decrementado quando a assinatura é criada no servidor.This value is decremented when the subscription is created on the server.

O exemplo a seguir mostra como os orçamentos são tratados entre qualquer caixa de correio de destino e a conta de serviço que tem a função ApplicationImpersonation atribuída às caixas de correio de destino.The following example shows how budgets are handled between any target mailbox and the service account that has the ApplicationImpersonation role assigned for the target mailboxes.

  • ServiceAccount1 (SA1) representa muitos usuários (M1, m2, M3 e assim por diante) e cria assinaturas para cada caixa de correio.ServiceAccount1 (sa1) impersonates many users (m1, m2, m3, and so on) and creates subscriptions for each mailbox. Observe que, quando as assinaturas são criadas, o proprietário da assinatura é SA1, portanto, quando SA1 abre uma conexão com as assinaturas, o EWS impõe que as assinaturas sejam de Propriedade do SA1.Note that when the subscriptions are created, the subscription owner is sa1, so when sa1 opens a connection with the subscriptions, EWS enforces that the subscriptions are owned by sa1.

  • O Sa1 pode abrir a conexão das seguintes maneiras:Sa1 can open the connection in the following ways:

  1. Sem representação, portanto, a conexão é cobrada em relação ao SA1.Without impersonation, so the connection is charged against sa1.

  2. Ao representar qualquer um dos usuários — M1, por exemplo, para que a conexão seja cobrada por uma cópia do orçamento do m1's.By impersonating any of the users — m1 for example — so that the connection is charged against a copy of m1's budget. (O próprio M1 pode abrir dez conexões usando o Exchange Online e todas as contas de serviço que estão representando M1 podem abrir dez conexões usando o orçamento copiado.)(M1 itself can open ten connections by using Exchange Online, and all service accounts impersonating m1 can open ten connections by using the copied budget.)

  • Se o limite de conexão for atingido, as seguintes soluções alternativas estarão disponíveis:If the connection limit is hit, the following workarounds are available:

    • Se a opção 1 for usada, o administrador pode criar várias contas de serviço para representar usuários adicionais.If option 1 is used, the administrator can create multiple service accounts to impersonate additional users.

    • Se a opção 2 for usada, o código pode representar outro usuário, m2, por exemplo.If option 2 is used, the code can impersonate another user — m2 for example.

Exemplo: manutenção da afinidade entre um grupo de assinaturas e o servidor de caixa de correioExample: Maintaining affinity between a group of subscriptions and the Mailbox server

Ok, vamos vê-lo em ação.Okay, let's see it in action. O exemplo de código a seguir mostra como agrupar usuários e usar os cabeçalhos x-AnchorMailbox e X-PreferServerAffinity e o cookie X-BackendOverrideCookie para manter a afinidade com o servidor de caixa de correio.The following code example shows you how to group users and use the X-AnchorMailbox and X-PreferServerAffinity headers and the X-BackendOverrideCookie cookie to maintain affinity with the Mailbox server. Como os cabeçalhos e o cookie são de importância principal na história da afinidade, este exemplo se concentra nas solicitações e respostas XML do EWS.Because the headers and the cookie are of primary importance in the affinity story, this example focuses on the EWS XML requests and responses. Para usar a API gerenciada do EWS para criar o corpo das solicitações de assinatura e respostas, consulte Stream notifications about Mailbox Events by using EWS in Exchange and pull notifications about Mailbox Events by using the EWS in Exchange.To use the EWS Managed API to create the body of the subscription requests and responses, see Stream notifications about mailbox events by using EWS in Exchange and Pull notifications about mailbox events by using EWS in Exchange. Esta seção inclui etapas adicionais específicas para manter a afinidade e adicionar os cabeçalhos às suas solicitações.This section includes additional steps particular to maintaining affinity and adding the headers to your requests.

Este exemplo tem quatro usuários: alfred@contoso.com, alisa@contoso.com, ronnie@contoso.com e sadie@contoso.com.This example has four users: alfred@contoso.com, alisa@contoso.com, ronnie@contoso.com, and sadie@contoso.com. A figura a seguir mostra as configurações de descoberta automática do GroupingInformation e do ExternalEwsUrl para os usuários.The following figure shows the GroupingInformation and ExternalEwsUrl Autodiscover settings for the users.

Figura 1. Configurações de descoberta automática usadas para agrupar caixas de correioFigure 1. Autodiscover settings used to group mailboxes

A table that shows the GroupingInformation and ExternalEwsUrl values for each of the users.

Usando as configurações das respostas de descoberta automática, as caixas de correio são agrupadas pelo valor concatenado das configurações GroupingInformation e ExternalEwsUrl.Using the settings from the Autodiscover responses, the mailboxes are grouped by the concatenated value of the GroupingInformation and ExternalEwsUrl settings. Neste exemplo, Alfred e Sadie têm os mesmos valores, portanto, estão em um grupo, e alisa e Ronnie compartilham os mesmos valores, portanto, estão em outro grupo.In this example, Alfred and Sadie have the same values, so they are in one group, and Alisa and Ronnie share the same values, so they are in another group.

Figura 2. Criando grupos de caixa de correioFigure 2. Creating mailbox groups

A table that shows how mailbox groups are created using Autodiscover settings.

Para o objetivo deste exemplo, vamos nos concentrar no grupo A. Devemos usar as mesmas etapas para o grupo B, mas usar um valor X-AnchorMailbox diferente para esse grupo.For the purpose of this example, we'll focus on Group A. We would use the same steps for group B, but use a different X-AnchorMailbox value for that group.

Usando o ApplicationImpersonation, crie a solicitação de assinatura da caixa de correio de âncora (Alfred@contoso.com), com o cabeçalho X-AnchorMailbox definido para o endereço de email e um valor de cabeçalho x-PreferServerAffinity de true.Using ApplicationImpersonation, create the subscription request for the anchor mailbox (alfred@contoso.com), with the X-AnchorMailbox header set to the their email address and an X-PreferServerAffinity header value of true. A definição desses dois valores de cabeçalho disparará o servidor para criar um X-BackEndOverrideCookie para a resposta.Setting these two header values will trigger the server to create an X-BackEndOverrideCookie for the response.

Se você estiver usando a API gerenciada do EWS, use o métodoAdd HttpHeaderspara adicionar os dois cabeçalhos à sua solicitação de assinatura, conforme mostrado.If you're using the EWS Managed API, use the HttpHeadersAdd method to add the two headers to your subscription request, as shown.

service.HttpHeaders.Add("X-AnchorMailbox", Mailbox.SMTPAddress);
service.HttpHeaders.Add("X-PreferServerAffinity", "true");

Portanto, a solicitação de assinatura do Alfred tem a seguinte aparência.So Alfred's subscription request looks like this.

POST https://outlook.office365.com/EWS/Exchange.asmx HTTP/1.1
Content-Type: text/xml; charset=utf-8
Accept: text/xml
User-Agent: ExchangeServicesClient/15.00.0516.014
X-AnchorMailbox: alfred@contoso.com
X-PreferServerAffinity: true
Host: outlook.office365.com
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2013" />
    <t:ExchangeImpersonation>
      <t:ConnectingSID>
        <t:SmtpAddress>alfred@contoso.com</t:SmtpAddress>
      </t:ConnectingSID>
    </t:ExchangeImpersonation>
  </soap:Header>
  <soap:Body>
    <m:Subscribe>
      <m:StreamingSubscriptionRequest>
        <t:FolderIds>
          <t:DistinguishedFolderId Id="inbox" />
        </t:FolderIds>
        <t:EventTypes>
          <t:EventType>NewMailEvent</t:EventType>
        </t:EventTypes>
      </m:StreamingSubscriptionRequest>
    </m:Subscribe>
  </soap:Body>
</soap:Envelope>

A seguinte mensagem XML é a resposta à solicitação de assinatura do Alfred e inclui o X-BackEndOverrideCookie.The following XML message is the response to Alfred's subscription request, and it includes the X-BackEndOverrideCookie. Reenvie este cookie para todas as solicitações subsequentes para os usuários deste grupo.Resend this cookie for all subsequent requests for users in this group. Observe que a resposta também contém cookies adicionais, como o cookie exchangecookie usado pelo Exchange 2010.Notice that the response also contains additional cookies, such as the exchangecookie cookie used by Exchange 2010. Exchange Online, Exchange Online como parte do Office 365 e versões do Exchange a partir do Exchange 2013, ignore exchangecookie se estiver incluído em solicitações de assinatura subsequentes.Exchange Online, Exchange Online as part of Office 365, and versions of Exchange starting with Exchange 2013, ignore exchangecookie if it is included in subsequent subscription requests.

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Set-Cookie: exchangecookie=ddb8c383aef34c7694132aa679744feb; expires=Thu, 25-Sep-2014 18:42:45 GMT; path=/;
    HttpOnly
Set-Cookie: X-BackEndOverrideCookie=CO1PR06MB222.namprd06.prod.outlook.com~1941996295; path=/; secure; HttpOnly
Set-Cookie: X-BackEndCookie=alfred@contoso.com=Ox8XKzcXLxg==; 
    expires=Wed, 25-Sep-2013 18:52:49 GMT; path=/EWS; secure; HttpOnly
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:ServerVersionInfo MajorVersion="15"
                         MinorVersion="0"
                         MajorBuildNumber="775"
                         MinorBuildNumber="7"
                         Version="V2_4"
                         xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"
                         xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
                         xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <m:SubscribeResponse xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
                         xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">
      <m:ResponseMessages>
        <m:SubscribeResponseMessage ResponseClass="Success">
          <m:ResponseCode>NoError</m:ResponseCode>
          <m:SubscriptionId>JgBjbzFwcjA2bWIyMjIubmFtcHJkMDYucHJvZC5vdXRsb29rLmNvbRAAAAAUeGk+7JFdSaFM8/NI/gQQpVdgZX6H0Ag=</m:SubscriptionId>
        </m:SubscribeResponseMessage>
      </m:ResponseMessages>
    </m:SubscribeResponse>
  </s:Body>
</s:Envelope>

Usando o X-BackEndOverrideCookie da resposta de Alfred e o cabeçalho X-AnchorMailbox, a solicitação de assinatura é criada para o Sadie, o outro membro da solicitação de assinatura de grupo A. Sadie tem a seguinte aparência.Using the X-BackEndOverrideCookie from Alfred's response and the X-AnchorMailbox header, the subscription request is created for Sadie, the other member of Group A. Sadie's subscription request looks like this.

POST https://outlook.office365.com/EWS/Exchange.asmx HTTP/1.1
Content-Type: text/xml; charset=utf-8
Accept: text/xml
User-Agent: ExchangeServicesClient/15.00.0516.014
X-AnchorMailbox: alfred@contoso.com
X-PreferServerAffinity: true
Host: outlook.office365.com
Cookie: X-BackEndOverrideCookie=CO1PR06MB222.namprd06.prod.outlook.com~1941996295
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2013" />
    <t:ExchangeImpersonation>
      <t:ConnectingSID>
        <t:SmtpAddress>sadie@contoso.com </t:SmtpAddress>
      </t:ConnectingSID>
    </t:ExchangeImpersonation>
  </soap:Header>
  <soap:Body>
    <m:Subscribe>
      <m:StreamingSubscriptionRequest>
        <t:FolderIds>
          <t:DistinguishedFolderId Id="inbox" />
        </t:FolderIds>
        <t:EventTypes>
          <t:EventType>NewMailEvent</t:EventType>
        </t:EventTypes>
      </m:StreamingSubscriptionRequest>
    </m:Subscribe>
  </soap:Body>
</soap:Envelope>

A resposta de assinatura do Sadie tem a seguinte aparência.Sadie's subscription response looks like this. Observe que ele não inclui o X-BackEndOverrideCookie.Note that it does not include the X-BackEndOverrideCookie. O cliente é responsável por armazenar em cache esse valor para solicitações futuras.The client is responsible for caching that value for future requests.

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Set-Cookie: exchangecookie=640ea858f69d47ff8cce8b44c337f6d9; path=/
Set-Cookie: X-BackEndCookie=alfred@contoso.com=Ox8XKzcXLxg==; 
   expires= Wed, 25-Sep-2013 18:53:06 GMT; path=/EWS; secure; HttpOnly
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:ServerVersionInfo MajorVersion="15"
                         MinorVersion="0"
                         MajorBuildNumber="775"
                         MinorBuildNumber="7"
                         Version="V2_4"
                         xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"
                         xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
                         xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <m:SubscribeResponse xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
                         xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">
      <m:ResponseMessages>
        <m:SubscribeResponseMessage ResponseClass="Success">
          <m:ResponseCode>NoError</m:ResponseCode>
          <m:SubscriptionId>JgBjbzFwcjA2bWIyMjIubmFtcHJkMDYucHJvZC5vdXRsb29rLmNvbRAAAAB4EQOy2pfrQJfM3hzs/nZJIZssan6H0Ag=</m:SubscriptionId>
        </m:SubscribeResponseMessage>
      </m:ResponseMessages>
    </m:SubscribeResponse>
  </s:Body>
</s:Envelope>

Usando os valores SubscriptionId das respostas de assinatura, uma solicitação de operação GetStreamingEvents foi criada para todas as assinaturas do grupo.Using the SubscriptionId values from the subscription responses, a GetStreamingEvents operation request was created for all the subscriptions in the group. Como há menos de 200 assinaturas nesse grupo, todas elas são enviadas em uma solicitação.Because there are less than 200 subscriptions in this group, they are all sent in one request. O cabeçalho X-PreferServerAffinity é definido como true e o X-BackEndOverrideCookie está incluído.The X-PreferServerAffinity header is set to true and the X-BackEndOverrideCookie is included.

POST https://outlook.office365.com/EWS/Exchange.asmx HTTP/1.1
Content-Type: text/xml; charset=utf-8
Accept: text/xml
User-Agent: ExchangeServicesClient/15.00.0516.014
X-AnchorMailbox: alfred@contoso.com
X-PreferServerAffinity: true
Host: outlook.office365.com
Cookie: X-BackEndOverrideCookie=CO1PR06MB222.namprd06.prod.outlook.com~1941996295
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2013" />
    <t:ExchangeImpersonation>
      <t:ConnectingSID>
        <t:SmtpAddress>sadie@contoso.com</t:SmtpAddress>
      </t:ConnectingSID>
    </t:ExchangeImpersonation>
  </soap:Header>
  <soap:Body>
    <m:GetStreamingEvents>
      <m:SubscriptionIds>
        <t:SubscriptionId>JgBjbzFwcjA2bWIyMjIubmFtcHJkMDYucHJvZC5vdXRsb29rLmNvbRAAAAB4EQOy2pfrQJfM3hzs/nZJIZssan6H0Ag=</t:SubscriptionId>
        <t:SubscriptionId>JgBjbzFwcjA2bWIyMjIubmFtcHJkMDYucHJvZC5vdXRsb29rLmNvbRAAAAAUeGk+7JFdSaFM8/NI/gQQpVdgZX6H0Ag=</t:SubscriptionId>
      </m:SubscriptionIds>
      <m:ConnectionTimeout>10</m:ConnectionTimeout>
    </m:GetStreamingEvents>
  </soap:Body>
</soap:Envelope>

Os eventos retornados são passados para um thread separado para processamento.The returned events are then passed to a separate thread for processing.

Como a afinidade foi alterada?How has affinity changed?

No Exchange 2010, as assinaturas são mantidas no servidor de acesso para cliente, conforme mostrado na Figura 3.In Exchange 2010, subscriptions are maintained on the Client Access server, as shown in Figure 3. Nas versões do Exchange posteriores ao Exchange 2010, as assinaturas são mantidas no servidor de caixa de correio, conforme mostrado na Figura 4.In versions of Exchange later than Exchange 2010, subscriptions are maintained on the Mailbox server, as shown in Figure 4.

Figura 3. Processo de manutenção da afinidade no Exchange 2010Figure 3. Process for maintaining affinity in Exchange 2010

An illustration that shows how the table of active subscriptions is maintained on the Client Access server in Exchange 2010.

Figura 4. Processo para manter a afinidade no Exchange Online e no Exchange 2013Figure 4. Process for maintaining affinity in Exchange Online and Exchange 2013

An illustration that shows how the load balancer and the Client Access server route requests to the mailbox server that maintains the table of active subscriptions in Exchange Server and Exchange Online.

No Exchange 2010, o cliente só conhece o endereço do balanceador de carga e o exchangecookie retornado pelo servidor garante que a solicitação seja encaminhada para o servidor de acesso para cliente certo.In Exchange 2010, the client only knows the address of the load balancer, and the exchangecookie that is returned by the server ensures that the request is routed to the right Client Access server. No entanto, em versões posteriores, as funções de servidor de acesso para cliente e o balanceador de carga devem rotear as solicitações apropriadamente antes de chegarem ao servidor de caixa de correio.However, in later versions, the load balancer and the Client Access server roles both have to route the requests appropriately before they get to the Mailbox server. Para fazer isso, são necessárias informações adicionais, que é o motivo pelo qual os novos cabeçalhos e cookie foram introduzidos.To do that, additional information is required, which is why the new headers and cookie were introduced. O artigo inscrições de notificação, eventos de caixa de correio e EWS no Exchange explica como as assinaturas são mantidas no Exchange 2013.The article Notification subscriptions, mailbox events, and EWS in Exchange explains how subscriptions are maintained in Exchange 2013.

Você pode notar que o exchangecookie que o Exchange 2010 usa ainda é retornado por versões posteriores.You might notice that the exchangecookie that Exchange 2010 uses is still returned by later versions. Não há danos em incluir esse cookie em solicitações, mas as versões posteriores do Exchange o ignoram.There's no harm in including this cookie in requests, but later versions of Exchange ignore it.

Confira tambémSee also