We need to set Eureka server URL at client application from startup code, but it seems there is no way how to do it.
We have a mechanism how to discover Eureka server on network by UDP multicast broadcasting. Server sends response back to the client with information about IP address and port where Eureka server is running. But we don't know how to set this URL in Eureka client application from code. It seems the only way how to set Eureka server URL is the property eureka.client.serviceUrl.defaultZone in application.property file.
// Server - start a new thread with UDP packet detection and reply mechanism
LocationService.listenAndReplyToEurekaClients(thisServerPort);
// Server - application start
SpringApplication.run(EurekaServerApplication.class, args);
// Client - send UDP packet and receive reply with Eureka server IP and port
Response response = LocationService.findEurekaServerAddress(5, 3, TimeUnit.SECONDS);
var hostProtocol = "http";
var eurekaUrl = new URL(
hostProtocol,
response.getEurekaAddress(),
response.getEurekaPort(),"").toString();
We would like to set this eurekaURL to the client before it starts registering to Eureka server.
In this case, we can do following things-
Extend EurekaClientConfigBean and override getEurekaServerServiceUrls method. Method returns a List of String which is nothing but list of all the URLS, of eureka instances. You need to set the URL here from your response which has IP and port.
Later create the discovery client using- DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config). (Its going to be a Bean for sure).
That should work.
You can create ApplicationInfoManager as-
ApplicationInfoManager applicationInfoManager =
initializeApplicationInfoManager(webAppInstanceConfig);
Where WebAppInstanceConfig is-
class WebAppInstanceConfig extends MyDataCenterInstanceConfig {// Override all the needed properties from MyDataCenterInstanceConfig}
Related
I'm developing a chat, and firstly I was using sockets and streams to communicate between the server and client, which I already tested with my friends and it worked. Now I`m trying to convert to RMI.
So, it is working locally, but when my friend tries to connect he gets a refused connection. Weirder is that it shows the server local ip (192.168.25.28).
My code looks like this:
public void conectar() throws RemoteException, MalformedURLException, NotBoundException{
// COMUNICADOR SERVIDOR (USADO PELO CLIENTE)
comunicadorServidor = new ComunicadorServidor(id); // cria um novo comunicador
LocateRegistry.createRegistry(8081); // inicia o registro RMI na porta 8081
Naming.rebind("//:8081/ComunicadorServidor", comunicadorServidor); // vincula o objeto comunicador ao endereço RMI
// COMUNICADOR CLIENTE (USADO PELO SERVIDOR)
comunicador = (IComunicadorCliente) Naming.lookup("//" + conexao.getInetAddress().getHostAddress() + ":8082/ComunicadorCliente"); // procura o comunicador no cliente
}
So I use RMI in both server and client, and one connect to each another, because in server I have methods like Authentication and Send Message, which the cliente uses, and in the client I have methods like Update Users List and Receive Message, which the server uses.
So first I create an instance of the RMI class (server-side), create a registry on port 8081, then bind the object to port 8081 with the name "ComunicadorServidor".
And after that the server tries to connect to the client RMI.
So I read about the rebind method, and if I don't specify an address, it will bind to the local host address, which I ask: even if it's binding to my local machine, is it still available outside? If not, how can I bind it in the same away as socket, where I just specify some port and it will be available to any address, like localhost, local ip, or external ip.
And about the lookup, what is the best way to get the client IP (right now I'm taking from the socket), how can I be sure that I will get a correct IP? Can I connect to the client RMI without a socket?
And in the client side it's essentialy the same thing, except it binds the RMI class to 8082 and lookup for the RMI class in server-side with the provided IP and port.
Weirder is that it shows the server local ip (192.168.25.28).
That's correct. If you need it to appear on a public IP address you need to look up java.rmi.server.hostname, and see Item A.1 in the RMI FAQ.
So I read about the rebind method, and if I don't specify an address, it will bind to the local host address, which I ask: even if it's binding to my local machine, is it still available outside?
The Registry is available to the outside world if the server-side firewall rules so permit. Note that bind in the RMI sense just means associating a remote object with a name in the Registry: it has nothing to do with Socket.bind().
And about the lookup, what is the best way to get the client IP (right now I'm taking from the socket), how can I be sure that I will get a correct IP? Can I connect to the client RMI without a socket?
You can't 'connect' in RMI at all, but you don't need the client's IP address. The client should register its remote object with the server via a server remote method, e.g. register(Client client) throws RemoteException. Then the server has a stub on which it can call client remote methods directly (client-side firewall permitting).
I'm transferring files using FTP with JAVA.
I'm using FTPClient and FTPServer from Apache. But in a specific environment, sometimes the file isn't transferred. I call the enterLocalPassiveMode method from FTPClient before the login method call and yet sometimes the files aren't transferred.
The storeFile method returns "false".
The getReplyString method returns "200 Command TYPE okay".
The list method returns "227".
When the file is transferred successfully:
The list method returns 150.
The getReplyString method returns "150 File status okay; about to open data connection".
Client code:
this.getFtpClientUtil().connect(settingsService.getServer(), settingsService.getFtpServerCommandChannelPort());
int reply = this.getFtpClientUtil().getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
logger.error("Fail to connect to FTP Server");
this.getFtpClientUtil().disconnect();
isConnect = false;
return false;
}
logger.info("FTP Server connected successfully");
this.getFtpClientUtil().enterLocalPassiveMode();
isConnect = this.getFtpClientUtil().login(settingsService.getftpUsername(), settingsService.getftpPassword());
Server Code:
// Data Configuration
this.dataConfigurationFactory = new DataConnectionConfigurationFactory();
dataConfigurationFactory.setPassiveAddress(this.ipAddress);
dataConfigurationFactory.setPassiveExternalAddress(this.ipAddress);
dataConfigurationFactory.setPassivePorts(this.settingsService.getFtpServerTransferChannelPort());
// Listener
listenerFactory = new ListenerFactory();
listenerFactory.setPort(this.settingsService.getFtpServerCommandChannelPort());
listenerFactory.setDataConnectionConfiguration(dataConfigurationFactory.createDataConnectionConfiguration());
// Desliga SSL
listenerFactory.setImplicitSsl(false);
// User
PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory();
UserManager um = userManagerFactory.createUserManager();
this.serverFactory = new FtpServerFactory();
serverFactory.addListener("default", listenerFactory.createListener());
serverFactory.setUserManager(um);
UserFactory userFactory = new UserFactory();
userFactory.setName(this.settingsService.getftpUsername());
userFactory.setPassword(this.settingsService.getftpPassword());
userFactory.setMaxIdleTime(60);
final String absolutePath = this.settingsService.getftpHomeDirectory();
userFactory.setHomeDirectory(absolutePath);
userFactory.setAuthorities(Arrays.asList((Authority) new WritePermission()));
User user = userFactory.createUser();
um.save(user);
// Connection Config
connectionConfigFactory = new ConnectionConfigFactory();
connectionConfigFactory.setAnonymousLoginEnabled(false);
connectionConfigFactory.setMaxLogins(100);
serverFactory.setConnectionConfig(connectionConfigFactory.createConnectionConfig());
Is this a firewall problem?
I tried set passive port ranges on the server side using the setPassivePorts method from DataConnectionConfigurationFactory class, but the problem continues.
Is there any form to set port ranges on the Client side?
How can I check if the connection is really using passive mode?
Thanks in advance.
Is this a firewall problem?
In these cases, the correct way would be turn off the firewall to test or set a range of ports that the application can to connect. But in the production environment this wasn't an option. So, the only thing I know is that in the development environment works fine and in the production environment the problem arise. My assumption is that the firewall is blocking the ports.
Is there any form to set port ranges on the Client side? How can I check if the connection is really using passive mode?
The local port can be set on connect() method from FTPClient:
this.getFtpClientUtil().connect(settingsService.getServer(), settingsService.getFtpServerCommandChannelPort(),
InetAddress.getLocalHost(), getLocalPort());
It's possible to verify if the connection is using the passive mode in two ways:
The getPassivePort() method from FTPClient will return -1 if the passive mode isn't in use.
In the question, I mentioned that the list() method from FTPClient returns the 227 code. This code also indicates that the passive mode is in use. I thought that this code was an error. What really happened was an error after entering in passive mode, but was returned the code from previous command.
Setting local port didn't resolve the problem. Perhaps because the local port that I'm configuring is only for the command channel. The transfer channel still uses random ports on client side. The solution is trying to transfer the file again. If the transfer fails, I disconnect the client, then I connect the client again using other ports and then I try to transfer the file again. In all my tests, the files was transferred successfully in the second time. I put 3 attempts if the transferring fails.
When connecting the client again, if the same port was used, the java could throw "java.net.BindException: Address already in use". Even after disconnect the client, the port continues locked for a few moments. In this case, I verify if the port is available before trying to connect, if necessary I try to connect the client in another port.
How to find out where Paho Java client got actually connected to when it was called with list of severURIs.
I work on a client application where multiple equal brokers are used to achieve “High Availability” system. Paho is provided with list of all brokers to connect to:
MqttConnectOptions options = new MqttConnectOptions();
options.setServerURIs( new String[]{"tcp://broker1.com:1883",
"tcp://broker2.com:1883", "tcp://broker3.com:1883"} );
MqttClient mqttClient = new MqttClient("tcp://broker1.com:1883",
clientId, new MemoryPersistence());
mqttClient.connect(options);
After connect I would like to report where it has got actually connected to, but I do not know how.
MqttClient.getServerURI() returns URI provided in MqttClient constructor regardless it is connected to.
According to documentation:
When an attempt to connect is initiated the client will start with the
first serverURI in the list and work through the list until a
connection is established with a server. If a connection cannot be
made to any of the servers then the connect attempt fails.
I'm attempting to connect to a TCP socket in Android.
I know the socket service works because I can connect and interact with it in a browser (in JavaScript) as follows:
var ws = window.WebSocket || window.MozWebSocket;
window.ws = new wsImpl('ws://foo.bar.com:8282/MySocketService', 'my-protocol');
...
So, in my Android app:
This connects successfully, but I never receive messages from it:
SocketAddress sa = new InetSocketAddress("foo.bar.com", 8282);
This fails to connect:
SocketAddress sa = new InetSocketAddress("foo.bar.com/MySocketService", 8282);
and I receive an error like:
java.net.UnknownHostException: Host is unresolved: foo.bar.com/MySocketService:8282
Is there any way to indicate the application path for a TCP service?
TCP end-point is just IP address and a port number. What you are talking about is handled by upper-level protocols on top of TCP, like HTTP, so you need to look at other utilities like java.net.URL.
I'm using Netty with Java trying to configure a TCP client. Everything is working so far, except that I'm connecting on port 1050 but when I call messageEvent.getRemoteAddress() on messageReceived() method of the handler, I'm getting the port 1500. I changed the port to 1049 but I'm still receiving 1500. This is Netty's problem or can it be the server's problem?
My hardware setup here is: this netty client running on a Java server, and several access control equipments spread through the area here. The equipments act as tcp servers and the netty as the client, that process everything the server sends and just reply to them.
The tcp server initialization is this:
private ChannelFactory fabrica;
private ServerBootstrap bootstrap;
public void iniciarServidorTCP() {
fabrica = new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
bootstrap = new ServerBootstrap(fabrica);
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
#Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("decoderDeMensagem", new MensagemDecoderTCP());
pipeline.addLast("handlerGerente", new GerenteTCP());
pipeline.addLast("encoder de mensagem", new MensagemEncoderTCP());
return pipeline;
}
});
bootstrap.setOption("child.tcpNoDelay", true);
bootstrap.setOption("child.reuseAddress", true);
bootstrap.bind(new InetSocketAddress(1050));
}
Any idea why I'm getting 1500 instead of 1050? Could it be a problem with the equipment?
Every TCP connection has a source port and a destination port. When you connect to a server, the server sees the destination port as its well-known address. The client picks the source port. On either end, getting the "remote address" gets the other side's address. So when you call get remote address on the server, you get the client's address, not the server's.
Imagine you have a server with one IP address and one well-known port. Now, say you have a client machine with one IP address. If it make's four connections to the server, how can either end tell those connections apart? The answer is that the client port is different.