Design for an enterprise scale Exchange 2013 OAB

Design for an enterprise scale Exchange 2013 OAB

Today we will be discussing how to design your Exchange 2013 Offline Address Book (OAB) for an enterprise scale client.  By enterprise scale client we mean a client with thousands of mailboxes spread over multiple Active Directory sites.

See our previous post “Exchange Global Address List and the Outlook Offline Address Book” to clear up any confusion between the OAB and the Global Address List (GAL).

How has the OAB design changed?

Before we delve into the design, let’s first look at how the OAB has changed from Exchange 2010 to Exchange 2013.  The diagram below depicts the flow for an Exchange 2010 organization.

Exchange 2010 Offline Address Book Design

There is a single hard coded OAB generation server which reads the GAL from Active Directory based on a schedule that you can get using Get-OfflineAddressBook.  The Client Access Servers poll for changes and utilise the File Distribution Service to copy that OAB from the generation server to the CAS.  The list of Client Access Servers that do this polling can be set by changing the VirtualDirectories attribute of the Set-OfflineAddressBook cmdlet and the polling interval can be set by changing the PollInterval attribute of the Set-OABVirtualDirectory cmdlet.  Finally the Outlook client itself polls for changes to the OAB every 24 hours, or within about 5 minutes of starting.

As you can see the above process has a single point of failure.  i.e. if the OAB generation server fails and you change the config to use a new OAB generation server, then a brand new OAB will be generated and every CAS server will download that full copy, but what is even worse is that every Outlook client will download a full fresh OAB.  Now if you have an OAB for 1000 mailboxes that’s likely to be pretty insignificant, however if you have over 100,000 mailboxes then the OAB can be quite a few MB even when compressed.

So how did Exchange 2013 improve this?  Let’s only talk about Exchange 2013 CU5 and later, since before then there was a design flaw which could prove to be even more horrendous than the Exchange 2010 design.  In Exchange 2013 the OAB lives in an arbitration mailbox rather than on disk.  Now that simple change means that the mailbox will fail over as part of the DAG.  Brilliant so that’s one part solved.  The next aspect they changed is the CAS server polling for changes and copying them.  Instead now the Frontend server proxies the request to the server that is hosting the OAB’s arbitration mailbox.  The diagram below shows these two changes.

Exchange 2013 Offline Address Book Design

Right so that’s a bit about how the OAB flow has changed as we move to Exchange 2013.

Being mindful of migrations from Exchange 2010

One thing to be mindful of is that as you migrate from Exchange 2010 to Exchange 2013, a 2013 frontend server will prefer the 2013 OAB.  This means that if you are not careful when you add the first Exchange 2013 server into an AD site that has Exchange 2010 mailbox users, then this 2013 server will tell users to download a full fresh OAB.  Again not an issue for only a handful of users but if the site hosts 10,000 users that can be a massive problem.

To prevent this simply ensure that every mailbox database has the Offline Address Book set to the default address book

Get-MailboxDatabase | Set-MailboxDatabase -OfflineAddressBook "\Default Offline Address Book"

How can we leverage this new design?

Now for a large organization having a single OAB in a single arbitration mailbox isn’t so useful, since now there is all of this WAN traffic going on as Frontend servers worldwide proxy requests to the OAB’s arbitration mailbox server.

Luckily Exchange allows us to create additional Offline Address Books and additional arbitration mailboxes.  Before we start creating arbitration mailboxes and OABs all over the place, here are some simple rules:

  1. Create a single OAB per AD site (or collection of sites if you have a multi-site DAG setup)
  2. Assign each mailbox database the OAB it should use from that same site

So if you have a DAG that is spread over 4 AD sites (and therefore you have very good connectivity between these sites in order for replication to function properly), then create an OAB within one of the 4 AD sites.  You could create more but then failover scenarios get pretty complex since a mailbox or mailbox database can only be assigned a single OAB and an OAB can only be within a single arbitration mailbox.

How do you create a new OAB and arbitration mailbox?

step 1: Create the new arbitration mailbox

New-Mailbox -Arbitration -Name "OAB for DE" -Database DE01-DB04 -UserPrincipalName oab-de@contoso.com –DisplayName "OAB for DE"

step 2: Enable the new arbitration mailbox for OAB generation

Set-Mailbox "OAB for DE" –Arbitration –OABGen $true

step 3: Create a new OAB and assign it to the new Arbitration Mailbox

New-OfflineAddressBook -Name "OAB for DE" –GeneratingMailbox "CN=OAB for DE,CN=Users,DC=contoso,DC=com" –AddressLists "Default Global Address List"

step 4: Assign the new OAB to the mailbox databases

Get-MailboxDatabase DE* | Set-MailboxDatabase -OfflineAddressBook "OAB for DE"

This can be repeated for each AD site (or collection of AD sites) until your entire enterprise is covered with OAB arbitration mailbox to service their local clients. When a user travels then the Frontend server they talk to will still proxy the request over the WAN to the correct arbitration mailbox server, but that is minimal compared to full downloads or everyone having to proxy to a single arbitration mailbox.

How do we control the generation time?

One interesting gotcha is that the schedule on Get/Set-OfflineAddressBook is no longer used for Exchange 2013.  Instead there are two attributes on Get/Set-MailboxServer that are used.  For this reason it is vital that ALL mailbox servers in a DAG have the same settings, otherwise the OAB will be generated differently depending on failover conditions.

These two attributes are called OABGeneratorWorkCycle and OABGeneratorWorkCycleCheckpoint.  Now these are workload parameters, since Exchange 2013 has moved to workload based multi-threading.  This means that each thread is assigned a priority (for OAB this is low) and as long as there are enough resources then Exchange will run these threads.  The OABGeneratorWorkCycle tells Exchange that we’d like the OAB generation cycle the be completed within that time period.  The OABGeneratorWorkCycleCheckpoint tells Exchange how often we’d like it to check for anything new to do.

So the default of 1 day for each of those two settings tells Exchange we want it to check for new/changed users every day and we’re ok for it to take up to a day to complete that processing.  If we change the checkpoint attribute to say 4 hours then Exchange will check for new/changed users every 4 hours and as long as the generation process itself doesn’t exceed 4 hours, the end result will be that a fresh OAB is generated every 4 hours.  If the server is busy then it may take longer to finish a single cycle (since we’ve still left the OABGeneratorWorkCycle to 1 day) so worst case a new OAB should be generated daily.

If we change the OABGeneratorWorkCycle to less than the time it actually takes an idle server to generate the OAB then Exchange will go to best efforts basis, and will work as quickly as it can without affecting any higher priority tasks.

In summary

So summarising all of this…  The Exchange 2013 OAB design is leaps and bounds better than Exchange 2010 and will be less prone to failure, although the generation settings being on the mailbox server is something to bear in mind.  The use of workload parameters rather than a schedule makes it impossible to predict when a new OAB will be generated but the process will not interfere with regular tasks like mail routing, mail access, etc.

The big killer feature is the ability to control where the generation of the OAB happens in various places on the network to avoid issues on the WAN especially when full OAB downloads are needed for upgrades or client profile rebuilds.