Directory Programming .NET

Active Directory and ADAM programming support for .NET developers
Welcome to Directory Programming .NET Sign in | Join | Help
in Search

Connection Caching Issues[With Web Application]

Last post 06-28-2009, 2:47 PM by joe. 7 replies.
Sort Posts: Previous Next
  •  06-16-2009, 11:02 AM 6669

    Connection Caching Issues[With Web Application]

    Hi,Joe

     I have read your book about the directory service programming, you have done a great job!

    Howerver, there are still something make me confused:

    I have a MOSS/Sharepoint running in a AD environment and using the AD authentication.

    The MOSS is runing with a application pool under a public domain account.

    In a MOSS page, i am using DirectoryEntry and DirectorySearcher to query AD server for users' information, and i write the code following the example code in  chapter 3 of your book.
    DirectoryEntry rootDSE = new DirectoryEntry( LDAP://myserver.mydomain.com/RootDSE" );

    1 When users browse the page from different clients, should the default networkcredential be the public account that running my MOSS or every user's account from their clients?

    2 You tell us to store a single DirectoryEntry object in a static variable or cache, do you mean that we should keep the single DirectoryEntry object for all requests from different clients and never dispose it unless we restart the iis service?

    3 We have many AD servers, but how can we specify a different server for each request? Or is there any way to switch a server when the current server throw a exception such as "the server is not operational"?

    Thanks again, you are a great man.

     

    Additon

    -----------------------------------------------------------------------------------------

    My Web application is running as a domain account,and in my page code i wrote like this:

    string server="xx.hd.com";

    string account="myadmin";

    string pwd="mypwd";

    using(DirectoryEntry entryRoot=new DirectoryEntry(server,account,mypwd,AuthenticationType.Secure))

    {

    using(DirectoryEntry entry=new DirectoryEntry(server,account,mypwd,AuthenticationType.Secure)){
    using (DirectorySearcher mySearcher= new DirectorySearcher(enrty))
    {
    mySearcher.SearchScope = SearchScope.Subtree;
    mySearcher.Filter="(|(objectClass=user)(SAMAccountName=u00123456)(SAMAccountName=u00123457)(SAMAccountName=u00123458))";

    SearchResultCollection results = mySearcher.FindAll();

    foreach(SearchResult result in results)
    {
    //load result's properties
    }
    }
    }
    }

    However, when i execute netstat command on my ad server , there is a tcp list like this:

    tcp   hd02:1023     hd01:ldap  time_wait

    tcp   hd02:1024     hd01:ldap  time_wait

    tcp   hd02:1025     hd01:ldap  time_wait

    tcp   hd02:1026     hd01:ldap  time_wait

    tcp   hd02:1027     hd01:ldap  time_wait

    ....

    hd02 is my web server, hd01 is my ad server

    why there are still so many time_wait tcp connections on my ad server?

  •  06-16-2009, 9:59 PM 6674 in reply to 6669

    Re: Connection Caching Issues

    For 1, this depends on whether impersonation is enabled at the time the request is made or more specifically, what the identity of the current thread is.  If you want to know for sure whose credentials are about to be used, you can always check WindowsIdentity.GetCurrent().Name to find out.

    If the goal is to ensure that a single set of credentials is used, then you want to either specify them in your constructor or ensure that you are not impersonating different users at the time you make the call.

    Regarding 2, the idea is to have one DE that uses the same credentials and connection to the server, so you want to keep that one alive.  If you have different creds to use or wish to connect to different servers, then you would want to cache that object individually.  The idea is that only one LDAP socket is open and that you aren't closing lots of new opened sockets all the time or you will run out.

    Regarding 3, you don't really want to specify new servers all the time.  This causes you to open and close sockets which is what can cause you to run out of wildcard ports.  If that happens, you get the error you mention even if the server itself is fine.  The error can be misleading.

    Hopefully that helps explain it a bit more.

  •  06-24-2009, 8:48 AM 6723 in reply to 6674

    Re: Connection Caching Issues

    Hi,Joe

    Additon

    -----------------------------------------------------------------------------------------

    My Web application is running as a domain account,and in my page code i wrote like this:

    string server="xx.hd.com";

    string account="myadmin";

    string pwd="mypwd";

    using(DirectoryEntry entryRoot=new DirectoryEntry(server,account,mypwd,AuthenticationType.Secure))

    {

    using(DirectoryEntry entry=new DirectoryEntry(server,account,mypwd,AuthenticationType.Secure)){
    using (DirectorySearcher mySearcher= new DirectorySearcher(enrty))
    {
    mySearcher.SearchScope = SearchScope.Subtree;
    mySearcher.Filter="(|(objectClass=user)(SAMAccountName=u00123456)(SAMAccountName=u00123457)(SAMAccountName=u00123458))";

    SearchResultCollection results = mySearcher.FindAll();

    foreach(SearchResult result in results)
    {
    //load result's properties
    }
    }
    }
    }

    However, when i execute netstat command on my ad server , there is a tcp list like this:

    tcp   hd02:1023     hd01:ldap  time_wait

    tcp   hd02:1024     hd01:ldap  time_wait

    tcp   hd02:1025     hd01:ldap  time_wait

    tcp   hd02:1026     hd01:ldap  time_wait

    tcp   hd02:1027     hd01:ldap  time_wait

    ....

    hd02 is my web server, hd01 is my ad server

    why there are still so many time_wait tcp connections on my ad server?

  •  06-24-2009, 4:59 PM 6731 in reply to 6723

    Re: Connection Caching Issues

    One thing, make sure you wrap the SearchResultCollection in using as well.  It is also IDisposable.

    What may be going on here is that you are cleaning up all your connections on each call, but you don't have a separate DirectoryEntry that you open and keep open.  To use the static member approach (or something like that), you might create and bind a DirectoryEntry in something like the app start even and add it to cache or something.  That should keep the primary connection open.

     

  •  06-25-2009, 10:31 AM 6741 in reply to 6731

    Re: Connection Caching Issues

    Hi joe,

    I have tested my code for several times, and i found something like this:

    if the code is like this:

    DirectoryEntry entryRoot = new DirectoryEntry("LDAP://hd.com",user,pwd,AuthenticationType.Secure);

    object  obj = entryRoot.NativeObject;

    for(int i=0;i<100;i++)

    {

       using(DirectoryEntry entry = new DirectoryEntry("LDAP://hd.com/CN=user 00123456,CN=Users,DC=hd,DC=com",user,pwd,AuthenticationType.Secure))

    {
    get :entry.Properties["Mail"].Value

    }

    }

    entryRoot.Dispose();

    It is ok and there are only 2-3 time_wait tcp connections on my AD server.

    But if i run with the following code:

    DirectoryEntry entryRoot = new DirectoryEntry("LDAP://hd.com",user,pwd,AuthenticationType.Secure);

    object  obj = entryRoot.NativeObject;

    for(int i=0;i<100;i++)

    {

       using(DirectoryEntry entry = new DirectoryEntry(LDAP://hd.com,user,pwd,AuthenticationType.Secure))

    {
    DirectorySearcher searcher = new DirectorySearcher();

    searcher.SearchRoot = entry;

    searcher.SearchScope=SearchScope.Subtree;

    searcher.Filter="(sAMAccountName=u00123456)";

    SearchResult result = searcher.FindOne();

    if(result!=null)

    {

    get result.Properties["Mail"].Value and other properties.

    }

    }

    }

    entryRoot.Dispose();

    There will be as many as 100 tcp connections with time_wait state.

    Hope you can tell us what cause this?

  •  06-25-2009, 4:22 PM 6747 in reply to 6741

    Re: Connection Caching Issues

    Based on what you showed, the DirectoryEntry objects inside the loop *should* all use the same connection to the directory already established by the first DE since they use the same server and credentials.  The fact that they do not looks wrong to me.  You could try hard coding the actual DNS name of the server itself and also adding AuthenticationTypes.ServerBind to your auth flags to see if that changes the behavior, but it might not.

    This is one of the major problems with ADSI connection caching.  It is difficult to predict how it is going to behave or know exactly what it is doing.  That is the reason I tend to prefer SDS.Protocols in cases where it really matters.  With it, you control the creation and lifetime of the LdapConnection object, so you can dictate how many connections.  The downside in multi-threaded apps like ASP.NET with long process lifetimes is that you then need to manage concurrent access to shared resources across threads, so there is extra coding complexity. 

    The ideal solution would be for SDS.P to have a connection pool of sorts that you could use which would make the concurrency easier to manage.

  •  06-27-2009, 10:27 AM 6760 in reply to 6747

    Re: Connection Caching Issues

    Hi joe,

    I'm glad to tell you i have solved this problem.

    The code should not be:

    DirectoryEntry entryRoot = new DirectoryEntry(server,account,pwd);

    object obj=entryRoot.NativeObject;

    for(int i=0;i<1000;i++)

    {

    using(DirectoryEntry entry = new DirectoryEntry(server,account,pwd)

    {

    using(DirectorySearcher searcher = new new DirectorySearcher())

    {

    searcher.SearchRoot=entry;

    ...

    ...

    SearchResultCollection results = searcher.FindAll();

    }

    }

    }

     

    It should be like this:

    DirectoryEntry entryRoot = new DirectoryEntry(server,account,pwd);

    object obj=entryRoot.NativeObject;

    for(int i=0;i<1000;i++)

    using(DirectorySearcher searcher = new new DirectorySearcher())

    {

    searcher.SearchRoot=new DirectoryEntry(server,account,pwd);

    ...

    ...

    SearchResultCollection results = searcher.FindAll(); 

    }

    }

     

    It looks so strange but it works.Hope this would help someone else.

     

  •  06-28-2009, 2:47 PM 6761 in reply to 6760

    Re: Connection Caching Issues

    Thanks for posting back.  That is weird.  The fact that you can't call Dispose on the DE object used as the search root is strange.  It makes it look like it would leak each of those and require them to be finalized by garbage collector.  On the other hand, they do not actually get forced to bind and the searcher actually makes a copy of the search root object to use so maybe that has something to do with.

    I still don't like that it should be this mysterious or a change like that should make a difference.  It makes it very difficult to use SDS effectively in a web app.

View as RSS news feed in XML