Heya everyone,
great to see a lot of people again and even new faces in Frankfurt today! As there was some interest in the deployment stuff, here are some semi-random notes from the train ride back to get you started.
TL;DR: Lots of code snippets and config
Used software
All can be installed for messing around through homebrew or downloaded as single binaries from their respective pages.
Initial launch consul / nomad
Nomad and consul can be run in dev mode locally:
$ consul agent -dev
$ nomad agent -dev
per default the web UI is available on port 8500 (consul) and 4646 (nomad)
Integrating consul in your WOApp
Then the code comes down to (roughly):
final Consul.Builder builder = Consul.builder().withHostAndPort(HostAndPort.fromParts("localhost", 8500));
final Consul consul = builder.build();
final ConsulAgent consulAgentClient = consul.agentClient();
final WOApplication application = WOApplication.application();
final String serviceID = "someUniqueValue"; // we use host + appname + port to build this
final ImmutableRegCheck ttlCheck = ImmutableRegCheck.builder()
.ttl("5s")
.deregisterCriticalServiceAfter("60s")
.build();
final Registration registration = ImmutableRegistration.builder()
.port(application.getPort())
.id(serviceID)
.address(application.getHost())
.name(application.name())
.addTags("WebObjectsApp", NSBundle.mainBundle().name())
.addChecks(ttlCheck)
.build();
consulAgentClient.register(registration);
consulAgentClient.pass(serviceID);
After this happened, you need to regularly "check in" with consul (see the ttlCheck.ttl() argument), otherwise the app will be declared down. After the deregister time (next line) it will completely be removed from the system (to not leave around too many zombie entries). You can check in by regularly calling (for example in a separate thread):
consulAgentClient.pass(serviceID);
You should then see your service popup in the service tab of consul ✅ (note that the web UI has a different look than in my presentation as my demo system still uses an older version).
Using consul-template to generate a traefik configuration and launching traefik
Consul-template is part of consul (in homebrew) and can be used to dynamically generate the configuration. An example could look like this (called traefik-ctmpl):
[entryPoints]
[entryPoints.http]
address = ":10080"
[entryPoints.traefik]
address = ":10081"
[api]
entryPoint = "traefik"
dashboard = true
debug = true
[file]
[backends]
{{range services}}{{if .Tags | contains "WebObjectsApp" }}
[backends.wobackend-{{.Name}}]
[backends.wobackend-{{.Name}}.loadBalancer]
method = "drr"
[backends.wobackend-{{.Name}}.buffering]
maxRequestBodyBytes = 10485760
memRequestBodyBytes = 2097152
maxResponseBodyBytes = 10485760
memResponseBodyBytes = 2097152
retryExpression = "IsNetworkError() && Attempts() <= 2"
{{range service .Name}}
[backends.wobackend-{{.Name}}.servers.{{.Node | replaceAll "." "-"}}-{{.Port}}]
url = ""
weight = 10
{{end}}{{end}}{{end}}
[frontends]
{{range services}}{{if .Tags | contains "WebObjectsApp" }}
[frontends.wofrontend-{{.Name}}]
backend = "wobackend-{{.Name}}"
passHostHeader = true
[frontends.wofrontend-{{.Name}}.routes.route-woa]
rule = "PathPrefix: /cgi-bin/WebObjects/{{.Name}}.woa/"
{{end}}{{end}}
This will configure the traefik http traffic on port 10080 and service UI an 10081. There is also some basic configuration to forward headers to the application, have large request / response buffers and a 3-try retry mechanism. You now run consul-template and traefik from the resulting configuration.
$ consul-template -template traefik-ctmpl:traefik.toml # continuously generate traefik.toml using traefik-ctmpl
$ traefik -accesslog
Congratulations
Integrating your WOApp into Nomad
For this you'll need the 2020 WO-Day-Ference access pass ;-) At least currently we haven't finished this part but you can follow the guide at
https://www.nomadproject.io/intro/getting-started/jobs.html to get a basic idea how to schedule and run your applications in Nomad. All that is really required for WOApps, is some additional glue, to get the current hostname, extract the port from the consul-provided
server.port java property and feed it into the correct WO* parameters (in addition to other required / desired parameters for logging and running in the proper standalone mode).
If you made it here, these notes hopefully are of some interest to you and maybe even helpful. Feel free to continue here on the mailing list or contact me for any further questions!
Greetings
Dennis
PS: It seems that session stickiness currently unfortunately is only supported through cookies, as otherwise traefik and the application would need a somewhat (same) deeper understanding of the URL scheme to properly generate content and links or traefik would have to inspect the content deeper.
--
-----------------------------------------------------
Dennis Bliefernicht • Head of Backend Development
T +49 40 357 3001 62
XYRALITY GmbH • Friedensallee 290 • 22763 Hamburg
Registergericht: Hamburg HRB 115332
Geschäftsführer: Sven Ossenbrüggen
-----------------------------------------------------