2010 m. spalio 7 d., ketvirtadienis

Solving database logging bottlenecks with NLog

Solving database logging bottlenecks with NLog


Recently I worked on improving the speed of asp.net application. After several improvements the most important bottleneck was related to the database logging. We used logging extensively and Enterprise library 4 facilitated us in this.

Those of you who are familiar with Enterprise library logging capabilities probably know that they offer a great config generation tool and a script to create a database which consists of 3 tables: 




On one hand, it's convenient to use the database which is feasibly designed for the most logging needs and is automatically created.
On the other hand, there might be cases where the "solution to all problems" isn't an optimal solution. Especially if you app doesn't meet certain requirements.

In my case I choose to suggest NLog for database logging tasks instead of Enterprise library.
Suppose that we need only very primitive logging database consisting of one table:



And run a test with the following strategy:
  1. 100 one line database logs
  2. 1 is repeated 100 times and an average time is taken.

 In short, we see that performance might be improved up to 5 times. The loss is scalability and additional time for setting things up. It took me probably 7 times less time to configure Enterprise library.


References:

  • http://msdn.microsoft.com/en-us/library/ff648951.aspx
  • http://nlog-project.org/

2010 m. kovo 12 d., penktadienis

Communication between WCF and JBoss server via REST

Part 3: Controlling serialization and prefixed namespaces


In this part I would like to demonstrate how to customize serialization process and to introduce some interoperability issues. Plot is the same: we are communicating with java server and its internal logic requires specifying namespace prefixes:

<ns2:student xmlns:ns2="http://pauliusraila.blogspot.com/">
<id>12</id>
<name> Raila</name>
</ns2:student>


According to the XML specification for namespaces 1.1:  http://www.w3.org/TR/2006/REC-xml-names11-20060816/ there are two ways to specify the namespace: 
  • default namespace attribute
  • prefixed namespace attribute
According to this following message should be interpreted the same as the previous one:

<student xmlns="http://pauliusraila.blogspot.com/">
<id>12</id>
<name> Raila</name>
</student>


Unfortunately we have to use only prefixed namespace attributes.


.NET provided serializers:
  • XmlSerializer 
  • DataContractSerializer
DataContractSerializer is the default in WCF unless you specify that XmlSerialzier should be used. It works with a subset of XML Infoset and therefore provides a better performance and reduces message size.


DataContractSerializer provides a possibility to specify custom namespace but only as the default namespace attribute. 

We have to utilize XmlSerializer.


Although XmlSerializer can be used both in declarative and imperative manner in current situation we have to pass XmlSerializerNamespaces object and we have to utilize an imperative way:

XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add("ns", "
http://pauliusraila.blogspot.com");

Moreover we can no longer use HttpContentExtensions libraries to create a serialized content:


HttpContentExtensions.CreateXmlSerializable<Account >(newAccount); 

Instead this I've wrote a generic method which uses a custom namespace object:

 public static HttpContent CreateHttpContent(T obj, XmlSerializerNamespaces namespaces)
{
            XmlSerializer ser = new XmlSerializer(typeof(T));
            MemoryStream ms = new MemoryStream();
           
            namespaces == null ? 

               ser.Serialize(ms, obj): ser.Serialize(ms, obj, namespaces);
            ms.Close();

         
            return HttpContent.Create(ms.ToArray());          
  }


2009 m. gruodžio 27 d., sekmadienis

Communication between WCF and JBoss server via REST

Part 2: Using ssl + basic auth

Providing plain credentials over a secure transport layer is considered as quite secure way to communicate.

Let's build a secure Rest client:

using (HttpClient client = new HttpClient()) // needs disposal
{
  client.DefaultHeaders.ContentType = "text/xml";
  client.TransportSettings.Credentials = new NetworkCredential("username", "password");
 
  ServicePointManager.Expect100Continue = false;

 ServicePointManager.ServerCertificateValidationCallback = (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => { return true; };

 Account newAccount = new Account()
  {
     Id = 0,
     Name = “FirstUser”
  };

  HttpContentExtensions.CreateXmlSerializable<Account>(newAccount);
  HttpResponseMessage resp = lient.Post("http://example/account", newAccount);

  resp.EnsureStatusIsSuccessful(); // fires exceptions
  
  Status status = resp.Content.ReadAsXmlSerializable<Status>();
}

The property ServicePointManager.Expect100Continue solves different Http1.1 interpretation problem between Java .NET.

This case is covered in the HTTP/1.1 (RFC 2616) specification in section 8.2.3:

"Because of the presence of older implementations, the protocol allows ambiguous situations in which a client may send "Expect: 100-continue" without receiving either a 417 (Expectation Failed) status
or a 100 (Continue) status. Therefore, when a client sends this header field to an origin server (possibly via a proxy) from which it has never seen a 100 (Continue) status, the client SHOULD NOT wait for an indefinite period before sending the request body."

This problem appeared only when I'd added security to my client. Probably it is related to increasing waiting time.

ServicePointManager.ServerCertificateValidationCallback is used only in testing mode. The purpose is to override certificate validation which would cause exception becouse we don't have one in a testing stage.



References:
  • http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html 

2009 m. lapkričio 29 d., sekmadienis

Communication between WCF and JBoss server via REST

Communication between WCF and JBoss server via REST

Targets:

  • Build a client to communicate with JBoss(Java application server) RESTEasy REST service
  • Use ssl combined basic auth to ensure security
  • Use direct xml - object serialization
  • Explore WCF REST Starter Kit possibilities

Issues:
  • Http 1.1 different standards interpretation by .NET and java
  • Adding custom xml namespace prefixes to request message

PART 1 - Simple client

Two different ways for calling REST from .NET :
  • Using simple HttpWebRequest and HttpWebResponse objects. (old way, more technical details)
  • Using WCF REST Starter Kit.

Let’s focus on the second type. It saves some lines of code and hides unnecessary technical details.
We have a task to create a user on the remote system and receive the status.

So far we’ve successfully created the following DTO objects (by using xsd tool that comes with Visual Studio or by hand:
  • Simplified user with id and Name fields
  • Status with success/failure indicator + optional message (failure case)
///
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlRootAttribute(IsNullable = false, ElementName = "account")]
public class Account
{

private long idField;
private string name;

///
[System.Xml.Serialization.XmlElementAttribute(ElementName="id")]
public long Id
{
   get
   {

      return this.idField;
   }
  set
  {
     this.idField = value;
   }

}
[System.Xml.Serialization.XmlElementAttribute(ElementName = "name")]
public string Name
{
   get
   {
     return this.name;
   }
   set
   {
     this.name = value;
   }
}
}

[System.SerializableAttribute()]
[System.Xml.Serialization.XmlRootAttribute(IsNullable = false, ElementName = "status")]
public class Status
{

private string msg;
private bool successField;

///
[System.Xml.Serialization.XmlElementAttribute(ElementName = "msg")]
public string Msg
{
   get
   {
     return this.msg;
   }
   set
   {
     this.msg = value;
   }
}
[System.Xml.Serialization.XmlElementAttribute(ElementName = "success")]
public bool Success
{
   get
   {
     return this.successField;
  }
   set
   {
     this.successField = value;
   }

}
}


Then our code looks like:



using (HttpClient client = new HttpClient()) // needs disposal
{
  client.DefaultHeaders.ContentType = "text/xml";
  Account newAccount = new Account()
  {
     Id = 0,
     Name = “FirstUser”
  };

  HttpContentExtensions.CreateXmlSerializable<Account >(newAccount);
  HttpResponseMessage resp = lient.Post("http://example/account", newAccount);

  resp.EnsureStatusIsSuccessful(); // fires exceptions
  
  Status status = resp.Content.ReadAsXmlSerializable<Status>();
}

HttpContentExtensions class provides helper methods for Http content creation.

Next part will provide security for our client