{"id":46506,"date":"2014-07-28T11:06:30","date_gmt":"2014-07-28T08:06:30","guid":{"rendered":"https:\/\/www.altoros.com\/blog\/?p=46506"},"modified":"2020-04-14T16:10:22","modified_gmt":"2020-04-14T13:10:22","slug":"net-on-cloud-foundry-part-2-prototyping-with-iron-foundry","status":"publish","type":"post","link":"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/","title":{"rendered":".NET on Cloud Foundry, Part 2: Prototyping with Iron Foundry"},"content":{"rendered":"<p><center><\/p>\n<p><a href=\"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-1-installation-on-windows-and-using-iron-foundry\/\">Part 1<\/a> | <strong>Part 2<\/strong> | <a href=\"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-3-deploying-a-mapreduce-application-with-mono\/\">Part 3<\/a><\/p>\n<p><\/center><\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-transparent ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/#Building_a_MapReduce_PoC\" >Building a MapReduce PoC<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/#Hosting_web_apps_with_Iron_Foundry\" >Hosting web apps with Iron Foundry<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/#Enabling_messaging_with_MongoDBs_capped_collections\" >Enabling messaging with MongoDB&#8217;s capped collections<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/#Implementing_a_notifier_with_WebSockets\" >Implementing a notifier with WebSockets<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/#Assembling_a_test_app_for_Iron_Foundry\" >Assembling a test app for Iron Foundry<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/#Implementing_a_word_search_algorithm_with_MapReduce\" >Implementing a word search algorithm with MapReduce<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/#Deploying_applications_with_Iron_Foundry\" >Deploying applications with Iron Foundry<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/#Validating_a_prototype_in_Iron_Foundry\" >Validating a prototype in Iron Foundry<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/#Further_reading\" >Further reading<\/a><\/li><\/ul><\/nav><\/div>\n<h3><span class=\"ez-toc-section\" id=\"Building_a_MapReduce_PoC\"><\/span>Building a MapReduce PoC<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Most customers prefer to validate a concept before investing into a production system. In our case, an ultimate solution should allow for long-running computations, have a web interface for setting tasks, and support MapReduce or other data processing methods. So, an ideal prototype would be a platform that provides a simple method for deploying, scaling, and monitoring apps. That is what Iron Foundry does.<\/p>\n<p>In this post, we\u2019ll describe how to create a prototype with Iron Foundry on Cloud Foundry. Our test application will use MapReduce to find the most popular words in a text. The picture below demonstrates the data processing workflow.<\/p>\n<p><center><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/data-processing-workflows-with-iron-foundry.png\"><img decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/data-processing-workflows-with-iron-foundry.png\" alt=\"\" width=\"360\" class=\"aligncenter size-full wp-image-46516\" \/><\/a><\/center><\/p>\n<p>As you can see, text is transferred from a client to a web component for processing. At this stage, the job is divided between available Mappers, which send the results to a Reducer. In its turn, the Reducer performs final computations and returns the output back to the client via a Notifier. Below, we will describe how to create each of the components, establish communication between them, and deploy an application with Iron Foundry.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Hosting_web_apps_with_Iron_Foundry\"><\/span>Hosting web apps with Iron Foundry<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>So, let&#8217;s start with the first component of the system\u2014a website. It is easy to push a standard MVC application to Iron Foundry using IIS Hostable Web Core. We didn&#8217;t even have to change the code or do additional configuration. And what about hosting web applications with Iron Foundry?<\/p>\n<p>Our web application will not depend on IIS and\u2014most probably\u2014it will use HTTP Listeners to handle traffic. Keep it in mind that you should know port numbers to enable listening to new HTTP requests. We learned how to do it in the Iron Foundry Google group.<\/p>\n<pre style=\"padding-left: 20px;\">var _listener = new HttpListener();\r\nvar port = Environment.GetEnvironmentVariable(\"VCAP_APP_PORT\");\r\n_listener.Prefixes.Add(\"http:\/\/*:\" + port + \"\/\");<\/pre>\n<p>So, Cloud Foundry router will redirect all requests to <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">VCAP_APP_PORT<\/code>. It is also necessary to use a <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">http:\/\/*:port\/<\/code> pattern to follow the Iron Foundry firewall rule.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Enabling_messaging_with_MongoDBs_capped_collections\"><\/span>Enabling messaging with MongoDB&#8217;s capped collections<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Now, we should provide communication between all the components of a system. If we take Microsoft Azure, Message Bus is used as a messaging infrastructure. In the current version of <a href=\"http:\/\/ironfoundry.me\/\" target=\"_blank\" rel=\"noopener noreferrer\">ironfoundry.me<\/a>, there are only two services (MS SQL and MongoDB), and no messaging options are provided. Definitely, we can use <a href=\"https:\/\/www.cloudamqp.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">RabbitMQ-as-a-Service<\/a>, but its free plan does not allow us to have more than three connections, and it lacks some other features our demo needs. We knew that it is not a great deal to build a custom messaging component based on the <a href=\"https:\/\/docs.mongodb.com\/manual\/core\/capped-collections\/\" rel=\"noopener noreferrer\" target=\"_blank\">MongoDB capped collections<\/a>. To test this approach, one should know how to:<\/p>\n<ul>\n<li>add a MongoDB service<\/li>\n<li>get a connection string<\/li>\n<\/ul>\n<p>Adding MongoDB is simple, all you need is execute two commands in the command line interface: create a service and bind a service. Below, you will see an example of creating a <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">my-mongo<\/code> service and binding it to the Mapper app.<\/p>\n<p><center;\"><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/creating-my-mongo-service-cloud-foundry-net.jpg\"><img decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/creating-my-mongo-service-cloud-foundry-net.jpg\" alt=\"\" width=\"640\" class=\"aligncenter size-full wp-image-46520\" \/><\/a><\/center><\/p>\n<p>After binding, the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">VCAP_SERVICES<\/code> environment variable will contain all the necessary details to establish a connection.<\/p>\n<pre style=\"padding-left: 20px;\">const string envName = \"VCAP_SERVICES\"; \r\nvar settings = Environment.GetEnvironmentVariable(envName); \r\nvar jmongo = JObject.Parse(settings); \r\nvar db = jmongo[\"mongodb-2.2\"][0][\"credentials\"][\"db\"]; \r\nvar url = jmongo[\"mongodb-2.2\"][0][\"credentials\"][\"url\"]; \r\nvar client = new MongoClient(url.ToString()); \r\nvar server = client.GetServer(); \r\nvar database = server.GetDatabase(db.ToString());<\/pre>\n<p>Unfortunately, our first attempts to launch our own messaging service failed. We were able to connect, but when we were trying to start any activity, there appeared a message: <em>\u201cSystem.IO.EndOfStreamException: Attempted to read past the end of the stream.\u201d<\/em> As we have already tested this solution locally and it worked well, we were not really inspired by the idea to start creating a new one over again. Here, we should do justice to the ironfoundry.me developers. They are open for communication and listen to the community. So, very soon they adjusted a default configuration setting on the MongoDB deployment, which resolved this issue.<\/p>\n<p><p>However, there is another way of adding a messaging service. We found <a href=\"https:\/\/mlab.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">MongoDB-as-a-Service<\/a> in the list of Cloud Foundry services. This solution has a free plan with lots of capabilities. So, we have just created a new database and successfully run our Iron Foundry MongoDB Queue test application.<\/p>\n<p>Next time, we will tell how to create a notifier using WebSockets and show how to build a simple MapReduce app in Iron Foundry.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Implementing_a_notifier_with_WebSockets\"><\/span>Implementing a notifier with WebSockets<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>In the beginning, we showed the architecture of the system. As you can see, a Notifier app pushes real-time updates to the client via WebSockets. There are many frameworks that provide the required functionality. We opted for <a href=\"http:\/\/xsockets.net\/\" target=\"_blank\" rel=\"noopener noreferrer\">XSockets.NET<\/a>, a framework for building real-time .NET apps.<\/p>\n<p>We needed to create a self-hosted XSockets server in Iron Foundry and establish communication between it and the HTML client. Unfortunately, we failed to negotiate a handshake with XSockets in Iron Foundry, since the Cloud Foundry router had some issues with the WebSockets. Then, we came up with another idea of starting a Node.js HTTP server and attaching a socket.io instance to it.<\/p>\n<pre style=\"padding-left: 20px;\">>var host = process.env.VCAP_APP_HOST || \"localhost\"; \r\nvar port = process.env.VCAP_APP_PORT || 3001;\r\n&nbsp;\r\nvar server = require('http').Server(); \r\nvar io = require('socket.io'); \r\nserver.listen(port, host); \r\nio.listen(server);<\/pre>\n<p>It worked out, and we became able to access the HTML client. However, one more thing was left\u2014the server should be accessible from the .NET Reducer console app. That is why we had to use socket.io v0.9 instead of sockets.io v1, which was not supported by the socket.io library. So, the notifier was implemented as a Node.js server in combination with the socket.io package v0.9.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Assembling_a_test_app_for_Iron_Foundry\"><\/span>Assembling a test app for Iron Foundry<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>At this stage, you should put all components into a single system. Our web client is a simple HTML page developed with AngularJS and Bootstrap. It looks like shown below.<\/p>\n<p><center><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/assembling-a-test-app-for-Iron-Foundry.png\"><img decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/assembling-a-test-app-for-Iron-Foundry.png\" alt=\"\" width=\"360\" class=\"aligncenter size-full wp-image-46522\" \/><\/a><\/center><\/p>\n<p>We will host the page and services via ServiceStack. To start such a web component in Iron Foundry, you need to get a <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">VCAP_APP_PORT<\/code> variable.<\/p>\n<pre style=\"padding-left: 20px;\">var uri = \"http:\/\/*:\" + Environment.GetEnvironmentVariable(\"VCAP_APP_PORT\") + \"\/\"; \r\nvar host = new AppHost(); \r\n&nbsp;&nbsp;host.Init(); \r\nhost.Start(uri); \r\n\"Type Ctrl+C to quit..\".Print(); \r\n&nbsp;&nbsp;Thread.Sleep(Timeout.Infinite);<\/pre>\n<p>The <em>Start<\/em> button will send the text to the server, where it will be divided into several parts and propagated to the Mapper applications.<\/p>\n<pre style=\"padding-left: 20px;\">var parts = _mappers.Count; \r\nvar chunks = Helper.SplitText(req.Text, parts); \r\nfor (var i = 0; i &lt; parts; i++) \r\n&nbsp;&nbsp;SendChunk(_mappers[i], chunks[i]);<\/pre>\n<p>Where <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">SendChunk<\/code>:<\/p>\n<pre style=\"padding-left: 20px;\">var queue = new MongoQ(Constants.QueueLength, mapper);\r\nqueue.Send(new Message(chunk));<\/pre>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Implementing_a_word_search_algorithm_with_MapReduce\"><\/span>Implementing a word search algorithm with MapReduce<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The main goal of our algorithm was finding a word that has been used most frequently in a text. Planning logic of a prototype app in Iron Foundry is the same as on any other platform, so the steps described in this post are quite universal for all MapReduce workloads.<\/p>\n<p>The diagram below illustrates how the MapReduce algorithm works.<\/p>\n<p><center><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/map-reduce-word-algorithm-on-cloud-foundry.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/map-reduce-word-algorithm-on-cloud-foundry.png\" alt=\"\" width=\"618\" height=\"220\" class=\"aligncenter size-full wp-image-46524\" \/><\/a><\/center><\/p>\n<p>Basically, the test task can be represented by two simple unit tests.<\/p>\n<pre style=\"padding-left: 20px;\">[TestMethod]\r\n        public void MapReduce()\r\n        {\r\n            const string text = \"a bb ccc ccc\";\r\n            const string result = \"a:1,bb:1,ccc:2,\";\r\n\r\n            var map = Helper.MapReduce(text);\r\n            Assert.AreEqual(result, map);\r\n        }\r\n\r\n        [TestMethod]\r\n        public void Reduce()\r\n        {\r\n            const int max = 3;\r\n            var words = new List<keyvaluepair <string, int>> { new KeyValuePair<string , int>(\"a\", 1), new KeyValuePair<\/string><string , int>(\"a\", 2), new KeyValuePair<\/string><string , int>(\"b\", 2) };\r\n\r\n            var reduce = Helper.Reduce(words).ToList();\r\n            Assert.AreEqual(reduce[0].Value, max);\r\n        } <\/string><\/keyvaluepair><\/pre>\n<p>You can use the following code to implement the Mapper tasks in C#.<\/p>\n<pre style=\"padding-left: 20px;\">text.Split(new[] { \" \", \".\", \",\", \"\\n\", \"\\r\\n\", \"*\" }, StringSplitOptions.RemoveEmptyEntries)\r\n                .Select(item => new KeyValuePair<string , int>(item, 1))\r\n                .GroupBy(k => k.Key, v => v.Value).Select(s => new KeyValuePair<\/string><string , int>(s.Key, s.Count()))\r\n                .Aggregate(\"\", (current, word) => current + (word.Key + \":\" + word.Value + \",\"));<\/string><\/pre>\n<p>As an alternative, if you prefer a functional style, you can create the Mapper tasks with F#.<\/p>\n<pre style=\"padding-left: 20px;\">let words input= Regex.Matches(input, \"\\w+\") |> Seq.cast |> Seq.map (fun (x:Match) -> x.Value.ToLower()) |> Seq.countBy id |> Seq.reduce (fun (a, b) (c, d) -> (a + \":\" + b.ToString() + \",\" + c + \":\" + d.ToString() + \",\", 1)) |> fst<\/pre>\n<p>or<\/p>\n<pre style=\"padding-left: 20px;\">let words (input:string) = input.Split([|\" \"; \".\"; \",\"; \"\\n\"; \"\\r\\n\"; \"*\"|], StringSplitOptions.RemoveEmptyEntries) |> Seq.cast |> Seq.countBy id |> Seq.reduce (fun (a, b) (c, d) -> (a + \":\" + b.ToString() + \",\" + c + \":\" + d.ToString() + \",\", 1)) |> fst<\/pre>\n<p>Since the C#-based solution worked a little bit faster under the workload used for a prototype app, we opted for it. Now, we are not going to research into how to improve performance, since it is a topic for a separate blog post.<\/p>\n<p>For reducing operation, we can use the approach described below.<\/p>\n<pre style=\"padding-left: 20px;\">allWords.GroupBy(k => k.Key).Select(s => new KeyValuePair<string , int>(s.Key, s.Sum(p => p.Value))).OrderByDescending(o => o.Value);<\/string><\/pre>\n<p>So, the preparations are over, and now we should think how an app will process the Mapper and Reducer tasks. The first component will map the text and send it. You can implement a Reducer using the reactor pattern. It has an Event Demultiplexer, which will display names of Mappers ready for sequential processing.<\/p>\n<pre style=\"padding-left: 20px;\">var demultiplexer = new MongoQ<message>(Constants.QueueSmall, Constants.Demultiplexer);\r\n            while (true)\r\n            {\r\n                var availableMappers = demultiplexer.Receive();             \r\n                ProcessMessage(availableMappers);               \r\n            } <\/message><\/pre>\n<p>In the next section, we will tell you how to assemble all parts of the prototype into a single solution. You will also learn how to deploy a MapReduce app to Iron Foundry.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Deploying_applications_with_Iron_Foundry\"><\/span>Deploying applications with Iron Foundry<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>In this section, we will show you how to deploy an application that consists of four major components: a website, a Mapper, a Reducer, and a Notifier. The picture below illustrates the workflow for processing a request from a client application. Each of the components can be scaled horizontally.<\/p>\n<p><center><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/mapreduce-processing-a-request-from-a-client-app-cloud-foundry.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/mapreduce-processing-a-request-from-a-client-app-cloud-foundry.png\" alt=\"\" width=\"339\" height=\"420\" class=\"aligncenter size-full wp-image-46525\" \/><\/a><\/center><\/p>\n<p>Our main goal is to deploy the system as easily and quickly as possible. You need to copy binary output with a post-build event for each application to a folder with the following structure.<\/p>\n<pre style=\"padding-left: 20px;\"><message>\r\n-deploy\r\n\t-web\r\n\t-mapper\r\n\t-reducer\r\n\t-notifier\r\n<\/message><\/pre>\n<p>After that, add the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">manifest.yml<\/code> file to the deploy folder and run the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">cf-push<\/code> command. The manifest will provide all the information necessary for the cloud solution to deploy the system. The <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">manifest.yml<\/code> file looks like shown below.<\/p>\n<pre style=\"padding-left: 20px;\"><message>\r\n---\r\napplications:\r\n- name: ironicweb\r\n  memory: 256MB\r\n  stack: windows2012\r\n  instances: 2\r\n  path: .\/web\/\r\n- name: mapper\r\n  memory: 256MB\r\n  stack: windows2012\r\n  instances: 4\r\n  no-route: true\r\n  path: .\/mapper\/\r\n- name: reducer\r\n  memory: 256MB\r\n  stack: windows2012\r\n  instances: 1\r\n  no-route: true\r\n  path: .\/reducer\/\r\n- name: ironicnotifier\r\n  buildpack: https:\/\/github.com\/cloudfoundry\/heroku-buildpack-nodejs.git\r\n  memory: 256MB\r\n  instances: 1\r\n  path: .\/notifier\/\r\n  command: node notifier.js\r\n<\/message><\/pre>\n<p>Please pay attention to the \u201cstack\u201d element. It should be Windows 2012 for .NET applications. If your application is designed to run as a background worker, you must specify <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">no-route: true<\/code>. Once this setting is enabled, the Iron Foundry component will stop trying to connect to the application to check its health status.<\/p>\n<p>Since a Notifier is not a .NET application\u2014it uses a slightly different manifest file\u2014we have added a buildpack with Node.js. It specifies what runtime must be prepared for the application. In the manifest file, we added a command that will execute the Node.js file. Remember to add the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">package.json<\/code> file to the Notifier folder. This file must contain details about the deployed application.<\/p>\n<pre style=\"padding-left: 20px;\"><message>\r\n{\r\n    \"name\": \"notifier\",\r\n    \"version\": \"0.0.1\",\r\n    \"dependencies\": {\r\n        \"socket.io\": \"0.9.17\"\r\n    },\r\n    \"engines\": {\r\n        \"node\": \"0.10.x\",\r\n        \"npm\": \"1.3.x\"\r\n    }\r\n}\r\n<\/message><\/pre>\n<p>After you have pushed your applications, open <a href=\"http:\/\/ironicweb.beta.ironfoundry.me\/\" target=\"_blank\" rel=\"noopener noreferrer\">ironicweb.beta.ironfoundry.me<\/a> to make sure that all of your application instances (10 in our system) work together and respond to requests.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Validating_a_prototype_in_Iron_Foundry\"><\/span>Validating a prototype in Iron Foundry<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>In this section, we will share our experience with Iron Foundry\u2019s integration capabilities. At this stage, we have already used Iron Foundry to deploy our product on Cloud Foundry. There are four connected microservices horizontally scaled to eight instances.<\/p>\n<p><center><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/microservices-scaled-horizontally-on-cloud-foundry.png\"><img decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/microservices-scaled-horizontally-on-cloud-foundry.png\" alt=\"\" width=\"640\" class=\"aligncenter size-full wp-image-46527\" \/><\/a><\/center><\/p>\n<p>Two of the components can be accessed via HTTP using these URLs: <a href=\"http:\/\/ironicweb.beta.ironfoundry.me\/\" target=\"_blank\" rel=\"noopener noreferrer\">ironicweb.beta.ironfoundry.me<\/a> and <a href=\"http:\/\/ironicnotifier.beta.ironfoundry.me\/\" target=\"_blank\" rel=\"noopener noreferrer\">ironicnotifier.beta.ironfoundry.me<\/a> (the second one is a node HTTP server for socket communication without a UI). IronicWeb helps to find the most popular words in texts. The web interface allows for entering text manually or via a simple file upload.<\/p>\n<p>The first step after the web page has loaded is to discover mappers. To do it, IronicWeb uses a custom MongoDB messaging component. This enables us to scale mappers via the command line interface and ensures that the new map-reduce job will use all available resources.<\/p>\n<p><center><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/using-ironicweb-for-mar-reduce-jobs-cloud-foundry.png\"><img decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/using-ironicweb-for-mar-reduce-jobs-cloud-foundry.png\" alt=\"\" width=\"640\" class=\"aligncenter size-full wp-image-46528\" \/><\/a><\/center><\/p>\n<p>To re-deploy the entire system, we must run just one simple <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">cf p<\/code> command and wait for staging to finish, which takes less than a minute. There is no need to worry about the environment and various settings\u2014we can just code and enjoy the result.<\/p>\n<p>In the next post, we will explain how to move the whole system to the original Cloud Foundry platform without Iron Foundry. In addition, we will go over the current options and limitations for.NET products on Cloud Foundry.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Further_reading\"><\/span>Further reading<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<ul>\n<li><a href=\"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-1-installation-on-windows-and-using-iron-foundry\/\" target=\"_blank\" rel=\"noopener noreferrer\">.NET on Cloud Foundry, Part 1: Installation on Windows and Using Iron Foundry<\/a><\/li>\n<li><a href=\"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-3-deploying-a-mapreduce-application-with-mono\/\">.NET on Cloud Foundry, Part 3: Deploying a MapReduce Application with Mono<\/a><\/li>\n<\/ul>\n<hr \/>\n<p><center><small>This series was written by Alex Makarenko; edited by <a href=\"https:\/\/www.altoros.com\/blog\/author\/volha-kurylionak\/\">Volha Kurylionak<\/a> and <a href=\"https:\/\/www.altoros.com\/blog\/author\/alex\/\">Alex Khizhniak<\/a>.<\/small><\/center><\/p>\n","protected":false},"excerpt":{"rendered":"<\/p>\n<p>Part 1 | Part 2 | Part 3<\/p>\n<\/p>\n<p>Building a MapReduce PoC<\/p>\n<p>Most customers prefer to validate a concept before investing into a production system. In our case, an ultimate solution should allow for long-running computations, have a web interface for setting tasks, and support MapReduce or other data processing methods. So, [&#8230;]<\/p>\n","protected":false},"author":38,"featured_media":46528,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","footnotes":"","_links_to":"","_links_to_target":""},"categories":[214],"tags":[873,206],"class_list":["post-46506","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-cloud-native","tag-oss-cloud-foundry"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>.NET on Cloud Foundry, Part 2: Prototyping with Iron Foundry | Altoros<\/title>\n<meta name=\"description\" content=\"This blog post demonstrates how to deploy a prototype app\u2014capable of word search\u2014on Cloud Foundry.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\".NET on Cloud Foundry, Part 2: Prototyping with Iron Foundry | Altoros\" \/>\n<meta property=\"og:description\" content=\"Part 1 | Part 2 | Part 3 Building a MapReduce PoC Most customers prefer to validate a concept before investing into a production system. In our case, an ultimate solution should allow for long-running computations, have a web interface for setting tasks, and support MapReduce or other data processing methods. So, [...]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/\" \/>\n<meta property=\"og:site_name\" content=\"Altoros\" \/>\n<meta property=\"article:published_time\" content=\"2014-07-28T08:06:30+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-04-14T13:10:22+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/using-ironicweb-for-mar-reduce-jobs-cloud-foundry.png\" \/>\n\t<meta property=\"og:image:width\" content=\"975\" \/>\n\t<meta property=\"og:image:height\" content=\"598\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Alex Makarenko\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Alex Makarenko\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"2 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\\\/\"},\"author\":{\"name\":\"Alex Makarenko\",\"@id\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/#\\\/schema\\\/person\\\/e355ca9f2206c0529037e48629e0de4b\"},\"headline\":\".NET on Cloud Foundry, Part 2: Prototyping with Iron Foundry\",\"datePublished\":\"2014-07-28T08:06:30+00:00\",\"dateModified\":\"2020-04-14T13:10:22+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\\\/\"},\"wordCount\":486,\"commentCount\":0,\"image\":{\"@id\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/wp-content\\\/uploads\\\/2014\\\/07\\\/using-ironicweb-for-mar-reduce-jobs-cloud-foundry.png\",\"keywords\":[\"Cloud-Native\",\"OSS Cloud Foundry\"],\"articleSection\":[\"Tutorials\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.altoros.com\\\/blog\\\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\\\/\",\"url\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\\\/\",\"name\":\".NET on Cloud Foundry, Part 2: Prototyping with Iron Foundry | Altoros\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/wp-content\\\/uploads\\\/2014\\\/07\\\/using-ironicweb-for-mar-reduce-jobs-cloud-foundry.png\",\"datePublished\":\"2014-07-28T08:06:30+00:00\",\"dateModified\":\"2020-04-14T13:10:22+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/#\\\/schema\\\/person\\\/e355ca9f2206c0529037e48629e0de4b\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.altoros.com\\\/blog\\\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/wp-content\\\/uploads\\\/2014\\\/07\\\/using-ironicweb-for-mar-reduce-jobs-cloud-foundry.png\",\"contentUrl\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/wp-content\\\/uploads\\\/2014\\\/07\\\/using-ironicweb-for-mar-reduce-jobs-cloud-foundry.png\",\"width\":975,\"height\":598},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\".NET on Cloud Foundry, Part 2: Prototyping with Iron Foundry\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/\",\"name\":\"Altoros\",\"description\":\"Insight\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/#\\\/schema\\\/person\\\/e355ca9f2206c0529037e48629e0de4b\",\"name\":\"Alex Makarenko\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/083fdfcbdf4d372139cf32711db57e55f697f43bbb05939609132d3d70590123?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/083fdfcbdf4d372139cf32711db57e55f697f43bbb05939609132d3d70590123?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/083fdfcbdf4d372139cf32711db57e55f697f43bbb05939609132d3d70590123?s=96&d=mm&r=g\",\"caption\":\"Alex Makarenko\"},\"url\":\"https:\\\/\\\/www.altoros.com\\\/blog\\\/author\\\/alex-makarenko\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":".NET on Cloud Foundry, Part 2: Prototyping with Iron Foundry | Altoros","description":"This blog post demonstrates how to deploy a prototype app\u2014capable of word search\u2014on Cloud Foundry.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/","og_locale":"en_US","og_type":"article","og_title":".NET on Cloud Foundry, Part 2: Prototyping with Iron Foundry | Altoros","og_description":"Part 1 | Part 2 | Part 3 Building a MapReduce PoC Most customers prefer to validate a concept before investing into a production system. In our case, an ultimate solution should allow for long-running computations, have a web interface for setting tasks, and support MapReduce or other data processing methods. So, [...]","og_url":"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/","og_site_name":"Altoros","article_published_time":"2014-07-28T08:06:30+00:00","article_modified_time":"2020-04-14T13:10:22+00:00","og_image":[{"width":975,"height":598,"url":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/using-ironicweb-for-mar-reduce-jobs-cloud-foundry.png","type":"image\/png"}],"author":"Alex Makarenko","twitter_misc":{"Written by":"Alex Makarenko","Est. reading time":"2 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/#article","isPartOf":{"@id":"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/"},"author":{"name":"Alex Makarenko","@id":"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/e355ca9f2206c0529037e48629e0de4b"},"headline":".NET on Cloud Foundry, Part 2: Prototyping with Iron Foundry","datePublished":"2014-07-28T08:06:30+00:00","dateModified":"2020-04-14T13:10:22+00:00","mainEntityOfPage":{"@id":"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/"},"wordCount":486,"commentCount":0,"image":{"@id":"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/#primaryimage"},"thumbnailUrl":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/using-ironicweb-for-mar-reduce-jobs-cloud-foundry.png","keywords":["Cloud-Native","OSS Cloud Foundry"],"articleSection":["Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/","url":"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/","name":".NET on Cloud Foundry, Part 2: Prototyping with Iron Foundry | Altoros","isPartOf":{"@id":"https:\/\/www.altoros.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/#primaryimage"},"image":{"@id":"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/#primaryimage"},"thumbnailUrl":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/using-ironicweb-for-mar-reduce-jobs-cloud-foundry.png","datePublished":"2014-07-28T08:06:30+00:00","dateModified":"2020-04-14T13:10:22+00:00","author":{"@id":"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/e355ca9f2206c0529037e48629e0de4b"},"breadcrumb":{"@id":"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/#primaryimage","url":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/using-ironicweb-for-mar-reduce-jobs-cloud-foundry.png","contentUrl":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2014\/07\/using-ironicweb-for-mar-reduce-jobs-cloud-foundry.png","width":975,"height":598},{"@type":"BreadcrumbList","@id":"https:\/\/www.altoros.com\/blog\/net-on-cloud-foundry-part-2-prototyping-with-iron-foundry\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.altoros.com\/blog\/"},{"@type":"ListItem","position":2,"name":".NET on Cloud Foundry, Part 2: Prototyping with Iron Foundry"}]},{"@type":"WebSite","@id":"https:\/\/www.altoros.com\/blog\/#website","url":"https:\/\/www.altoros.com\/blog\/","name":"Altoros","description":"Insight","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.altoros.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/e355ca9f2206c0529037e48629e0de4b","name":"Alex Makarenko","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/083fdfcbdf4d372139cf32711db57e55f697f43bbb05939609132d3d70590123?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/083fdfcbdf4d372139cf32711db57e55f697f43bbb05939609132d3d70590123?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/083fdfcbdf4d372139cf32711db57e55f697f43bbb05939609132d3d70590123?s=96&d=mm&r=g","caption":"Alex Makarenko"},"url":"https:\/\/www.altoros.com\/blog\/author\/alex-makarenko\/"}]}},"_links":{"self":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts\/46506","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/users\/38"}],"replies":[{"embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/comments?post=46506"}],"version-history":[{"count":16,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts\/46506\/revisions"}],"predecessor-version":[{"id":53438,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts\/46506\/revisions\/53438"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/media\/46528"}],"wp:attachment":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/media?parent=46506"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/categories?post=46506"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/tags?post=46506"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}