Quantcast
Channel: Ugo Lattanzi
Viewing all articles
Browse latest Browse all 8

Speed up WebAPI on Microsoft Azure

0
0

One of my favorite features of ASP.NET WebAPI is the opportunity to run your code outside Internet Information Service (IIS). I don’t have anything against IIS, in fact my tough matches with this tweet:

But System.Web is really a problem and, in some cases, IIS pipeline is too complicated for a simple REST call.

we fix one bug and open seven new one (unnamed Microsoft employee on System.Web)

Another important thing I like is cloud computing and Microsoft Aure in this case. In fact, if you want to run your APIs outside IIS and you have to scale on Microsoft Azure, maybe this article could be helpful.

Azure offers different ways to host your APIs and scale them. The most common solutions are WebSites or Cloud Services.

Unfortunately we can’t use Azure WebSites because everything there runs on IIS (more info here) so, we have to use the Cloud Services but the question here is Web Role or Worker Role?

The main difference among Web Role and Worker Role is that the first one runs on IIS, the domain is configured on the webserver and the port 80 is opened by default; the second one is a process (.exe file to be clear) that runs on a “closed” environment.

To remain consistent with what is written above, we have to use the Worker Role instead of the Web Role so, let’s start to create it following the steps below:

Now that the Azure project and Workrole project are ready, It's important to open the port 80 on the worker role (remember that by default the worker role is a close environment).

Finally we have the environment ready, It’s time to install few WebAPI packages and write some code.

PM> Install-Package Microsoft.AspNet.WebApi.OwinSelfHost

Now add OWIN startup class

and finally configure WebAPI Routing and its OWIN Middleware

usingSystem.Web.Http;usingDemoWorkerRole;usingMicrosoft.Owin;usingOwin;[assembly: OwinStartup(typeof (Startup))]namespaceDemoWorkerRole{publicclassStartup{publicvoidConfiguration(IAppBuilderapp){varconfig=newHttpConfiguration();// Routingconfig.Routes.MapHttpRoute("Default","api/{controller}/{id}",new{id=RouteParameter.Optional});//Configure WebAPIapp.UseWebApi(config);}}}

and create a demo controller

usingSystem.Web.Http;namespaceDemoWorkerRole.APIs{publicclassDemoController:ApiController{publicstringGet(stringid){returnstring.Format("The parameter value is {0}",id);}}}

Till now nothing special, the app is ready and we have just to configure the worker role that is the WorkerRole.cs file created by Visual Studio.

What we have to do here, is to read the configuration from Azure (we have to map a custom domain for example) and start the web server.

To do that, first add the domain on the cloud service configuration following the steps below:

finally the worker role:

usingSystem;usingSystem.Diagnostics;usingSystem.Net;usingSystem.Threading;usingSystem.Threading.Tasks;usingMicrosoft.Owin.Hosting;usingMicrosoft.WindowsAzure.ServiceRuntime;namespaceDemoWorkerRole{publicclassWorkerRole:RoleEntryPoint{privatereadonlyCancellationTokenSourcecancellationTokenSource=newCancellationTokenSource();privatereadonlyManualResetEventrunCompleteEvent=newManualResetEvent(false);privateIDisposableapp;publicoverridevoidRun(){Trace.TraceInformation("WorkerRole is running");try{RunAsync(cancellationTokenSource.Token).Wait();}finally{runCompleteEvent.Set();}}publicoverrideboolOnStart(){// Set the maximum number of concurrent connectionsServicePointManager.DefaultConnectionLimit=12;stringbaseUri=String.Format("{0}://{1}:{2}",RoleEnvironment.GetConfigurationSettingValue("protocol"),RoleEnvironment.GetConfigurationSettingValue("domain"),RoleEnvironment.GetConfigurationSettingValue("port"));Trace.TraceInformation(String.Format("Starting OWIN at {0}",baseUri),"Information");try{app=WebApp.Start<Startup>(newStartOptions(url:baseUri));}catch(Exceptione){Trace.TraceError(e.ToString());throw;}boolresult=base.OnStart();Trace.TraceInformation("WorkerRole has been started");returnresult;}publicoverridevoidOnStop(){Trace.TraceInformation("WorkerRole is stopping");cancellationTokenSource.Cancel();runCompleteEvent.WaitOne();if(app!=null){app.Dispose();}base.OnStop();Trace.TraceInformation("WorkerRole has stopped");}privateasyncTaskRunAsync(CancellationTokencancellationToken){// TODO: Replace the following with your own logic.while(!cancellationToken.IsCancellationRequested){//Trace.TraceInformation("Working");awaitTask.Delay(1000);}}}}

we are almost done, the last step is to configure the right execution context into the ServiceDefinistion.csdef

<?xml version="1.0" encoding="utf-8"?><ServiceDefinitionname="imperugo.demo.azure.webapi"xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition"schemaVersion="2014-06.2.4"><WorkerRolename="DemoWorkerRole"vmsize="Small"><RuntimeexecutionContext="elevated"/><Imports><ImportmoduleName="Diagnostics"/></Imports><Endpoints><InputEndpointname="Http"protocol="http"port="80"localPort="80"/></Endpoints><ConfigurationSettings><Settingname="protocol"/><Settingname="domain"/><Settingname="port"/></ConfigurationSettings></WorkerRole></ServiceDefinition>

Here the important part is Runtime node. That part is really important because we are using the HttpListener to read the incoming message from the Web and that requires elevated privileges.

Now we are up & running using WebAPi hosted on a Cloud Service without using IIS.

The demo code is available here.

Have fun.


Viewing all articles
Browse latest Browse all 8

Latest Images

Trending Articles





Latest Images