Deploying Google OR-Tools to Azure
Having a C# app use Google OR-Tools to solve a Job Shop Problem (JSP) in the last article technically works but standing up an entire MVC app to host a single end point is less than an ideal solution. Enter Azure functions. Light weight, easy to scale and connects to the Azure ecosystem. In this article we will create an Azure Function that accepts the same problem set via HTTP trigger, calls Google's OR tools API and returns the calculated output.
Using visual studio 2019 (community edition is fine) create a new project, search for Azure Functions and accept the defaults to create a new HTTP trigger function.
First we need to model our input data.
To test the input model serializes as expected add a break point in Visual Studio, start the function locally, mock the body data and Post in Postman.
Open a Quick Watch (Ctrl D, Q) on curProblemSet and drill in to check our object serialized from the body request. Everything looks good, 3 Jobs the first two with 3 tasks and the last with 2 tasks.
Next open Nuget packet manager and install Google.OrTools
Copy over the code from the JobShopController and... Errors?!
Some searching reveals a long history of Google libraries and azure functions not playing well together. After researching how to manually install 3rd party DLLs for an Azure function and double checking external DLLs were properly deployed it was time to deep dive into nuget package hierarchy and CPU architecture compatibility possibilities -- 3 hours later and I yield. It's time to work around the problem. A Core API will integrate with Azure triggers, the Power Platform and Common Data Service(CDS) and get us moving again.
Create a new ASP.NET Core Web Application -> Name -> Create -> select API and ensure configure for HTTPS is checked -> create. Move our input models over, create a new endpoint, fire up Postman and let's test the input serialization.
Reusing the same body data from our function test, adjust the URL to the new localhost endpoint and.... 415 Unsupported Media Type?
Set the Header content-type to application/json, switch the Body type to raw with JSON and the API now properly deserializes our ProblemSet.
With things working locally it's time to tidy up the code a bit, publish to Azure, test our deployed API with Postman and... 500 Internal Server Error?!?
Let's take a look at the app insights -> investigate -> failures
Turns out a BadImageFormatException has nothing to do with gifs or pngs but a failure when an application attempts to access a .dll or .exe incompatible with the current run-time. Putting the pieces together; Google libraries work locally when run in a web app under .NET and Core run-times but not for an Azure function and neither run-time works when deployed on Azure. For those playing along at home have you figured it out yet? That's right, Azure containers are .NET 32 bit by default.
Fortunately we can easily change an app service's stack to Core and platform to 64 bit.
Save the changes, restart our app service and check it out in Postman
Victory! A 200 OK is returned along with our solved payload.
Thanks for coming along on the journey and stop back next time as we add a UI to our API.
The URLs shift from jspapi.az* to jspdemoapi.az* when I switched app service plans. A tangible reminder exceptions and time-outs are computationally expensive.
Hi Derek, you wrote this article almost six years ago, yet here I am to express my gratitude for the help it provided me. It took me a few days to explore the possible causes of this strange behavior, until a somewhat desperate search led me to stumble upon your article. Thank you and have a great day!
Not all heroes wear capes