logo

The ConnectWise Control forum has moved to ConnectWise University! This forum has been locked and is in read-only mode. Click here for instructions on how to access the new forum.

Welcome Guest! You can not login or register.

Notification

Icon
Error

Options
Go to last post Go to first unread
foodtec  
#1 Posted : Tuesday, June 10, 2014 11:32:30 AM(UTC)
foodtec


Rank: Newbie

Joined: 4/2/2014(UTC)
Posts: 9
Greece

Hi,

We have a ScreenConnect server running in AWS in a 'm1.small' instance with 'Windows server 2008 R2 Datacenter' as OS.

It has been cheerfully running version 3.2 without fail, serving about 5000 connected unattended clients and an average of 20 and maximum of 80 concurrently connected host sessions.

We also have some custom code that gives back some session info to identify if an unattended client is accessible (connected or not) and how many support engineers are connected to it (host sessions)

(We put the MAC address of the machine as the session name and then search based on it)


Code:

public class GetSessionInfo : IHttpHandler {
    
    public void ProcessRequest (HttpContext context) {
        String macAddr = context.Request.QueryString["MacAddr"];
        String callback = context.Request.QueryString["callback"];
        SessionInfo session;
        try
        {
            SessionSummary summary = SessionSummaries.getSessionForMac(macAddr);
            session = new SessionInfo(summary);
        }
        catch (ObjectNotFoundException e)
        {
            session = new SessionInfo();
        }

        var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();


        if (callback.IsNullOrEmpty())
        {
            context.Response.ContentType = "application/json";
            context.Response.Write(serializer.Serialize(session));
        }
        else
        {
            context.Response.ContentType = "application/javascript";
            context.Response.Write(callback + "(");
            context.Response.Write(serializer.Serialize(session));
            context.Response.Write(")");
        }
    }

    public bool IsReusable { get { return false; } }
}

Code:

        public static SessionSummary getSessionForMac(String sessionName)
        {
            if (sessionName.IsNullOrEmpty())
                throw new ObjectNotFoundException("No such machine");

            using (var sessionManager = Elsinore.ScreenConnect.ServiceChannelPool<Elsinore.ScreenConnect.ISessionManagerChannel>.Instance.Borrow())
            {
                IEnumerable<SessionSummary> summaries = sessionManager.GetSessionSummaries().Where(ss => string.Equals(ss.Name, sessionName, StringComparison.InvariantCultureIgnoreCase));


                SessionSummary sessionSummary = null;
                foreach (SessionSummary summary in summaries)
                {

                    // TODO throw exception if multiple connected are found?
                    if (summary.MostRelevantGuestEventType == SessionEventType.Connected)
                        return summary;
                    else
                        sessionSummary = summary;
                }

                if (sessionSummary == null)
                    throw new ObjectNotFoundException("No such machine");

                return sessionSummary;
            }
        }



This bit of code was serving requests quite often and was able to handle more than 35 concurrent requests within a timeout of 4 secs without reaching the instance's cpu load to 100% and slowing down the existing host connections.


The plot twist comes when we upgraded a few days ago to version 4.2
We have not changed the configuration at all, same ports and FQDN are used as before and currently our whole fleet of 5000 ver3.2 unattended clients are connected to it.
We have updated our custom code to work with the code changes in 4.2:


Code:

        public static Session getSessionForMac(String sessionName)
        {
            if (sessionName.IsNullOrEmpty())
                throw new ObjectNotFoundException("No such machine");

            using (var sessionManager = Elsinore.ScreenConnect.ServiceChannelPool<Elsinore.ScreenConnect.ISessionManagerChannel>.Instance.Borrow())
            {
                IEnumerable<Session> sessionList = sessionManager.GetSessions().Where(ss => string.Equals(ss.Name, sessionName, StringComparison.InvariantCultureIgnoreCase));


                Session sessionReturned = null;
                foreach (Session session in sessionList)
                {

                    // TODO throw exception if multiple connected are found?
                    if (session.GuestConnectedCount > 0)
                        return session;
                    else
                        sessionReturned = session;
                }

                if (sessionReturned == null)
                    throw new ObjectNotFoundException("No such machine");

                return sessionReturned;
            }
        }



BUT
when requests hit our new custom code now,
1. The cpu usage skyrockets to 100%
2. The requests do not seem to be processed in parallel but in sequence and each request seems to need about 800ms to 1000ms to complete causing 35 concurrent requests to complete in 35-36 seconds (versus 4 secs that did before)
3. When these requests are waiting to be processed, all the connected host sessions become sluggish and lagging

With the introduction of sqlite database storing all session data it looks like ScreenConnect server is slower now accessing them than in ver 3.2, in which (I assume) it kept all that data in memory.



Here comes the questions:
1. How can we bring back the quick responsiveness session info data query?

2. Why is it processing the requests in sequence? Is it opening and closing the sqlite database for each request?

3. Is there some session info caching we can enable in the ScreenConnect server so it can behave like ver 3.2 ? Can we tell the screenconnect server to keep session info in memory?

4. Are we doing something wrong in the new code? Is there a better way to query for what we are looking for?
(By just altering the 'Cache Size' in <connectionStrings> in web.config from '10000' to '40000' we saw an improvement of response from 35 seconds, to 17 seconds but again this is not enough)

5. Should we be looking to replace the sqlite database with a different one that does caching by itself? If yes, how?

6. Would it be faster if we queried the sqlite database directly for the info we are looking for?

Jake  
#2 Posted : Tuesday, June 10, 2014 2:02:21 PM(UTC)
Jake


Rank: Administration

Medals: Level 4: Wise Old Owl! Received 100 Thanks!

Joined: 4/9/2010(UTC)
Posts: 2,061

Thanks: 1 times
Was thanked: 393 time(s) in 188 post(s)
The GetSessions call is still completely from memory. That particular call should be very quick. Other calls into your service could be slowing down these calls, especially if you have 5000 sessions. All calls to the web service are serialized. We've done quite a bit of tweaking in 4.3 and 4.4, and you should try one of those. Also there are some connection string parameters for write-ahead-logging that should increase performance of database writing calls (though not your GetSessions call). The connection string for 5.0 looks like this:

Code:
<add name="SessionDatabase" providerName="SQLite" connectionString="Data Source=|DataDirectory|/Session.db; DateTimeKind=Utc; Foreign Keys=true; Page Size=4096; Cache Size=100000; Journal Mode=WAL" />

Edited by user Tuesday, June 10, 2014 2:06:39 PM(UTC)  | Reason: Not specified

ScreenConnect Team
foodtec  
#3 Posted : Tuesday, June 10, 2014 2:48:42 PM(UTC)
foodtec


Rank: Newbie

Joined: 4/2/2014(UTC)
Posts: 9
Greece

Thanks Jake for the quick reply!

Its good to know that its not because of us accessing session info in a wrong way.

Would it be faster if we accessed session info from the database directly instead of the ScreenConnect classes?

Are all PRAGMA commands supported as options on the connection string?
Jake  
#4 Posted : Tuesday, June 10, 2014 3:59:24 PM(UTC)
Jake


Rank: Administration

Medals: Level 4: Wise Old Owl! Received 100 Thanks!

Joined: 4/9/2010(UTC)
Posts: 2,061

Thanks: 1 times
Was thanked: 393 time(s) in 188 post(s)
You shouldn't access the database directly. I'd really try upgrading to 4.4 when you feel comfortable.

Not all pragma commands are translated from the connection string. Just what is supported by the .NET sqlite provider.

Additionally, 5.0 will have a SessionManager method that will allow you to specify a filter dynamically, so you won't need to return all 5000 of your sessions on each request.
ScreenConnect Team
foodtec  
#5 Posted : Thursday, June 12, 2014 6:53:14 AM(UTC)
foodtec


Rank: Newbie

Joined: 4/2/2014(UTC)
Posts: 9
Greece

Hi,

Tried the different options in the connection string and saw that they made no difference in the end.

35 concurrent requests for session info, took 36-42 seconds to be completed, pretty much like before. I probably has to do with the fact that Journaling mode WAL improves writes and write locks in the sqlite db and not reads, that these requests are doing.
Users browsing this topic
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.