📜 ⬆️ ⬇️

Host an Azure cloud service on regular vds

I am writing web projects in visual studio, and with each new version of the studio, it seems to be sharpened to work with Windows Azure. I like Azura, although I only use a small set of options. The main thing for me is Cloud service. The cloud service is great for deploying a distributed server.

So, I create a cloud service, in which I add one web role (IIS virtual machine), one worker (virtual machine without IIS) and a shared class library. After publishing, my roles are assigned an ip-address and different ports. That is, immediately there is a tcp network, manual settings are minimal and can be done in the studio itself. You can, for example, make a public access point for a worker, but I do not need it. My worker will be hidden from outside eyes and a wcf server will hang on it, and my roles will communicate over a fast local network.

I bring general classes to the library (which I connect to all roles), for example, the interface and communication channel:

[ServiceContract] public interface IwcfChat { [OperationContract] string SendMessage(string userId, string userName, string text); [OperationContract] string GetMessages(string userId, string userName); } //================ public sealed class wcfChat:IDisposable { IwcfChat _channel; ChannelFactory<IwcfChat> factory = null; public wcfChat() { NetTcpBinding b = new NetTcpBinding(); b.Security.Mode = SecurityMode.None; b.Security.Message.ClientCredentialType = MessageCredentialType.None; #if(DEBUG) EndpointAddress address = new EndpointAddress("net.tcp://127.255.0.1:9003/wcfChat"); #else EndpointAddress address = new EndpointAddress("net.tcp://"+spr.wcfIP+":9003/wcfChat"); #endif factory = new ChannelFactory<IwcfChat>(b, address); factory.Faulted += OnChannelFaulted; factory.Open(); } public IwcfChat channel { get { if (factory != null && factory.State == CommunicationState.Opened) { if(_channel==null) _channel = factory.CreateChannel(); return _channel; } return null; } } void OnChannelFaulted(object sender, EventArgs e) { factory.Abort(); } public void Dispose() { factory.Close(); } } 

')
I call the methods in the web role like this:

  using (var chat = new wcfChat()) { res = chat.channel.SendMessage(id, name, text); } 


Accordingly, in the worker I have the implementation of methods from the interface (SendMessage, GetMessage), I will not paint them, as well as in the worker at startup, the code that makes it the host for wcf is executed:

 public override bool OnStart() { //      ServicePointManager.DefaultConnectionLimit = 12; // Create the host ServiceHost host = new ServiceHost(typeof(wcfChat)); // Read config parameters string hostName = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["port"].IPEndpoint.Address.ToString(); // Create Metadata ServiceMetadataBehavior metadatabehavior = new ServiceMetadataBehavior(); host.Description.Behaviors.Add(metadatabehavior); Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding(); string mexendpointurl = string.Format("net.tcp://{0}:{1}/wcfChatMetadata", hostName, 8003); host.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, mexendpointurl, new Uri(mexendpointurl)); // Create end point string endpointurl = string.Format("net.tcp://{0}:{1}/wcfChat", hostName, 9003); host.AddServiceEndpoint(typeof(IwcfChat), new NetTcpBinding(SecurityMode.None), endpointurl, new Uri(endpointurl)); // Open the host host.Open(); // Trace output Trace.WriteLine("WCF Listening At: " + endpointurl); Trace.WriteLine("WCF MetaData Listening At: " + mexendpointurl); return base.OnStart(); } 

Here I showed the methods of the string type, but the type of the return value can be absolutely any, for example, a complex class, which is described in my common library. Everything, I have no other settings in web configuration, no packages in xml or SOAP. There are no automatically generated contract files. When I tried to do this, when searching for information about wcf on the Internet, the setting under http always pops up with all these packages / unpackings. Yes, wcf technology was originally invented to connect heterogeneous systems where it is necessary to serialize and transmit as a string. But if we have one programming language, and the client and wcf server are all our development, then there is no need to make a garden, everything works fine.

Thus, I have a distributed server, for costly operations I do a separate worker, for example, chat is shown here. All chat functions are moved to a separate virtual machine, and I can increase the performance of both the site (web role) and the chat itself.

This architecture seems to me correct and can withstand a stronger load than a monolithic project. All this is also being developed and debugged as one project in the studio, that is, when I call the wcf method, I can go deeper into the code in debugging, without messages like “I cannot debug inside, I don’t know what’s happening there, this is the result” .

With Azurov tools it is done easily and simply, I run the entire project with one button and debug it using it as a single project. I remember once a long time ago, on one of the projects there was a similar architecture, but I was young, and it was very difficult for me there: some facades, and if the parameters of the method changed, I made changes in four places.

I need to do something similar on regular servers. Not on their physical servers, but on vds / vps virtuals from some necessarily Russian hoster. I found a fun technology from one of the hosters ( 1gb.ru ), called Windows Azure Pack / COSN resource . According to the description, this is a shortened version of Azura and everything would have to "fly up." Of course, they have a trial period, I looked. In the browser, the control is as if from the old version of the Azura portal (if anyone remembers).
image
Of the possibilities there is only the creation of virtual machines, their integration into the network (manually), there is a service bus - that's all. It is also not possible to download this subscription in the studio, and this is a lot of convenience. Plus there is no possibility of creating a cloud service. The description says that this “private cloud” will be refined and complemented by features from the original Azura, but support said that everything has long been frozen, and in general, these are incompatible technologies (“this Azure Pack is completely incompatible with this Azure. There that is, that is, and there is not enough. There are common ideas, but the implementation is completely different, the API is different, and so on. "(c)).
In short - it does not fit.

Looking further. I run over screw hosts, looking for the possibility of renting regular vps / vds but with the ability to organize a local network between them. Many simply do not have such an opportunity. Yes, you can rent a virtual machine, pick up on it a VPN and another virtual machine to hook on to this network. But such a “local” network stretches over http, which is why it is obviously slower. I already thought that I would not succeed, but at the 1cloud hoster I see what I’m looking for: “Just in a couple of clicks, connect your virtual machines to a private network for free with 1 Gbit / s bandwidth.” in Moscow. Support says that local networks with a bandwidth of 10 Gbit / s are deployed on the Moscow infrastructure.

Great, we’ll try to do the same as above, just for regular hosting.

In the studio, we create a solution, I called it sharedTest, to which we add:
1. MVC application with the same name.
2. The windows class library, I just called Lib
3. Console application windows, I called it worker
image

Next, you need to tie these projects together, for this we right-click on our solution and go to the properties
image
Here it is necessary to select the item in the project being launched, that I have several ones being launched and my Worker to raise higher than the site.
Immediately following property - the dependence of projects. The library does not depend on anyone. The sharedTest site depends on both the library and the worker. A worker only depends on the library.

Do not forget in the properties of the worker (also with the right button and properties) specify the object to be launched, so that the worker will start first and wait for no one.
image

The next step is adding dependencies. In the Lib library, right-click links (Reference) -> add a link ... and we will need the System.ServiceModel package. We need the same package in the worker. In the same way in the website and the worker we add a link to our library from the Lib project.

The library is placed (conveniently with separate files) public interface IwcfChat and public sealed class wcfChat: IDisposable (my first listing is at the top). Also there is a directory with general settings or structures, there I only have an ip address (from where I got it will be a little later).

  public static class spr { public static string wcfIP = "10.0.0.6"; } 


Let's make our worker a service host (similar to the top listing, just transferred to the Main function, since I have a console application)
 class Program { static void Main(string[] args) { //      ServicePointManager.DefaultConnectionLimit = 12; // Create the host ServiceHost host = new ServiceHost(typeof(wcfChat)); // Read config parameters #if (DEBUG) string hostName = "127.255.0.1"; #else string hostName = spr.wcfIP; #endif // Create Metadata ServiceMetadataBehavior metadatabehavior = new ServiceMetadataBehavior(); host.Description.Behaviors.Add(metadatabehavior); Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding(); string mexendpointurl = string.Format("net.tcp://{0}:{1}/wcfChatMetadata", hostName, 8003); host.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, mexendpointurl, new Uri(mexendpointurl)); // Create end point string endpointurl = string.Format("net.tcp://{0}:{1}/wcfChat", hostName, 9003); host.AddServiceEndpoint(typeof(IwcfChat), new NetTcpBinding(SecurityMode.None), endpointurl, new Uri(endpointurl)); // Open the host host.Open(); Console.WriteLine("Host opened on "+hostName); Console.ReadLine(); } } 


Ports 8003 and 9003 I took from my head, as long as they were not standard and were not busy.

We add wcfChat class to the worker - implementation of our interface
 using Lib; namespace Worker { class wcfChat : IwcfChat { public string SendMessage(string userId, string userName, string text) { return "Sending message...."; } public string GetMessages(string userId, string userName) { return "Get messages"; } } } 


There was nothing to paint here, but the values ​​come. It's time to try - we modify our Home controller and its presentation.
  public ActionResult Index(bool isGet = true) { string res = ""; using (var chat = new wcfChat()) { res = isGet ? chat.channel.GetMessages("1", "name") : chat.channel.SendMessage("1", "name", "text"); } return View((object)res); } 

 @model string @{ ViewBag.Title = "Home Page"; } <br /><br /> <div>@Model</div> 


We start and see that everything works:
image

Great, it remains quite a bit - put the project at the host, I remind you, I work with 1cloud . We register, through the control panel we create two virtual machines of the configuration we need (I took the minimum ones in the Petersburg data center, but this doesn’t matter). They have a test period of several hours, support extended to me upon request, and in general well done, they go forward.
image

Next, create a local network, also a couple of clicks, the second item from the control panel, I called it testLocal. By the way, I turned off the dynamic IPs checkbox (DHCP), since my service depends on a static IP address, because of this I will have to tinker a bit more.
image

After creation, everything is still in the control panel, we go to each server, go to the Settings tab, find the Private networks and check the box that we use the newly created network. This flag will add us a new adapter and a new network inside the virtual machine. In the same place, we get an internal IP address, I had it 10.0.0.5 and 10.0.0.6 for the site and the worker. In order for the network to work, we climb over the remote desktop (RDP) to our virtual machines and manually drive these values ​​into the network settings. Instructions for those who do not understand, are there next .

I want to warn you that it did not work right away. I indicated the networks as publicly available, so I had to redo them into private ones like this . And you also need to add my used ports to the firewall exceptions. For this, I called the launch of the Win + R key and typed netsh.exe there
after which the command line typed command
 firewall set portopening protocol = TCP port = 9003 name = myService mode = ENABLE scope = SUBNET profile = CURRENT 


Now I will tell about the publication. I configured IIS for this manual . You can check the performance from the browser by external IP address. Picture from IIS tells us that everything works.
image

I did not do anything with ftp, nor, especially, with setting up publishing from a version control system, this is a topic for another article. I corrected the aypishnik to the issued one, published my web application to the file system and threw my daddy C: \ inetpub \ wwwroot on the server into pens. I updated the page and saw the expected error at Home / Index, as there was no service yet.

Actually, I also published my worker to the file system, the installer turned out. Here the only thing you need to not get confused with DEBUG / RELEASE. I dragged the whole daddy to the desktop of the second virtual machine, installed it with the left mouse button and started it. My black window came out, which said that the service was working. We update the site, we see that everything was successful.

image

So I got a workable distributed server. I gave the chat as an example, although in the comments they say that you need to beat your hands for it) In general, I use this technology in a browser game, where the functions for calculating the duel are placed on a separate server. One of the advantages is that I can improve the performance of only one specific server, if I need to. In the same way, you can do it for two websites, for example, the first server will process the photos, and the second server on the subdomain will be used to store the images (the image will be sent once, and the second will only display).
Naturally, the implementation is not perfect, it is only a frame point. It is necessary to set up a correct and convenient publication. In addition, there is a hard link 1 to 1, and if you need several workers, you will need a load balancer. Also, in a good way, you need to get rid of static internal aypishnikov. Well, in general, for speed, you will need to replace the wcf connection with the implementation directly via tcp sockets.

Source: https://habr.com/ru/post/305696/


All Articles