we've setup a consul cluster with a couple of services on, and that's working fine. My question is what is the best way to discover the service in my winforms app.
I can connect to the cluster fine using one of the clusters IP address, and see the services, but my question is what is the best way to actually connect to the cluster to discover the services?
Its seems a bit naff to have to specify an IP of one of the servers in the cluster, what if that server is down?
I guess we could maybe use a DNS round-robin address, or loop over pre-defined servers but again that doesn't seem amazing.
How are other people doing this?
Thanks
Usually, some kind of Load Balancer is used to access the cluster with single IP-address and port. For example, HAProxy. In that case, balancer cares of your request to reach active server instance and the only address you need is balancer's address. But for sure, in most cases, this will need some extra resources.
Related
There's a similar question ( Can I temporarily override DNS resolution within a .NET application? ) but I just can't figure it out with the meager response there.
Background info
I have a server set up in my home network, an old computer. Our router has the right ports forwarded, the server runs server software for things like http, svn, games, etc. I've got a domain name registered that always points to our external IP address. For all intents and purposes, I've got a typical webserver set up. My friends can game on my server by connecting via the domain name, I can push and pull svn projects, etc.
The only problem is that I also need to use my server when I'm connected to my home network (the same network as the server). Using the domain name results in Windows resolving it to our own IP address, and my router is too retarded to realize it just needs to forward it back into our network to the server as per the usual. I've done some looking around, configuring, telnetting and DNS overriding, but I have it on good authority that our ISP apparently crippled the DNS override feature of their routers to prevent this exact scenario. Apparently they don't like internal loopbacks.
I now basically have to keep 2 configs for each of my server's services: one config that specifies the domain name for when I'm abroad, and a second that specifies the server's internal IP for when I'm at home. It's frustrating because it just isn't always possible.
I want to instantiate a global DNS resolution request/response listener that will do the following: if the requested domain name matches a given string, override the IP in the response with one of my choice.
I've looked things up like easyhook, dllimport, msdn pages, etc, but I still can't figure out where to actually start, which classes I need to get access to, and so on. I basically have no pre-existing code for this particular problem.
I have Visual Studio, years of relatively simple programming experience and a good understanding of unfamiliar code and everything else, just no idea how to start or what to look for.
Many thanks for anything that can get me going.
Couple of pointers, DNS is as you mentioned some server somewhere that knows how to resolve a Domain name to an IP ADDRESS. There are two types of responses 1) Definitive for the domain and 2) Not Definitive for the Domain. Obviously any Definitive response will win.
DNS does not run at TCP/IP layer it runs one layer below using UDP (port 53). As a result DNS is tied into the TCP/IP stack whereby the stack first looks locally to a local host table and sees is the name is there, if it cannot find it the stack will send out the DNS request prior to the session start or SYN packet flying. In order for this to happen, the DNS servers must resolve the address.
I do not fully understand your issue because most Windows servers only have 1 IP Address and one associated Domain name. Unless of course they are using DHCP which just means the server uses multiple address on boot up and DNS server receive updates to what those new address are.
Public vs. Private IP addresses are the responsibility of a router. The router is configured to do NAT (Network Address Translation). This allows a private server to have unroutable addresses like 10.10.1.100 etc. But the router will answer ARPs for the public address making the public network think the router is the public address. So one of your solutions could be to convert your server to a private address and use a "real" router that can perform NAT. Port forwarding is not really routing rather it's a way to "trick" packets destined for one port number to be forwarded to another port dedicated for that application.
My suggestion is to either follow the suggestions above or add the Domain names you want to the local Host table on the server. This will get you what you want. A better solution is to configure your own server to be a DNS server definitive for your domain, that way you get to control everything.
I ended up solving this with (as a few have suggested) the hosts file after all.
I first used ManagedWifi to set a network connection monitor. It detects changes to my connection status and reports the network name.
Then I wrote a console app that stays open (using Hidden Start allows me to hide the window) and safely modifies the hosts file, then flushes the DNS cache. This seems to work in pretty much realtime. :)
I have created a WCF service called MyAppService.
Now, I don't want to host that service on any servers. I would like to host it in my Computer. I know how to host a WCF service in Console/Windows App, as a Windows Service and in IIS.
But I have a problem to host this service in my computer. I mean in short that I want my Computer to Work as server and other computers should be able to consume myAppService from my computer via internet.
So, I would like to ask what is the best hosting option for me and how should I host my service such that other computers can consume myAppService using Internet. 1 more question : If the above problem is solved, then can I use netTcpBinding or I have to use some HttpBinding?
I'm still not 100% certain that I am answering the right question, but I'll give it a shot.
I believe what you are asking is: given that you are hosting a service in IIS on your personal computer, how do you allow others access to it? If my interpretation is incorrect, then please accept my apology in advance.
Note: I'm assuming IPv4 in this answer. IPv6 may be an option, but this answer would not apply.
There are two steps in the solution, and there are a few obstacles that you may or may not be able to overcome.
Get the client's web traffic to your public IP address.
Route incoming traffic to your computer.
Step 1
You can determine your public IP address in many ways, one of which is to ask Google: https://www.google.com/#q=what+is+my+ip
Obstacles are as follows:
Your IP address may change from time to time. The solution is to use a dynamic DNS service such as http://dyn.com/dns/, http://www.thatip.com/, or any of several alternatives that can be found online. These services will provide a URL that routes to your public IP, and they will provide a way to keep your public IP up-to-date so that name resoslution generally works. Keep in mind that DNS does not reliably change in realtime, however, so you should expect some downtime if and when your IP address changes.
Your ISP may block incoming traffic. Whether and how you can get around this is specific to your IP. Specifically, it is common for ISPs to block incoming port 20, 22, 23, 25, 80, and 443. You may be able to work around port blocking by choosing a non-standard port for your service. (This may not affect your WCF and IIS configuration as detailed in step 2.)
Particularly if you are using any kind of shared apartment connection, you may find that you do not have your own public IP address. If that is the case, then there is nothing you can do. If your router's WAN address (or computer's IP addres, if you're not using a router) is something in the 192.168.* or 10.* ranges, then it's time to look into server options.
Step 2
Once a client request has routed through the public internet to your public IP address, it needs to be routed to your computer.
The easiest, though least common these days, scenario is if your computer is directly connected to your cable/DSL modem. In this case, traffic that routes to your public IP is handled by your computer. This is the scenario where your WCF and IIS configuration needs to be listening on the actual port used by the client. For example, if your ISP is blocking port 80, then maybe you could configure your service to listen on port 34323, and that is the port that the client needs to request in the service call.
The most common scenario is that you have a router attached to your cable/DSL modem. In this case, you need to get into the administration control panel on your router and forward a port. For example, if your computer is configured to listen to port 80 for incoming service requests, then you can forward a port (for example, 34323) to port 80 on your local machine. How to forward the port differs by router. You should be able to find it by poking around or by doing an internet search.
The obstacle here is that your local IP address may change. You can overcome this by setting it to a static address outside of your router's DHCP assignment range or by setting up a DHCP reservation within your router. Either way will work. I suggest searching the internet for setting up a static IP or poking around in your router administration settings for DHCP reservations.
If you get all of your settings correct, and if there are no obstacles outside of your control, then a client on the internet can access your WCF service.
Edit:
I missed talking about local Windows firewall concerns. I could go into that, but allow me to link to this how-to guide that covers it pretty well. (Remember, a WCF service is conceptually similar to a website from a hosting standpoint, so much of this applies.) http://www.pcstats.com/articleview.cfm?articleID=1774
That's it. It's a newbie question, probably. I'm almost giving up on TcpClient/Listener because of NAT and firewall issues. I wanted to know if theres an alternative. port 80 probably doesn't have to deal with any of these annoying things. I hope the answer is Yes.
What about the SignalR over WebScockets
Yes, you can implement WebSockets in a non-browser application, but it won't solve your problem.
When you try to open a server listening to websocket connections, you will run into the same problem you ran into when you created a normal socket connection: Personal firewall solutions will get in the way and not every router will forward the port you've chosen. Using the well-known port 80 won't help you here. It is quite uncommon for normal consumers to have a webserver running behind their NAT router, so by default no NAT router will forward the port unless specifically configured to do so.
A NAT router will generally prevent any hosts behind it to act as servers unless configured to allow it. When you want the users to not worry about their NAT configuration, both users must act as clients. The only way to do this is by having a central server all players connect to.
While hosting a server is still not free, it has become quite cheap due to cloud-based hosters who will rent you small, virtualized servers for very modest prices. The smallest instance from Amazon EC2 only costs you 2 cents per hour or $14.40 per month. Or you can build your own server from some spare-parts and host it on your own internet connection. When you don't have a static IP address you can use a dynamic nameserver service like no-ip or DynDNS.
Yes you can, but please don't.
I would suggest to change your architecture:
Use a server socket as a main point to handle clients. This server has to have a visible IP/port. In this case you may have clients behind nuts, and do not bother.
I need to write an application that acts as a proxy between a client and a service. All I want to do is read the data that is traveling in both directions from client to service and vice versa. In essence I want this proxy to be able to be just plugged in without the need to reconfigure port settings in either the client or the service. Is this possible? Is there any specific library I could use in the C# .Net framework that will help?
EDIT: The service is on a remote machine.
EDIT: Example: Lets assume that the client is communicating to the service via port 1234 and the service is communicating to the client via port 5678. I want the application to listen and read the data traveling through these ports without actually reconfiguring either the client or the service. Is that possible?
If you are to read/listen/capture the data then it does not need to be a proxy. I would recommend WinPcap library (http://www.winpcap.org/). Although it's a C/C++ library, I don't think it's hard for a C#/.NET application to make use of it.
If you wanna redirect the ongoing connection as soon as your proxy program is up, the short answer is hard, really hard and impossible. As far as I've known, once the connection between 2 ends is established, no way you can change it (unless you have access to the router and modify its NAT on the fly, like a load balancer...). If you just want to read & not to modify the traffic data, use WinPcap or any packet sniffer. Either of these solutions are quite expensive to implement in term of money and technical work :)
Because you didn't give us what you actual wanna do, I assume that you don't need that "much" complexity. Here a solution just in case you meet the following prerequisites:
The client connects to the service via a domain name, not an absolute IP and vice versa. This is important because we are going to change the DNS in the host file to "fake" the end-point servers to our proxy server address.
You have access rights (administrator) to the client machine & the service machine to make any change.
Then what you should do next is to:
Change the IP of the hostname of your service server on your client machine to the IP of the proxy server. This just changes the result of the OS DNS resolver. Do the reversing way for the service server.
Drop & re-establish connections between 2 client machine & service server. Now, each connection is properly "proxied" via your proxy server.
Ha, quite intricate but it works I think... Hoping someone has better solutions for this situation and I'm looking forward to hearing that.
Is there anyway to configure a WCF service with a failover endpoint if the primary endpoint dies? Kind of like being able to specify a failover server in a SQL cluster.
Specifically I am using the TCP/IP binding for speed, but on the rare occurrence that the machine is not available I would like to redirect traffic to the failover server. Not too bothered about losing messages. I'd just prefer not to write the code to handle re-routing.
You need to use a layer 4 load balancer in front of the two endpoints. Prob best to stick with a dedicated piece of hardware.
Without trying to sound too vague but I think Windows Network Load Balancing (NLB) should handle this for you.
Haven't done it yet with WCF but plan to have a local DNS entry pointing to our Network Load Balancing (NLB) virtual iP address which will direct all traffic to one of our servers hosting services within IIS. I have used NLB for this exact scenario in the past for web sites and see no reason why it will not work well with WCF.
The beauty of it is that you can take servers in and out of the virtual cluster at will and NLB takes care of all the ugly re-directing to an available node. It also comes with a great price tag: $FREE with your Windows Server license.
We've had good luck with BigIP as a solution, though it's not cheap or easy to set up.
One nice feature is it allows you to set up your SSL certificate (and backdoor to the CA) at the load balancer's common endpoint. Then you can use protocols to transfer the requests back to the WCF servers so the entire transmission is encrypted.