Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • MuirisOG 382 posts 1284 karma points
    Jul 21, 2017 @ 10:28
    MuirisOG
    0

    Multiple sites on one Umbraco instance

    We have multiple sites on one Umbraco instance and have noticed that start-up times are a bit slow.

    We're using Umbraco v7.5.14

    Should I be using the umbraco.config?

    How do all the sites compete for the same config file?

    Thanks

    Muiris

  • Alex Skrypnyk 6131 posts 23950 karma points MVP 7x admin c-trib
    Jul 21, 2017 @ 10:31
    Alex Skrypnyk
    0

    Hi MuirisOG

    Do you have some custom logic in Umbraco start event?

    Is it a big site?

    Thanks,

    Alex

  • MuirisOG 382 posts 1284 karma points
    Jul 21, 2017 @ 10:43
    MuirisOG
    0

    Alex Yes, I do.

    I've had to implement an IUrlProvider and IContentFinder (took me a while but I got there) and one of the things my contentfinder does is build a hashtree to match our old CMS page IDs with our new one.

    It only builds the hashtree on the first load... from then on it's cached (I've used LogHelper to make sure it does just that).

    I guess I could try the sites and switch off the code to build the hashtree and see how quickly they each load.

    Thanks

    Muiris

  • Alex Skrypnyk 6131 posts 23950 karma points MVP 7x admin c-trib
    Jul 21, 2017 @ 10:58
    Alex Skrypnyk
    0

    It looks like the code that you have is the reason slow start.

    Please, share how did you solve the issue.

    Thanks,

    Alex

  • MuirisOG 382 posts 1284 karma points
    Jul 21, 2017 @ 11:02
    MuirisOG
    0

    Alex

    sorry, I have mislead you.

    I've checked and it only hits that section of the ContentFinder if one of our old CMS page URLs is detected.

    However, I'll prepare the ContentFinder to post here.

    Thanks again

    Muiris

  • Dave Woestenborghs 3504 posts 12133 karma points MVP 8x admin c-trib
    Jul 21, 2017 @ 12:00
    Dave Woestenborghs
    0

    Hi,

    We found that UrlProviders can also be performance issue. These are called everytime you access the .Url property of a published content item.

    Dave

  • MuirisOG 382 posts 1284 karma points
    Jul 21, 2017 @ 13:55
    MuirisOG
    0

    Dave,

    I notice that Jeroen Breuer uses caching in both his UrlProvider and ContentFinder code (https://www.youtube.com/watch?v=DWjbJiIUQdk)

    Perhaps I should try that out.

    Alex,

    our site will host our main site and 25 smaller sites. I have tried an individual Application Pool for each microsite but I'm not so sure it made much of a difference.

    We are not live yet - it's been a while and we're really close.

    We have a large number of pages within the Umbraco CMS and a huge amount of media nodes as well, but from what I can see here on the Umbraco forums, there are some pretty big sites out there.

    I've tried tidying my contentfinder and getting rid of all the identifiable code, so here goes:

    namespace myNameSpace.Library.ContentFinders
    {
        using System;
        using System.Collections;
        using System.Collections.Generic;
        using System.Linq;
        using System.Web;
        using Umbraco.Core;
        using Umbraco.Core.Cache;
        using Umbraco.Core.Logging;
        using Umbraco.Core.Models;
        using Umbraco.Core.Services;
        using Umbraco.Web;
        using Umbraco.Web.Routing;
    
    
        public class FourOhFourContentFinder : IContentFinder
        {
            //create a global hashtable as this can be re-used
            public static Hashtable newPageIDHashTable = new Hashtable();
    
            public bool TryFindContent(PublishedContentRequest contentRequest)
            {
    
                // **** 1) Start - check for the old CMS page ID
                String currurl = HttpContext.Current.Request.RawUrl;
                String querystring = null;
    
                // Check to make sure some query string variables exist and if not add some and redirect.
                // start by creating a few variables
                int iqs = currurl.IndexOf('?');
                int oldPageId;
                int newPageId = -1;
                int homepageId = 1059;
                string oldPageIdent = "";
                string newUrl = "";
    
                //if there is a querystring...
                if (iqs >= 0)
                {
                    //if the querystring contains the word "page" it indicates an old CMS page
                    querystring = (iqs < currurl.Length - 1) ? currurl.Substring(iqs + 1) : String.Empty;
                    oldPageIdent = HttpUtility.ParseQueryString(querystring).Get("page");
    
                    // Parse the query string variables into a NameValueCollection.
                    bool result = int.TryParse(oldPageIdent, out oldPageId);
    
                    if (result)
                    {
                        if (querystring.Length > 1)
                        {
                            //strip out the old page id
                            querystring = querystring.Replace("page=" + oldPageId, "");
                            //strip out a leading ampersand
                            if (querystring.Length > 1)
                            {
                                querystring = (querystring.Substring(0, 1) == "&" ? "?" + querystring.Substring(1, querystring.Length - 1) : "?" + querystring);
                            }
                        }
                        //check to see if the hashtable has already been created by looking for the homepage
                        if ((newPageIDHashTable.ContainsKey(0) && (int)newPageIDHashTable[0] == homepageId))
                        {
                            LogHelper.Info(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, currurl + "HashTable Exists!");
    
                            //check to see if the oldPageId (i.e. the old CMS ID) exists
                            if (newPageIDHashTable.ContainsKey(oldPageId))
                            {
                                newPageId = (int)newPageIDHashTable[oldPageId];
                                newUrl = System.Web.HttpContext.Current.Request.Url.Scheme + "://" + System.Web.HttpContext.Current.Request.Url.Host + ":" + System.Web.HttpContext.Current.Request.Url.Port + "/" + newPageId + querystring;
                                UmbracoContext.Current.HttpContext.Response.RedirectPermanent(newUrl);
                            }
                        }
                        else
                        {
                            LogHelper.Info(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, currurl + "HashTable Needs to be Created!");
    
                            // the hashtable doesn't exist so create it
                            makePageIDHashTable();
                            //check to see if the oldPageId (i.e. the old CMS ID) exists
                            if (newPageIDHashTable.ContainsKey(oldPageId))
                            {
                                newPageId = (int)newPageIDHashTable[oldPageId];
                                newUrl = System.Web.HttpContext.Current.Request.Url.Scheme + "://" + System.Web.HttpContext.Current.Request.Url.Host + ":" + System.Web.HttpContext.Current.Request.Url.Port + "/" + newPageId + querystring;
                                UmbracoContext.Current.HttpContext.Response.RedirectPermanent(newUrl);
                            }
                        }
                    }
                }
                ////End - check for the old page ID
    
                // *****  2) use contentRequest.Uri to get the current node
                // this has to happen after 1) above as otherwise we'd never find old CMS pages
                string _path = contentRequest.Uri.LocalPath.Replace("/", "");
    
                //if the path is non-existent, then return the homepage for this domain - let something else handle the request
                if (_path.Length < 1) return false;
    
                // ***** 3) get the page (or node) id from the Uri
                int nodeId;
                // if it's not a node id then let something else handle the request
                if (!int.TryParse(contentRequest.Uri.LocalPath.Replace("/", ""), out nodeId)) return false;
    
                // now check if we are in the right docmain or we will have to return a page 404
                // ***** 4) set up the page 404s
                if (contentRequest != null)
                {
                    // Get the current domain name
                    var ds = ApplicationContext.Current.Services.DomainService;
                    string domainName = HttpContext.Current.Request.ServerVariables["SERVER_NAME"];
                    // myOrgDomain is based on the request coming in
                    var myOrgDomain = ds.GetByName("http://" + domainName);
    
                    // 4a) return if there is no domain
                    if (myOrgDomain == null) return false;
    
                    //ignore intranet addresses as we don't need to return a 404 for the wrong domain
                    if ((domainName.ToLower() == "myorglive7514.local") || (domainName.ToLower() == "internalserver.myorg.co.uk")) return false;
    
                    // 4b) Get the root node id of the domain
                    // rootNodeId is based on the domain in the request coming in
                    int rootNodeId = (int)myOrgDomain.RootContentId;
    
                    // Return if a root node couldn't be found
                    if (rootNodeId <= 0) return false;
    
                    // 4c) Get the root node id of the domain
                    // Find the root node from the ID
                    IPublishedContent root = (rootNodeId > 0 ? UmbracoContext.Current.ContentCache.GetById(rootNodeId) : null);
    
                    // Return FALSE if the root node wasn't found (AKA move on to the next content finder)
                    if (root == null) return false;
    
                    //get this page's root node so we can compare the root node for this page with the root of the domain
                    //get the content from the node id
                    IPublishedContent currentPageContent = (nodeId > 0 ? UmbracoContext.Current.ContentCache.GetById(nodeId) : null);
    
                    // if 1) there is no content
                    // or 2) the root's template in this domain doesn't match the root's template for the page passed in
                    //       then we move on to the final stage of assigning the correct 404 for each domain
                    string templateForThisPage = "";
                    bool pageExists = true;
                    if (currentPageContent == null) 
                    {
                        pageExists = false;
                    }
                    else
                    {
                        IPublishedContent rootForThisPage = currentPageContent.AncestorOrSelf(1);
                        templateForThisPage = rootForThisPage.GetTemplateAlias();
                    }
    
                    // looks like nothing can find this page so now we decide which 404 to use
                    if (templateForThisPage != root.GetTemplateAlias() || !pageExists)
                    {
    
                        // Handle error pages for each site type
                        switch (root.GetTemplateAlias())
                        {
    
                            case "myOrg_site1":
                                {
                                        // Get the error page from the hardcoded ID
                                        contentRequest.PublishedContent = UmbracoContext.Current.ContentCache.GetById(1446);
                                        break;
                                }
    
                            case "myOrg_site2":
                                {
                                        contentRequest.PublishedContent = UmbracoContext.Current.ContentCache.GetById(2010);
                                        break;
                                }
    
                            case "myOrg_site3":
                                {
                                        contentRequest.PublishedContent = UmbracoContext.Current.ContentCache.GetById(4654);
                                        break;
                                }
    
                            case "myOrg_site4":
                                {
                                        contentRequest.PublishedContent = UmbracoContext.Current.ContentCache.GetById(2494);
                                        break;
                                }
    
    
                        }
                    }
    
    
                }
    
                // Return whether an error page was found
                return contentRequest.PublishedContent != null;
            }
    
            //get the new Umbraco ID for the old CMS page id
            public static void makePageIDHashTable()
            {
                IContentService cs = ApplicationContext.Current.Services.ContentService;
                IContentTypeService cts = ApplicationContext.Current.Services.ContentTypeService;
    
                int dt = cts.GetContentType("myOrgDocType").Id;
                IEnumerable<IContent> d = default(IEnumerable<IContent>);
    
                d = cs.GetContentOfContentType(dt);
    
                //set up some variables
                int oldPageID = 0;
                int newPageID = 0;
                //the hash table is a global variable
    
    
                //first iteration gets all the values we need
                foreach (IContent doc in d)
                {
                    //get the existing page id
                    if (doc.GetValue("p_page_id") == null)
                    {
                        //if p_page_id is null then this is either
                        //   a) a new page in Umbraco or
                        //   b) has been edited and the p_page_id has been deleted
                        continue;
                    }
                    else
                    {
                        oldPageID = Convert.ToInt32(doc.GetValue("p_page_id"));
                    }
    
                    //get the new page id
                    newPageID = doc.Id;
    
                    //check for duplicates - the hash table may already have the old and new page ids
                    if ((newPageIDHashTable.ContainsKey(oldPageID) && (int)newPageIDHashTable[oldPageID] == newPageID))
                    {
                        continue;
                    }
    
                    try
                    {
                        //add the page to the hash-table
                        newPageIDHashTable.Add(oldPageID, newPageID);
                    }
                    catch (Exception ex)
                    {
                        LogHelper.Error(typeof(FourOhFourContentFinder), "Error in FourOhFourContentFinder.makePageIDHashTable", ex);
                        continue;
                    }
    
                }
    
            }
    
    
        }
    
    }
    
  • Dave Woestenborghs 3504 posts 12133 karma points MVP 8x admin c-trib
    Jul 21, 2017 @ 14:05
    Dave Woestenborghs
    0

    Hi Muiris

    I think the problem is that you are using the ContentService to query your content. This will bypass the published content cache stored in memory and will query the database direclty.

    Dave

  • MuirisOG 382 posts 1284 karma points
    Jul 24, 2017 @ 09:09
    MuirisOG
    0

    Dave / Alex

    I think I might have found one way to speed up the sites.

    I've changed my setup in IIS... instead of having a site for each domain (with the appropriate host header), I've tried one site only with multiple host headers.

    Yet again, our previous setup allowed the former configuration with no performance issues.

    Which is better?

    These are not huge sites and so should all run together in harmony.

    Thanks

    Muiris

  • Dave Woestenborghs 3504 posts 12133 karma points MVP 8x admin c-trib
    Jul 24, 2017 @ 09:26
    Dave Woestenborghs
    102

    Hi Muiris,

    One Umbraco installation (even if it hosts multiple sites) should be one IIS website and one application pool. Having multiple IIS sites will have you run in to trouble.

    Dave

  • MuirisOG 382 posts 1284 karma points
    Jul 24, 2017 @ 09:30
    MuirisOG
    0

    Thanks Dave,

    the other method was working, but when I looked back over my own notes and the blogs and forum posts, everyone was doing it the other way.

    Our old CMS allows for the other approach, and when one site goes down, it didn't tend to take the others with it.

    I'll change the setup in IIS.

    Again, many thanks

    Muiris

Please Sign in or register to post replies

Write your reply to:

Draft