Search code examples
network-programmingapache-nifi

nifi can't assign requested address


I'm using apache-nifi, and it seems that I'm unable to bind to an address when starting the web server unless in the config file I use the public DNS name. Using the IP address that the DNS name resolves to does not work. Likewise using a host alias assigned in /etc/hosts does not work. In each of those cases, I see in the nifi log an exception thrown by jetty, saying that it cannot assign the requested address.

There is nothing listening on the port already, as verified with netstat and by the fact that when I use the DNS name, there is no error binding to the address. Is this by design, or am I doing something wrong?

Here are the details of my config. (I'm actually running a nifi cluster, and the embedded zookeeper also fails to bind on the IP address or host alias but works on the DNS name. Since the failure occurs if I use a single nifi node with clustering off, I'm just showing the nifi server config.)

The nifi server is running on a VM in a cloud service with a public dns. Let's say the public DNS name is "dns-abc", and it resolves to address 1.2.3.4.

If I specify in nifi.properties nifi.web.http.host=1.2.3.4, the bind fails. If I specify nifi.web.http.host=dns-abc it succeeds. So then I created an entry in /etc/hosts as follows:

1.2.3.4    nifi-1

and I specified nifi.web.http.host=nifi-1 in nifi.properties, and again the bind failed.

EDIT: Here's the stack trace

2017-09-18 01:02:30,610 WARN [main] org.apache.nifi.web.server.JettyServer Failed to start web server... shutting down.
java.net.BindException: Cannot assign requested address
        at sun.nio.ch.Net.bind0(Native Method)
        at sun.nio.ch.Net.bind(Net.java:433)
        at sun.nio.ch.Net.bind(Net.java:425)
        at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
        at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
        at org.eclipse.jetty.server.ServerConnector.open(ServerConnector.java:298)
        at org.eclipse.jetty.server.AbstractNetworkConnector.doStart(AbstractNetworkConnector.java:80)
        at org.eclipse.jetty.server.ServerConnector.doStart(ServerConnector.java:236)
        at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
        at org.eclipse.jetty.server.Server.doStart(Server.java:431)
        at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
        at org.apache.nifi.web.server.JettyServer.start(JettyServer.java:705)
        at org.apache.nifi.NiFi.<init>(NiFi.java:160)
        at org.apache.nifi.NiFi.main(NiFi.java:267)

Solution

  • The VM running in the cloud resolves the public DNS name for itself to its local IP address, and servers outside the VM resolve the same name to the VM's public IP address. Since the config must specify a local IP address for the server to bind to, and other hosts in the cluster will use the same configured node name as the host address they need to connect to remotely, it only works with a DNS resolution that works like this.

    I modified /etc/hosts on each system to resolve its own name as its local IP address and the other hosts in the cluster as their public IP address. Then I was able to use the host names from /etc/hosts for all the zookeeper and nifi config files. This is what I was after, because the IP addresses change when the VM is re-started, and I only need to change them in a single place on each VM.