Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [ecf-dev] Problem with Service Endpoint matching when using different network names

Hi Peter,

On 6/21/2018 2:08 AM, Peter Hermsdorf wrote:

Hi,

I need to bring up a issue that was already discussed earlier, eg.

https://bugs.eclipse.org/bugs/show_bug.cgi?id=419744

and here

http://dev.eclipse.org/mhonarc/lists/ecf-dev/msg08047.html

The issue is, that in our setup, the service matching is not working when accessing the remote server using a different hostname than the machine uses itself (a little hard to express as non native speaker ;) see ENDPOINT definition below)


Scott's last comment on the problem was to get more information about our use case and environment so I'll try to provide the required information

* we have a lot of clients using remote services from one application server

* we use the ecf generic provider.

* the remote service "discovery" is done by generating an EndpointDescription on client side, as all clients know by configuration which server to speak to. We use something like this to define the service endpoint:

props.put(ENDPOINT_ID, "ecftcp://" + host + ":8889/server");

where host is the hostname or IP address under which the client can access the remote server - which is not necessarily the hostname or IP which is configured at the server itself (which is exactly the issue). So eg. the server is exporting the service under endpoint

ecftcp://myhostname.company.local:8889/server

whereas the client needs to access the server eg. by using

ecftcp://otherhostname.public.net:8889/server or by ecftcp://192.168.0.100:8889/server

as endpoint id.

and even case sensitivity does matter: Some Windows machines (for whatever reason) have hostnames like MYHOSTNAME.company.local. Clients then are required to use the exact hostname with the correct upper/lowercase to access the server.

* the remote services are imported on client side via

remoteServiceAdmin.importService(endpointDescription);

* the remote services are exported on server side using DS with additional properties, like:

@Component(immediate = true, property = {
        "service.exported.interfaces=*",
        "service.exported.configs=ecf.generic.server",
        "ecf.generic.server.port=8889" })
public class MyserviceService implements IMyService {

* on server side we have a custom implementation of IHostContainerSelector which allows us to override

protected IRemoteServiceContainer createRSContainer

to add a custom RegistrySharedObject which customizes error handling ("exception to String serialization")


That's it i think.

So getting rid of the hostname part in the endpoint description and/or  when matching would probably solve the problem...


Thanks for any hints on this issue!



Ok, thanks for the description of the issue.   For this use case:  i.e. hostname used by clients that are different from the bind address for the server...i.e. client wants to use:

otherhostname.public.net

and the server needs to expose/listen on this interface:

myhostname.company.local  (or rather the ip address if the interface for this name)

For the generic provider, here are the remote service configuration properties

https://wiki.eclipse.org/ECF_Generic_Provider_Configuration_Properties#Remote_Service_Configuration_Properties

For the *external* address/name these are the relevant properties:

ecf.generic.server.hostname = otherhostname.public.net
ecf.generic.server.port = 8889
ecf.generic.server.path = /server

for example, these values will result in an external name of:  ecftcp://otherhostname.public.net:8889/server.  For the generic provider the name of the container and the external name must match.

There is also a service property:

ecf.generic.server.bindAddress = InetAddress.getByName("myhostname.company.local")

or InetAddress.getByName("13.91.95.74")...with your actual IP.

The bindAddress property ultimately specifies the *address that is passed to this ServerSocket constructor to listen on for the ecftcp server:

new ServerSocket(port, backlog, bindAddress)

https://docs.oracle.com/javase/7/docs/api/java/net/ServerSocket.html#ServerSocket(int,%20int,%20java.net.InetAddress)

So I think the solution for your use case is to use all four of these service properties set appropriately...e.g.:

ecf.generic.server.hostname = otherhostname.public.net
ecf.generic.server.port = 8889
ecf.generic.server.path = /server
ecf.generic.server.bindAddress = InetAddress.getByName("myhostname.company.local")

Since I don't currently have access to a dual-homed server I haven't been able to test this fully, but really the only thing it does is to pass the bindAddress to the ServerSocket, rather than using the default ('0.0.0.0')...which is all interfaces.

I realize now that the use of the InetAddress instance in the service properties is a little clumsy...it would be better if it could also take a String...e.g.:

ecf.generic.server.bindAddress=myhostname.company.local

If the above works for you/your use case, I'll add this (support of String as well as InetAddress) in a new enhancement for 3.14.1.

BTW...since you are overriding the HostContainerSelector for another purpose, you could pass the bindAddress (and the other properties explicitly by overriding AbstractContainerSelector.createContainer, or AbstractContainerSelector.getContainerFactoryArguments.   Be a little careful with this, however, as these methods are responsible for doing the RSA-specified handling of service properties (e.g. the ecf.generic.server. prefix is stripped off before the hostname, port, path, bindAddress are passed to the container instantiator as per RSA).

Another way to accomplish the above would be to also use the RemoteServiceAdmin on the server-side (in addition to the import/client side).   i.e. you can explicitly export a service with:

RemoteServiceAdmin.exportService(ServiceReference,Map<String,?> overridingProperties);

The exportService is usually done by the BasicTopologyManager when a remote service is registered with a call to:

RemoteServiceAdmin.exportService(ref, null)

but you can do it yourself programmatically at any time after registration via the exportService.   Note the overridingProperties...that allows you to set any properties you want (e.g. your four and the required service.exported.interfaces) that will be used to configure the server container, but then it doesn't require any properties set via @Component.   This might be more convenient for you/your use case, since you may not want to have all of the properties and their values hard coded in the @Component metadata.   With exportService you can also do things like use config admin to config your exports rather than putting app-specific info in the @Component properties.

The more that I think about it, the less I think you should look to override the HostContainerSelector...and rather use RemoteServiceAdmin.exportService if you need/want to do things programmatically on the export side.  

Best regards,

Peter


BTW: the search function of the ecf-dev archive does not seem to work:

http://dev.eclipse.org/mhonarc/lists/ecf-dev/

click on search results in a 404


Thanks...this appears to be some sort of EF infrastructure problem...I've opened this bug:

https://bugs.eclipse.org/bugs/show_bug.cgi?id=536151

Scott





_______________________________________________
ecf-dev mailing list
ecf-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/ecf-dev



Back to the top