Quantcast
Channel: Andrei Dzimchuk
Viewing all 60 articles
Browse latest View live

Updating Azure cloud service configuration with PowerShell

$
0
0
Azure team ships PowerShell cmdlets that allow us to automate literally any task we can perform on the portal. Automating development tasks is important for efficient DevOps flow as it gives us fast and reliable way to perform every day activities setting up environments, deploying applications, collecting diagnostics and so on.

Understanding ASP.NET 5 middleware

$
0
0
Principals and design approaches that we have seen in OWIN specification and some of its implementations (for Microsoft servers and frameworks the most notable is Katana) found their way into ASP.NET 5. In this post I want to focus on one of the core concepts which is middleware.

Getting to know the new ASP.NET 5 configuration framework

$
0
0
.NET applications traditionally relied on System.Configuration components for accessing and managing configurations. The new release of .NET revisits the configuration story by bringing on a brand new configuration framework that removes dependency on the configuration file format while providing consistent abstraction that can be used throughout your applications.

Bring your own DI container to ASP.NET 5

$
0
0
As you probably know ASP.NET 5 uses dependency injection from the ground up. It's unlike previous releases where higher level frameworks such as MVC, WebAPI or SignalR provided their own extension points to hook your DI container of choice in.

Bring your own DI container to ASP.NET 5 - Unity

$
0
0
Now that we understand some basics of how dependency injection is handled by ASP.NET 5 we are ready to start rolling out our integration components for our container of choice. In this post I’m going to walk you through integrating Unity with ASP.NET pipeline.

Setting up Azure CDN for your site

$
0
0
Microsoft Azure provides a modern CDN service that will help boost performance of your web applications. The service acts as a globally distributed pass-through cache and you can choose the backing service it will use to fetch original files from. You have three options currently: Azure Blob Storage, Azure Cloud Services and Azure Web Apps. Although it seems pretty straightforward to set it up there are important concerns that you need to address and in this post I'm going to try to outline them so that you could take maximum advantage of the service.

Search enable your applications with Azure Search

$
0
0
Azure Search is a search as a service offering that gives developers total control over indexing and searching of their content. It’s the control that sets Azure Search apart from public search offerings such as Google Custom Search. With Azure Search you, the developer, define what, how and how often will be indexed and how search UI, search and suggestion results will look like. It will require more work on your side as a developer but it’s that trade-off you’re likely to make to deliver precisely the search experience for your applications you need. In this post I’m going walk your through adding search capabilities to your applications. I’m going to use my blog as a sample application. But be aware that Azure Search is not limited to web applications. It exposes its functionality through a set of RESTful services so it can be used from just about any application that speaks HTTP.

Make sure to implement transient fault handling when running in the cloud

$
0
0
Applications running in the cloud or just making use of various external services are likely to face temporary failures when trying to communicate with these services. These failures could be network connectivity issues or request timeouts when external services are overloaded. An important aspect of these failures is that they are self-healing and if we retry calling services after a suitable delay these calls are likely to succeed.

How to provision Azure Search service with PowerShell

$
0
0
Azure Search Management API is built on top of Azure Resource Manager which is a new way of managing resource in Azure that you probably hear about more and more these days. The idea behind it is that instead of managing individual resources you start thinking in terms of your applications and what resources are needed for them. With powerful templates you can define resource groups containing resources that you need for your applications that you provision with literally a single command.

Automating Azure Search index operations

$
0
0
Last time we had a look at provisioning Azure Search service with Azure Resource Manager and PowerShell. The next step is to set up an index (or indexes) and decide how we are going to populate it. We should also index existing data for the first time once the index has been created. Automating these operations will enable us to re-build the index from scratch at any moment. This can be required not only during a new deployment to a new environment but also when necessary changes have been applied to our data structure.

First meet-up event of Belarus Azure User Group

$
0
0
On July, 22 2015 we've held the first meet-up event of Belarus Azure User Group where we shared experience building solution on Microsoft Azure, using various services and migrating existing solutions to the cloud. It was a special event for me because I was on stage speaking this time.

First look at Application Insights

$
0
0
Azure provides built-in capabilities for collecting diagnostic data of running applications. For example, in Web Apps we can setup server tracing for each HTTP request, persistence of detailed error pages  and failed request tracing. We can also enable application logging and use System.Diagnostics.Trace or a popular logging framework to capture valuable information about our applications. We can setup persistence of all of this data to Azure storage so we could analyze it later. It all comes out of the box. So why Application Insights?

Tracing and logging with Application Insights

$
0
0
Besides rich telemetry that is collected by Application Insights modules transparently for your applications you also want to make your custom tracing and logging messages part of the overall correlated diagnostics data so you could have even better insights into what's happening in your applications. Application Insights provides consistent APIs for .NET, JavaScript, Java and Android, Objective-C and Swift that allow you to send your custom messages optionally bundled with properties and metrics. You can use these APIs on the server, desktop, native device apps and in the web client code.

Event correlation in Application Insights

$
0
0
Application Insights uses several contextual properties for event correlation. The most generic one is Operation Id that allows us to analyze a series of events and traces as part of a single operation. Depending on the application type there can be additional correlation properties. For example, if we're talking about web requests these are also Session Id and User Id that allow us to group events and traces by the security and session context in which they occurred.

Azure Web Apps Continuous Deployment

$
0
0
Azure Web Apps provide a continuous deployment feature that allows you to quickly set up a continuous build and deployment process from your code repository. It implements a pull model when your repository is cloned to your web app, changes are pulled and the application is built when the web app gets notified from your source code hosting service and then deployed artifacts get copied to wwwroot folder. This is different from a more traditional model where you set up a build server that takes care of pulling sources, building them and preparing a deployment package that gets uploaded to the hosting environment.

Implementing Service Bus SAS keys rotation

$
0
0
Shared Access Signature (SAS) authentication provides a simple and flexible option to authenticate requests to Service Bus. You can define access rules on the entire namespace as well as individual entities such as queues, relays, topics and Event Hubs. While this is also possible with ACS authentication, what sets SAS option apart is the ability to grant access to Service Bus entities without giving out keys. This is achieved by issuing SAS tokens (or signatures, although the actual signatures are just part of them) that are bound to particular authorization policies and have a finite lifetime.

Scheduling web jobs in Basic tier web apps

$
0
0
You have an application application that is deployed to an Azure Web App running in Basic App Service hosting plan. You have a couple of web jobs there that are supposed to run on schedule and you chose to define the schedules with cron expressions. One day you noticed that these schedules never fired even though you remembered how you tested them on the Free plan and they seemed to work. You have Always On enabled as you want Kudu to always run to be able to trigger your scheduled jobs.

Presenting Application Insights at Belarus Azure Day 2015

$
0
0

On December, 13 2015 we’ve held a whole day live event dedicated to all things Azure. 8 speakers from Belarus, Ukraine and Russia presented on a wide array of topics from working efficiently with Azure storage and Service Bus to trendy container and microservices technologies to usage analytics with Application Insights and Mobile Engagement.

Belarus Azure Day 2015

Here’s the full list of topics and presenters:

I was talking about Application Insights and how it can help us get a better understanding of what's happing in our applications and how they are used. I demo'ed different kinds of events and correlation between them, built-in and custom metrics, client side and usage analytics and availability tests. I also covered integration aspects and how we can send our applications logs and traces to Application Insights so they become part of the whole telemetry that is gathered, analyzed and presented by the service.

Push notification flow with Azure Notification Hubs

$
0
0
One of the commonly expected features of mobile apps is an ability to receive push notifications, that is, notifications that do not require the apps to be up and running and having an established connection with their backend. Also if you have an app, chances are, you have it for more than one platform. Whatever the platform it is, a general push notification flow is relatively the same: * A mobile app contacts its native PNS to retrieve its handle; * Then it sends the handle to its backend; * The backend persists the handle for later usage; * When it needs to send a push notification the backend contacts the PNS using the handle to target a specific mobile app instance; * The PNS forwards the notification to the device specified by the handle. A Notification Hub stands in between your backend and the PNS. It is a broker that gives you a common API that abstracts your backend from communication details with a particular PNS. But that wouldn't be enough to make you want to use it. What makes Notification Hubs really useful is that they enable flexible addressing schemas and allow you to send messages to different platforms literally with a single call. This is achieved through maintaining a registry of subscriptions (PNS handles) and associated tags and templates. Let's have a look at an example. You are developing a mobile client app for a popular social network. The app should be able to notify users when people respond to their posts or comments or when someone follows them. Users want to be able to opt in or out of each type of notification. A single user usually has more than one device and she may set up different notification types on each device. When registering apps with a Notification Hub you provide a set of tags that will allow you to target future notifications to particular app installations: ``` (Android device): UserId:1 Event:Follow Event:Comment (Windows device): UserId:1 Event:Comment ``` Let's say someone comments on a post of this user and you want to deliver this notification to all user's devices where she subscribed to this type of event: ``` var tagExpression = "UserId:1 && event:Comment"; var notification = new Dictionary { { "message", "Someone commented on your post!" } }; await hub.SendTemplateNotificationAsync(notification, tagExpression); ``` Notice the `tagExpression` where you combine a set of tags that will be evaluated by the Notification Hub in order to determine a list of native push notification services and handles to be used to dispatch the message. In our case each of the user's devices will receive a notification as registrations from both of these devices happen to have the same set of tags. You can read up more on routing with tags and tag expressions [here](https://azure.microsoft.com/en-us/documentation/articles/notification-hubs-routing-tag-expressions/). What's this dictionary that we used as a notification payload? The dictionary contains values for placeholders that you define in platform specific templates. On a Windows device a template may look something like this: ``` $(message) ``` On an iOS device the template may look like this: ``` {"aps":{"alert":"$(message)"}} ``` You define template when you register application installation with a Notification Hub. You can read more on templates [here](https://azure.microsoft.com/en-us/documentation/articles/notification-hubs-templates/). ### PNS handle, registration ID and application ID App registration with a Notification Hub can be done directly from the client but I believe in all but very simple cases you will do it from the backend. The reason for that is that the backend needs to know the addressing schema and thus it has to control tags that are used during registration. There are 4 distinct activities that are related to setting up and sending push notifications: setting up a push notification channel, subscribing to topics, handling sign-off and dispatching notifications. In the remaining of this post I'm going to describe each one of them but before I continue I'd like to talk a little bit about app identification. PNS handles have limited life span and it's the responsibility of mobile apps to refresh them by requesting new handles from their corresponding native PNS. Notification Hubs should be able to distinguish between different devices but it cannot be done with just PNS handles as they are transient. To solve this problem, Notification Hubs generate long living registration IDs that should be persisted so that we can refer to devices’ registration each time we need to update PNS handles, tags or templates. Now the issue with registration IDs is that they are also transient. This is done on purpose to facilitate cleanup of mobile app instances that didn't properly unregister when they were uninstalled. For us it means that at some point registrations can expire and we should not use Notification Hubs as the only storage for registration details. A need for a local registry arises. The local registry will contain all of the information we need to recreate (or update) a Notification Hub registration. This will include registration ID, PNS handle and a bunch of app specific tags. Think of a sign-off scenario. When the user signs off you want to remove the registration so that no notifications are sent to this device anymore. When she signs back in you probably want to restore the registration. You will use a new PNS handle but you want to re-enable the user's subscriptions. We need a constant ID for app installation so we can re-associate the app instance with its existing device record in the local registry. This application ID will be generated by the mobile app and will be unique per app installation across mobile platforms. It should be generated when the app is installed and should survive sign off/sign in activities. The backend may also add application ID as a tag during registration with a Notification Hub. This will enable targeting a specific device by its ID. ### Registering a channel A 'channel' may sound somewhat fuzzy but what I mean here is a process to enable push notifications for an app instance. It's not about subscribing to app specific events but rather about performing all of the registration steps that are necessary to make an app instance push-capable. These steps should normally be carried out when the user signs in. ![Registering for push notifications](//az777544.vo.msecnd.net/blog-content/b77f1186-1a1b-4b93-a870-6ea2aaafd3f2.png) A mobile app requests a handle from its native PNS and calls a register endpoint on its backend. Besides the handle the app sends its application ID and a value indicating its platform type (Android, Apple, etc). The platform type is necessary as the backend needs to use a platform specific template when registering with a Notification Hub. In fact this template selection 'switch' that will happen during registration will be the only place where we actually care about the platform. The backend performs a registration against a Notification Hub by sending registration ID, PNS handle, platform template and a bunch of tags if they have been found in the local registry for the given application ID. If it's the first registration the backend can request a new registration ID from the Notification Hub. If it's a repeating registration the backend should try to re-use the registration ID from its local registry and be ready to handle `HttpStatusCode.Gone` response from the hub indicating that the registration had expired. In this case the backend should request another registration ID from the hub and retry the attempt. Have a look at some code example [here](https://msdn.microsoft.com/library/azure/dn743807.aspx?f=255&MSPPError=-2147217396). The backend finally persists the new handle and possibly a new registration ID in the local registry. This process is repeated when the mobile app needs to refresh its PNS handle or when the user re-signs into the app. ### Subscribing to topics This step is about updating the app’s registration when the user enables or disables a notification for an app specific event or topic. It should normally be done over a separate endpoint that your backend exposes. ![Subscribing to a topic](//az777544.vo.msecnd.net/blog-content/091a7975-3029-4c6b-96a4-9c1d4ac7304d.png) An app specific event should be represented as a tag and this tag needs to be added to the Notification Hub registration as well as persisted in the local registry. Note that there is an alternative registration procedure called **Installation**. It has certain advantages over a regular registration that I describe in this post, such as partial updates, automatic installationId insertion as a tag, etc., you can find more details [here](https://azure.microsoft.com/en-us/documentation/articles/notification-hubs-registration-management/)). It should be noted that the workflow that I describe here pretty much covers everything you can achieve with installations. ### Handling sign-off ![Handling sign-off](//az777544.vo.msecnd.net/blog-content/13d91898-e7fc-4043-ab50-bcd5386c6358.png) The backend should provide an endpoint for the mobile app to unregister when the user signs off. All it needs to pass in is its application ID. The backend will be able to look up the app's registration ID in the local registry and remove its registration from the Notification Hub. The backend should keep the app's record in the local registry (mainly for tags) so it can re-create proper subscriptions the next time the user signs in on that device. This is totally optional though. ### Dispatching notifications When an event is detected by the backend it needs to construct a notification payload and create a tag expression to properly address the message. The Notification Hub will use the expression to look up native PNS handles in its registry and will actually dispatch the notification to appropriate native push notification services.

Application request routing in Azure Web Apps

$
0
0
Azure Web Apps by default enable so-called sticky sessions when subsequent requests that are made within an established session get processed by the same instance of an app that served the very first request of the session. Web Apps rely on the IIS extension called [Application Request Routing](http://www.iis.net/learn/extensions/planning-for-arr) (ARR) to implement that and the idea is basically to add a cookie with a server instance identifier upon the first response so that subsequent requests include the cookie and thus can indicate to ARR which server instance to route them to. The feature is very useful when a lot of session state is loaded into memory and moving it to a distributed store is too expensive. It's also useful in scenarios when you need to quickly deploy your existing apps to Azure with little to none changes in code and/or configuration. However if you've built your app to be stateless ARR actually limits scalability of your system. Another thing to be aware of are long sessions. Think about a user who's got a tab with your app open for a long time and when he makes another request the instance that used to serve his session has long died. ### ARR in action Let's see how ARR works by deploying a sample application to an Azure Web App running with 2 instances. We're going to use a well known [MusicStore](https://github.com/aspnet/MusicStore) sample that allows users to buys music. Although it persists shopping carts in the database it uses in-memory session to store shopping cart identifiers. This is exactly the scenario that ARR is supposed to help with when deploying this kind of apps to web farms without making any design or code changes. But we will make a little change for our testing purposes. We're going make the app include a custom header in each response containing an ID of the Azure Web App instance serving the request: ``` app.Use(next => async context => { context.Response.OnStarting(state => { var ctx = (HttpContext)state; ctx.Response.Headers.Add("X-Instance-Id", Configuration["WEBSITE_INSTANCE_ID"]); return Task.FromResult(0); }, context); await next(context); }); ``` Now that we have a test app let's create a [JMeter](http://jmeter.apache.org/) script (test plan) that would emulate a user's activity of selecting a genre and adding a few albums from that genre to his shopping cart. ![JMeter test plan](//az777544.vo.msecnd.net/blog-content/7418b978-7717-41e9-9fca-1e2a8253549a.png) I used JMeter's capability to record web tests. Once the basic scenario has been recorded you normally clean up the calls you are not interested in and add post request processors and controllers to fully implement the behavior that you need. You can download the completed test plan from [here](https://az777544.vo.msecnd.net/blog-content/2016/03/MusicStore.jmx). On step 1 the user navigates to `/Store/Browse` path and passes `?Genre=Rock` query string parameter. The CSS extractor locates URLs to each album on the page and saves them in JMeter variables that will be used by the ForEach controller on step 2\. For the first 10 albums the ForEach controller first opens an album's page and then adds the album to the shopping cart. In the end we open the cart and verify that total sum is $89.90. Let's set the number of simultaneous users (threads) to 2 and ramp-up period to 0 or 1 second: ``` Thread 1: Response headers: HTTP/1.1 200 OK Cache-Control: no-cache Pragma: no-cache Transfer-Encoding: chunked Content-Type: text/html; charset=utf-8 Expires: -1 Vary: Accept-Encoding Server: Microsoft-IIS/8.0 Set-Cookie: .AspNet.Session=03e33212-4650-93c0-0cc2-d1fa6d4f3a5a; path=/; httponly X-Instance-Id: 1bcb92fe7c8bb579af8491a8a6da2bb9f589ffa9d2719f4f36a7d13e9b6359f3 X-Powered-By: ASP.NET Set-Cookie: ARRAffinity=1bcb92fe7c8bb579af8491a8a6da2bb9f589ffa9d2719f4f36a7d13e9b6359f3;Path=/;Domain=musicstore2.azurewebsites.net Date: Tue, 01 Mar 2016 12:40:26 GMT Thread 2: Response headers: HTTP/1.1 200 OK Cache-Control: no-cache Pragma: no-cache Transfer-Encoding: chunked Content-Type: text/html; charset=utf-8 Expires: -1 Vary: Accept-Encoding Server: Microsoft-IIS/8.0 Set-Cookie: .AspNet.Session=4854d1e5-14b8-82c4-d717-84cb954fec4d; path=/; httponly X-Instance-Id: a58e63fe330ef44eea87d6737206e361d6d9bab12d95c822f301420c3bcf36b9 X-Powered-By: ASP.NET Set-Cookie: ARRAffinity=a58e63fe330ef44eea87d6737206e361d6d9bab12d95c822f301420c3bcf36b9;Path=/;Domain=musicstore2.azurewebsites.net Date: Tue, 01 Mar 2016 12:40:27 GMT ``` We can see that requests from each thread were processed by different instances. Upon the first request the server added two cookies: session and ARR affinity that were then resent with each subsequent request. Note that the ARR affinity cookie values are basically the same as instance ID's that we return in our custom `X-Instance-Id` header. The test succeeded and both shopping carts contained expected number of items. ### Disabling ARR In order to prevent Azure Web Apps from adding the ARR affinity cookie we should add a special custom header to the response: ``` Arr-Disable-Session-Affinity: True ``` As MusicStore relies on in-memory session it will immediately break the shopping cart when running in a web farm. Let's demo it! First, let's update our middleware to add the disabling header: ``` app.Use(next => async context => { context.Response.OnStarting(state => { var ctx = (HttpContext)state; ctx.Response.Headers.Add("X-Instance-Id", Configuration["WEBSITE_INSTANCE_ID"]); ctx.Response.Headers.Add("Arr-Disable-Session-Affinity", "True"); return Task.FromResult(0); }, context); await next(context); }); ``` ``` Thread 1: Response headers: HTTP/1.1 200 OK Cache-Control: no-cache Pragma: no-cache Transfer-Encoding: chunked Content-Type: text/html; charset=utf-8 Expires: -1 Vary: Accept-Encoding Server: Microsoft-IIS/8.0 Set-Cookie: .AspNet.Session=632b8f9c-5aa1-e778-26bf-92333aa9fa49; path=/; httponly X-Instance-Id: 1bcb92fe7c8bb579af8491a8a6da2bb9f589ffa9d2719f4f36a7d13e9b6359f3 Arr-Disable-Session-Affinity: True X-Powered-By: ASP.NET Date: Tue, 01 Mar 2016 12:51:10 GMT Thread 2: Response headers: HTTP/1.1 200 OK Cache-Control: no-cache Pragma: no-cache Transfer-Encoding: chunked Content-Type: text/html; charset=utf-8 Expires: -1 Vary: Accept-Encoding Server: Microsoft-IIS/8.0 Set-Cookie: .AspNet.Session=e4f22745-8c2a-ac36-f753-3cce9c2e2469; path=/; httponly X-Instance-Id: a58e63fe330ef44eea87d6737206e361d6d9bab12d95c822f301420c3bcf36b9 Arr-Disable-Session-Affinity: True X-Powered-By: ASP.NET Date: Tue, 01 Mar 2016 12:51:48 GMT ``` We can see that again 2 different instances are processing requests from the test threads but there are no ARR affinity cookies any more. As a result subsequent requests get dispatched to different instances and shopping carts get filled up in an ad-hoc manner and of course in the end our test assertions fail. ![JMeter failed assertions](//az777544.vo.msecnd.net/blog-content/88cf9591-b6f4-4ec7-b1b1-68fe06dbace3.png) ### Distributed session store to the rescue! As we decided to scale out and disabled sticky sessions for potentially more efficient throughput we need to switch from memory to a distributed store for our session. It's pretty easy to achieve in ASP.NET Core as the session service relies on `IDistributedCache` implementation. The default one is a local cache that gets configured when you enable cache and session support in `Startup.cs`: ``` public void ConfigureServices(IServiceCollection services) { services.AddCaching(); services.AddSession(); } ``` However there are packages that provide SQL Server and Redis implementations of `IDistributedCache`. Let's add the Redis one to the application: ``` "dependencies": { "Microsoft.Extensions.Caching.Redis": "1.0.0-rc1-final" } ``` Now let's remove `services.AddCaching()` and configure the pipeline to use Redis cache instead: ``` public void ConfigureServices(IServiceCollection services) { services.AddRedisCache(); services.Configure(Configuration.GetSection("Redis")); services.AddSession(); } ``` For this to work we also need to add a 'Redis' section to the configuration with a property called 'Configuration' as defined in RedisCacheOptions but because the property contains a connection string to the Redis instance we should instead add an environment variable to the Web App (or a user secret when running locally): ``` Redis:Configuration = .redis.cache.windows.net,abortConnect=false,ssl=true,password=... ``` Once we have redeployed and re-run our test we can see that requests are still processed by different servers within the same session but the final shopping carts contain expected items.
Viewing all 60 articles
Browse latest View live