First time here, read through lots of info in the docs and some threads here.
Anycast is great for routing users to the ‘closest/best’ datacenter, but my need is to be able to send requests (HTTPS) to our Node app in a specific location.
Say, I have selected the regions ams, syd and lax.
I’d like Fly to fire up an instance in ams, as per the requests coming in to https://ams.myservice.com.
Can’t launch instance in ams? Do it in a nearby backup location (that’s fine).
Fly volumes may play a role here, but I’ve not been able to find anything that informs me how to send a request to a specific location (which may not be possible since you’re running an Anycasted network).
Right now, the only way to do what I think you want is to run three apps.
Autoscaling and load balancing are two different processes. We monitor metrics to scale instances when the soft limit thresholds are met. New instances get spread evenly across your regions. Requests are routed to the nearest instance that’s under its limits.
What kind of requests are you trying to route to specific regions? Are you trying to keep people “pinned” to one VM, or doing something like game matchmaking?
There are some headers you can use to send specific HTTP request to specific VMs. These might be useful if you’re making requests from JavaScript, but won’t help for links people click.
Three apps, that’s what I figured.
I guess the downside of this is that I need to set things up 3 times. Not a biggie, but setting up and managing one app would be a lot nicer.
At launch, the app will act as a microservice and only has the role of a helper to another service.
The requests to the app on Fly are not from browsers/JS, all from cURL (testing) or Fetch.
So, using request headers can work.
If you get a list of instance IDs with flyctl status, you can send a fly-force-instance-id: <id> header in your request. The caveat is that if the instance id doesn’t exist, or it’s maxed out, the request will fail.
Since this sounds like it’s for internal use, you can also just hit private IP addresses directly if you setup a wireguard peer. Something like:
curl http://ams.<app-name>.internal:8080
Will send a request to port 8080 on an AMS based instance (if you have one running).
Interesting.
I should have made clear earlier that the core service, to which the app on Fly is a helper, lives in Cloudflare.
Obviously, Cloudflare can’t send a request to the .internal.
And Cloudflare can’t use flyctl.
I’m assuming the answer is No, but asking anyway: can the app in each location have a static public IP?
An ugly solution (because, high latency) would be to have Cloudflare send the request to Fly and this is routed to the app in whatever Fly location and if that is not the target location, this location then acts as a proxy and sends a request to the correct target location using the private IP address.
High latency is is currently not an issue with the service, but Cloudflare US <=> Fly US <=> Fly AU is definitely not pretty and not future-proof.
Oh, I just realized we have a better answer for this as of a few weeks ago. Try setting fly-prefer-region: ams with a request, that should do the right thing.
We’re working on regional IPs but it’ll be a few months!
Probably the last question on this topic: is there a way to know from the response from which location the response was served?
My Node app will send out a response with some specific headers (e.g. cache-control) but I’d love for Fly to add a header to the response, e.g. x-fly-region: ams
There is a Fly-Region response header on all our responses that shows the edge region where the request was received.
If you want the region for your instance (might be different from the edge region), then you’ll want to add the header yourself from the environment variable FLY_REGION from inside your VM
In my code, I’m grabbing the runtime env var FLY_REGION per the The Fly Runtime Environment · Fly
and then putting that as the value in the x-cdnp-fly-region-node response header our app sends out.
curl -sv0 /dev/null 'https://nameless-sun-2664.fly.dev/'
The 404 is expected.
Note the x-cdnp-fly-region-nodeis empty, which means the Fly-Region was empty or triggered an error.
Also, the request header Fly-Region seems not present on requests coming into the app.
$fly ssh console
Error create ssh certificate: issue_certificate failed: no root key established
Yes, this is Node and using .getHeader on the incoming request results in TypeError: req.getHeader is not a function (to my surprise, can’t explain that) but on local the req.headers works fine, so this is not the issue.
I’ve re-deployed and now the catch returns a 400 response with in the body the error message. curl -sv 'https://nameless-sun-2664.fly.dev/' gives FLY_REGION is not defined