{"id":2023,"date":"2011-12-11T06:43:09","date_gmt":"2011-12-11T06:43:09","guid":{"rendered":"https:\/\/poiseddevelopers.com\/reality-tech\/?p=2023"},"modified":"2024-04-12T10:00:24","modified_gmt":"2024-04-12T10:00:24","slug":"rbs-remote-blob-storage-part-3","status":"publish","type":"post","link":"https:\/\/poiseddevelopers.com\/reality-tech\/rbs-remote-blob-storage-part-3\/","title":{"rendered":"RBS (Remote Blob Storage) part 3"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_65 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title \" >Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 eztoc-toggle-hide-by-default' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/poiseddevelopers.com\/reality-tech\/rbs-remote-blob-storage-part-3\/#Overview\" title=\"Overview\">Overview<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/poiseddevelopers.com\/reality-tech\/rbs-remote-blob-storage-part-3\/#Specific_steps\" title=\"Specific steps\">Specific steps<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/poiseddevelopers.com\/reality-tech\/rbs-remote-blob-storage-part-3\/#Tuning_the_internal_Maintainer_parameters\" title=\"Tuning the internal Maintainer parameters\">Tuning the internal Maintainer parameters<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/poiseddevelopers.com\/reality-tech\/rbs-remote-blob-storage-part-3\/#Tips\" title=\"Tips\">Tips<\/a><\/li><\/ul><\/nav><\/div>\n<p>A configured and running Remote Blob Storage (RBS) is a ticking time bomb until you\u2019ve configured the Maintainer to run. That\u2019s because RBS is designed to leave a trail of unused objects in its wake. RBS counts on a periodic process to run to eliminate all these unused objects. If you save a file in SharePoint a dozen times, even with versioning disabled, each save will leave a blob object behind, largely for performance reasons.<\/p>\n<p>Setting up Maintainer to run is not easy; which is compounded by skimpy and inconsistent documentation.<\/p>\n<p>Microsoft\u2019s documentation indicates that Encryption is not required if a Trusted connection is used. However I have found Encryption was required, with Maintainer complaining if the connection string was unencrypted.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Overview\"><\/span>Overview<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>To configure the Maintainer, the following steps must be carefully done:<br role=\"presentation\" data-uw-rm-sr=\"\" \/>1. Decrypt Connection string, if needed<br role=\"presentation\" data-uw-rm-sr=\"\" \/>2. Define each connection string in the config file; all connections are defined in this one file<br role=\"presentation\" data-uw-rm-sr=\"\" \/>3. Encrypt the connection strings within the config file<br role=\"presentation\" data-uw-rm-sr=\"\" \/>4. Run the Maintainer for each connection, referencing each connection by name<\/p>\n<p>Let\u2019s go through these step by step. First establish the locations of some key components. I like to put shortcuts to each on the desktop that open in a CMD window. If you do this, you\u2019ll thank me that you did. For me it was:<\/p>\n<p>Maintainer location:<br role=\"presentation\" data-uw-rm-sr=\"\" \/>C:Program FilesMicrosoft SQL Remote Blob Storage 10.50Maintainer<\/p>\n<p>.NET framework location:<br role=\"presentation\" data-uw-rm-sr=\"\" \/>C:WindowsMicrosoft.NETFrameworkv2.0.50727<\/p>\n<p>This is the utility to encrypt and decrypt connection strings. It only works against files named \u201cweb.config\u201d, so we will need to do a fair amount of file renaming along the way.<br role=\"presentation\" data-uw-rm-sr=\"\" \/>aspnet_regiis.exe<\/p>\n<p>Command to encrypt a connection string, from Maintainer directory and rename it back:<\/p>\n<pre>C:WindowsMicrosoft.NETFrameworkv2.0.50727aspnet_regiis.exe -pef connectionStrings . -prov DataProtectionConfigurationProvider\r\n RENAME web.config Microsoft.Data.SqlRemoteBlobs.Maintainer.exe.config<\/pre>\n<p>Alternatively, you can run the command to encrypt the connection string from the .NET directory:<\/p>\n<pre>aspnet_regiis.exe -pef connectionStrings . -prov DataProtectionConfigurationProvider\r\n RENAME \"C:Program FilesMicrosoft SQL Remote Blob Storage 10.50Maintainerweb.config\" \"C:Program FilesMicrosoft SQL Remote Blob Storage 10.50MaintainerMicrosoft.Data.SqlRemoteBlobs.Maintainer.exe.config\"<\/pre>\n<p>To decrypt from the Maintainer directory:<\/p>\n<pre>C:WindowsMicrosoft.NETFrameworkv2.0.50727aspnet_regiis.exe -pdf connectionStrings .<\/pre>\n<p>This is the command to start maintainer, referencing the PATH variable:<\/p>\n<pre>%programfiles%Microsoft SQL Remote Blob Storage 10.50MaintainerMicrosoft.Data.SqlRemoteBlobs.Maintainer.exe -ConnectionStringName RBSMaintainerConnection   -Operation GarbageCollection ConsistencyCheck  ConsistencyCheckForStores -GarbageCollectionPhases rdo -ConsistencyCheckMode r -TimeLimit 120\r\nMicrosoft.Data.SqlRemoteBlobs.Maintainer.exe -ConnectionStringName RBSMaintainerConnection   -Operation GarbageCollection ConsistencyCheck  ConsistencyCheckForStores -GarbageCollectionPhases rdo -ConsistencyCheckMode r -TimeLimit 120<\/pre>\n<p>You will want to decrypt and re-encrypt multiple times to make sure the Go to .NET directory. Some suggestions:<\/p>\n<ol>\n<li>run from .NET directory<\/li>\n<li>rename the maintainer config file first to web.config<br role=\"presentation\" data-uw-rm-sr=\"\" \/>REN Microsoft.Data.SqlRemoteBlobs.Maintainer.exe.config web.config<\/li>\n<li>If the web.config file has an empty connectionstring, then the filename\/directory was incorrect<\/li>\n<li>Review and tweak the connection string<\/li>\n<li>after encryption, rename back:<br role=\"presentation\" data-uw-rm-sr=\"\" \/>REN web.config Microsoft.Data.SqlRemoteBlobs.Maintainer.exe.config<\/li>\n<\/ol>\n<p>Decrypt to examine (the \u201cd\u201d in -pdf is \u201cDecrypt\u201d): aspnet_regiis.exe -pdf connectionStrings \u201c%programfiles%Microsoft SQL Remote Blob Storage 10.50Maintainer\u201d<\/p>\n<p>Encryption of connection string within Maintainer config file; run from .NET directory (the \u201ce\u201d in -pef is \u201cEncrypt\u201d):<\/p>\n<pre>aspnet_regiis -pef connectionStrings \"%programfiles%Microsoft SQL Remote Blob Storage 10.50Maintainer\" -prov DataProtectionConfigurationProvider<\/pre>\n<p>This is the command to start the Maintainer:<\/p>\n<pre>Microsoft.Data.SqlRemoteBlobs.Maintainer.exe -ConnectionStringName RBSMaintainerConnection -Operation GarbageCollection ConsistencyCheck  ConsistencyCheckForStores -GarbageCollectionPhases rdo -ConsistencyCheckMode r -TimeLimit 120<\/pre>\n<p>Note that the cofiguration file used by the Maintainer is called \u201d Microsoft.Data.SqlRemoteBlobs.Maintainer.exe.config\u201d.<\/p>\n<p>Here it is with the connection string unencrypted. A few things to note:<\/p>\n<ol>\n<li>\u201cApplication Name=\u201d\u2026 must use the &amp;quot and the name in those quotes. This is essential. Changing &amp;quot to an actual quote causes the request to fail.<\/li>\n<\/ol>\n<pre><\/pre>\n<p>The connection string must be encrypted for it to work, here it is below encrypted. Note the EncryptedData and CipherData tags:<\/p>\n<pre>    \r\n             AQAAANCMnd8BFdERjHoAwE\/Cl+sBAAAAvyx0EESER0Kn9Ui9t9ZzcgQAAAACAAAAAAADZgAAwAAAABAAAAA1gYCb5s1usLg\/P7uwA7TmAAAAAASAAACgAAAAEAAAACVQO6o7eVm\/lmikyJUtSeRIAgAAX5uFsFeWOEZQycBwOhxJmFN11JFnTdM+PycItclQJYk90gQZhZ2B7E6bf6h3MovJB\/jnWM4cEKbOG3w+9pPPEbAuk9c7Y+zQj4atoHdnlNX1D0kKge39A1LQK+C+JQ575bx4TWVI\/Zl5Edc5hbLWt+IifMytGHrZ4MHHENQOR3S001yMtBlaISuPQVa1DUDpzoBS3rpTDej2UAmHmBIjtHF1vXfmBz6R+p2xdQlpBajPRLOfQ28gXoT25HrpEyKTZtWyeFyWcYslqm7msowJ6FOP7iwatY9\/H9LkvWj0pAegHUQrmaCJnl9M+xGGiOigNeBe1o20tQFxYrW4RIJ\/MSOrTZthbccAaRMmgoR8PjMBNOAzE3eDMihGCpeEFtIxSDYZnT7OCuAkSCmqCWqLpDAJyqCmUJbCRrttU2xo7VnfCCGACzI4jfOHWVIFKYaIIfPFD6KVeDSdBDt9J4xeR\/sE5HV6Jcugcm8yAcW1CIq6\/w5QwfjSN20pjzOHXo9SFukhMJPJIWTf0GnGuwEdO2ci4a6mL0Y8me6BhZxpc3228Hegp+C7\/3p3kyrm0H93GwNTB2XkdUajg8K62buGve\/OLwIbgLH3pG1jkyhkgm1l5W\/CC8lA\/6QsdNiLTWHB4fq1AsbxpEIGgOy9sDvJmL3dvcaOeMpMv5g9mVetbYvE0D+WsZVH+ILBeZ0HwsZ4kty3E+5yVTG3TlkQ48j07e8QjE3o4xYv\/j5bSB7T+2Udlsi1rlNy93C1iggCfDrGCfpnhhMn5ZsUAAAACeMf9OAnNDQzMKpZ4HseVXcUBpg=\r\n            \r\n<\/pre>\n<h2><span class=\"ez-toc-section\" id=\"Specific_steps\"><\/span>Specific steps<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The connection string in the Maintainer are specified in the maintainer.exe.config file. This file has to co-exist with the executable. The connection string are either all encrypted or none. The default connection string that the RBS specifies is always encrypted and its a good practice to encrypt the connection strings .<\/p>\n<p>At first glance, the documentation is not clear on where Maintainer should be run. My findings indicate it should be configured on a single WFE (Web Front End) SharePoint server.<\/p>\n<p>Documentation does not indicate it, but I found a special name=tag needed to be added for each connection string, and it needs to be referenced when running the command. On the command line, for each database that the Maintainer needs to be run for, the ConnectionStringName parameter needs to be set to a corresponding Name= in the XML. This matching reference is what connects the command line Maintainer call to the specific connection to a database. depending on how RBS was installed, the default config file could have this tag, or it could be missing, so take care to check.<\/p>\n<p>Logging to the screen is not too helpful, as log data scrolls out of buffer. Enabling logging is recommended in the XML file.<\/p>\n<p>In order to encrypt and decrypt, the source (starting) file needs to be web.config, so the file needs to be repeatedly renamed between web.config and Microsoft.Data.SqlRemoteBlobs.Maintainer.exe.config<\/p>\n<p>For each content Database that is RBS enabled, a content database connection string needs to be added to the Microsoft.Data.SqlRemoteBlobs.Maintainer.exe.config file. It needs to be named using the Add Name=, and then referenced at runtime using the ConnectionStringName parameter. So, for additional databases, simply add additional connection string to the web.config file for each content database that is rbs enabled.<\/p>\n<pre><\/pre>\n<p>Encrypt the web.config file again by using following command<\/p>\n<p>cd \/d %windir%Microsoft.NETFramework64v2.0.50727<\/p>\n<p>aspnet_regiis -pef connectionStrings \u201c%programfiles%Microsoft SQL Remote Blob Storage 10.50Maintainer \u201d -prov DataProtectionConfigurationProvider<\/p>\n<p>Rename the file back to original<\/p>\n<p>cd \/d %programfiles%Microsoft SQL Remote Blob Storage 10.50Maintainer<\/p>\n<p>ren web.config Microsoft.Data.SqlRemoteBlobs.Maintainer.exe.config<\/p>\n<p>Note: the XML file is case sensitive, you need to use the exact string for \u2018connectionStrings\u2019 parameter above.<\/p>\n<p>For the first time, run the Maintainer manually. Thereafter, you\u2019ll want to schedule it to run:<\/p>\n<ol>\n<li>Create a Maintenance Task using following steps (for each database)<\/li>\n<li>Click Start, point to Administrative Tools, and click Task Scheduler.<\/li>\n<li>Right-click Task Scheduler (Local) and click Create Task.<\/li>\n<li>Click the Actions tab and click New.<\/li>\n<li>On the New Action page, specify:<\/li>\n<\/ol>\n<table style=\"border-collapse: collapse; width: 65%; border: 2px solid #dddddd; text-align: left; padding: 8px;\">\n<tbody>\n<tr style=\"background-color: #f2f2f2;\">\n<td style=\"border: 1px solid #dddddd; text-align: left; padding: 8px;\">i. Action as Start a Program.<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #dddddd; text-align: left; padding: 8px;\">ii. For the Program\/script, click Browse and navigate to the RBS Maintainer application; by default, the location is %programfiles%Microsoft SQL Remote Blob Storage 10.50Maintainer Microsoft.Data.SqlRemoteBlobs.Maintainer.exe.<\/td>\n<\/tr>\n<tr style=\"background-color: #f2f2f2;\">\n<td style=\"border: 1px solid #dddddd; text-align: left; padding: 8px;\">iii. In the Add Arguments (optional) field, enter the following parameter string: (change the name of the connection string as specified in the config file earlier)<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #dddddd; text-align: left; padding: 8px;\">-ConnectionStringName RBSMaintainerConnection -Operation GarbageCollection ConsistencyCheck ConsistencyCheckForStores -GarbageCollectionPhases rdo -ConsistencyCheckMode r -TimeLimit 120.<\/td>\n<\/tr>\n<tr style=\"background-color: #f2f2f2;\">\n<td style=\"border: 1px solid #dddddd; text-align: left; padding: 8px;\">iv. Click OK<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Note: XML file is case sensitive, you need to use the exact string for the connection string above.<\/p>\n<p>5. On the Triggers tab, click New.<\/p>\n<p>6. In the New task dialog box, set:<\/p>\n<p>iii. Click OK.earlier<\/p>\n<table style=\"border-collapse: collapse; width: 65%; border: 2px solid #dddddd; text-align: left; padding: 8px;\">\n<tbody>\n<tr style=\"background-color: #f2f2f2;\">\n<td style=\"border: 1px solid #dddddd; text-align: left; padding: 8px;\">i. Begin the task to On a schedule.<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #dddddd; text-align: left; padding: 8px;\">ii. The trigger schedule to be Weekly, Sunday, at 2am (or at another time when system usage is low.)<\/td>\n<\/tr>\n<tr style=\"background-color: #f2f2f2;\">\n<td style=\"border: 1px solid #dddddd; text-align: left; padding: 8px;\">iv. Click OK<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<ol>\n<li>On the General tab, enter a name for the task, such as \u201c RBS Maintainer\u201d, where identifies the database associated with the task. In the Security settings section:<\/li>\n<li>Make sure that the account under which the task is to be run has sufficient permissions to the database.<\/li>\n<li>Select the option to Run whether user is logged on or not.<\/li>\n<li>Click OK.<\/li>\n<\/ol>\n<h2><span class=\"ez-toc-section\" id=\"Tuning_the_internal_Maintainer_parameters\"><\/span>Tuning the internal Maintainer parameters<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>There are several internal parameters that should be set that control the frequency that the Maintainer can be run, as well as how long deleted entries should be maintained before being truly removed. This later option is meant to save DBAs from trouble if they restore an older Content DB without restoring the FILESTREAM. If deletes are very \u201clazy\u201d (ie, delayed by days) rolling back to a previous DB without a FILESTREAM restore could work. I set the parameters more aggressively, knowing I won\u2019t fall prey to this issue. Here\u2019s the SQL to apply the changes. Note it\u2019s better to use the Stored Procedures than setting the values directly:<\/p>\n<pre>USE [Content_database_yourname]\r\nGO\r\nSET ANSI_NULLS ON\r\nGO\r\nSET QUOTED_IDENTIFIER ON\r\nGO\r\nexec mssqlrbs.rbs_sp_set_config_value delete_scan_period, 'days 1'\r\nexec mssqlrbs.rbs_sp_set_config_value orphan_scan_period, 'days 1'\r\nexec mssqlrbs.rbs_sp_set_config_value garbage_collection_time_window, 'days 1'\r\nGO\r\n<\/pre>\n<p>if you want to get aggressive on storage recovery use a smaller timeframe:<\/p>\n<pre lang=\"php\">\r\nexec mssqlrbs.rbs_sp_set_config_value delete_scan_period, 'time 00:00:10'\r\nexec mssqlrbs.rbs_sp_set_config_value orphan_scan_period, 'time 00:00:10'\r\nexec mssqlrbs.rbs_sp_set_config_value garbage_collection_time_window, 'time 00:00:\r\n<\/pre>\n<h2><span class=\"ez-toc-section\" id=\"Tips\"><\/span>Tips<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<ul>\n<li>Back up all configuration files first<\/li>\n<li>Use Visual Studio to edit the XML files<\/li>\n<li>XML is largely case sensitive, so take care<\/li>\n<li>-pdf is for Decrypion, -pef is for encryption<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>A configured and running Remote Blob Storage (RBS) is a ticking time bomb until you\u2019ve configured the Maintainer to run. That\u2019s because RBS is designed to leave a trail of unused objects in its wake. RBS counts on a periodic process to run to eliminate all these unused objects. If you save a file in [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":2024,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[40],"tags":[],"class_list":["post-2023","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-rbs"],"acf":[],"_links":{"self":[{"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/posts\/2023","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/comments?post=2023"}],"version-history":[{"count":23,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/posts\/2023\/revisions"}],"predecessor-version":[{"id":2091,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/posts\/2023\/revisions\/2091"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/media\/2024"}],"wp:attachment":[{"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/media?parent=2023"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/categories?post=2023"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/tags?post=2023"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}