Git Product home page Git Product logo

Comments (12)

dsyer avatar dsyer commented on May 22, 2024

In theory the user just has to provide a @Bean of type EurekaInstanceConfig (e.g. the default implementation). Someone just needs to verify that.

from spring-cloud-netflix.

wgorder avatar wgorder commented on May 22, 2024

I have not even got this far. I am just trying to deploy a spring-cloud eureka (inside a docker container) to AWS. If I create a @bean of type EurekaInstanceConfig it blows up because there is an @Autowired dependency in EurekaDiscoveryClientConfiguration.java specifically typed to spring clouds EurekaInstanceConfigBean type

from spring-cloud-netflix.

wgorder avatar wgorder commented on May 22, 2024

Well my case is a little unique since I am also playing with their docker support in AWS beanstalk and I wanted to get the public hostname and local ip from inside the docker container. This bean seems to be working for me, although I am not done playing yet.
I also created a 'local' profile to disable all the AWS stuff when I am running locally. For them they would have read that out of their Eureka properties file. If we were going to fix this up it should probably be yet another property you can set to bypass under the eureka.instance properties.

@ConfigurationProperties("eureka.instance")
public class EurekaInstanceConfig extends EurekaInstanceConfigBean {
    private static final Logger logger = LoggerFactory.getLogger(EurekaInstanceConfig.class);
    protected String namespace = "eureka.";

    private boolean propValidateInstanceId;
    private DataCenterInfo info;

    public EurekaInstanceConfig(Environment environment){
        this.propValidateInstanceId = environment.acceptsProfiles("development");
        logger.debug("Validating Instance Id active profiles are: {}", new Object[] {environment.getActiveProfiles()});
        this.info = initDataCenterInfo();
    }

    private DataCenterInfo initDataCenterInfo() {
        DataCenterInfo info;
        try {
            info = AmazonInfo.Builder.newBuilder().autoBuild(namespace);
            logger.info("Datacenter is: " + DataCenterInfo.Name.Amazon);
        } catch (Throwable e) {
            logger.error("Cannot initialize amazon info :", e);
            throw new RuntimeException(e);
        }
        // Instance id being null means we could not get the amazon metadata
        AmazonInfo amazonInfo = (AmazonInfo) info;
        if (amazonInfo.get(AmazonInfo.MetaDataKey.instanceId) == null) {
            if (propValidateInstanceId) {
                throw new RuntimeException(
                        "Your datacenter is defined as cloud but we are not able to get the amazon metadata to "
                                + "register. \nSet the property " + namespace + "validateInstanceId to false to ignore the"
                                + "metadata call");
            } else {
                // The property to not validate instance ids may be set for
                // development and in that scenario, populate instance id
                // and public hostname with the hostname of the machine
                Map<String, String> metadataMap = new HashMap<String, String>();
                metadataMap.put(AmazonInfo.MetaDataKey.instanceId.getName(),
                        super.getIpAddress());
                metadataMap.put(AmazonInfo.MetaDataKey.publicHostname.getName(),
                        super.getHostName(false));
                amazonInfo.setMetadata(metadataMap);
            }
        } else if ((amazonInfo.get(AmazonInfo.MetaDataKey.publicHostname) == null)
                && (amazonInfo.get(AmazonInfo.MetaDataKey.localIpv4) != null)) {
            // This might be a case of VPC where the instance id is not null, but
            // public hostname might be null
            amazonInfo.getMetadata().put(AmazonInfo.MetaDataKey.publicHostname.getName(),
                    (amazonInfo.get(AmazonInfo.MetaDataKey.localIpv4)));
        }
        return info;
    }

    /*
     * (non-Javadoc)
     * @see com.netflix.appinfo.AbstractInstanceConfig#getHostName()
     */
    @Override
    public String getHostName(boolean refresh) {
        return ((AmazonInfo) info).get(AmazonInfo.MetaDataKey.publicHostname);
    }

    @Override
    public String getIpAddress() {
        String publicIp = ((AmazonInfo) info).get(AmazonInfo.MetaDataKey.publicIpv4);
        return  publicIp== null ? 
                ((AmazonInfo) info).get(AmazonInfo.MetaDataKey.localIpv4) : publicIp;
    }

    @Override
    public DataCenterInfo getDataCenterInfo() {
        return this.info;
    }
}

from spring-cloud-netflix.

rozhok avatar rozhok commented on May 22, 2024

@wgorder I have same case: dockerized Eureka service deployed on Beanstalk and a few microservices.
Did you solve the problem that services register themselves using internal IP and not accessible from outside?

from spring-cloud-netflix.

dsyer avatar dsyer commented on May 22, 2024

@rozhok can't you just set the eureka instance metadata up in configuration (per docs here: http://projects.spring.io/spring-cloud/docs/1.0.3/spring-cloud.html#_eureka_metadata_for_instances_and_clients)? That's what I do.

from spring-cloud-netflix.

wgorder avatar wgorder commented on May 22, 2024

@rozhok I am not sure if anything is changed since I was messing around with it. The wall I hit was that rather than the config being an interface as being discussed here:

#302

It is a class. So I ended up having to extend their bean so things that had a hard dependency on that class didn't blow up. The class looked like below, not super generic or anything but I basically replaced the spring cloud stuff with the standard out of the box eureka stuff that Netflix had that works well on AWS. The spring cloud abstraction is more suitable for CF at least at the time I was messing around with it. It seemed to break the existing AWS support you got from vanilla Eureka.

/**
 * Override the Spring Cloud configuration properties to work properly not only inside of AWS but also so we can
 * accurately determine the hostname and IP from within the docker container.
 *
 * @since 2/8/15
 */
@ConfigurationProperties("eureka.instance")
public class EurekaInstanceConfig extends EurekaInstanceConfigBean {
    private static final Logger logger = LoggerFactory.getLogger(EurekaInstanceConfig.class);
    protected String namespace = "eureka.";
    private DataCenterInfo info;

    public EurekaInstanceConfig(){
        this.info = initDataCenterInfo();
    }

    private DataCenterInfo initDataCenterInfo() {
        DataCenterInfo info;
        try {
            info = AmazonInfo.Builder.newBuilder().autoBuild(namespace);
            logger.info("Datacenter is: " + DataCenterInfo.Name.Amazon);
        } catch (Throwable e) {
            logger.error("Cannot initialize amazon info :", e);
            throw new RuntimeException(e);
        }
        // Instance id being null means we could not get the amazon metadata
        AmazonInfo amazonInfo = (AmazonInfo) info;
        if (amazonInfo.get(AmazonInfo.MetaDataKey.instanceId) == null) {
            throw new RuntimeException(
                    "Your datacenter is defined as cloud but we are not able to get the amazon metadata to "
                            + "register. \nSet the property " + namespace + "validateInstanceId to false to ignore the"
                            + "metadata call");

        } else if ((amazonInfo.get(AmazonInfo.MetaDataKey.publicHostname) == null)
                && (amazonInfo.get(AmazonInfo.MetaDataKey.localIpv4) != null)) {
            // This might be a case of VPC where the instance id is not null, but
            // public hostname might be null
            amazonInfo.getMetadata().put(AmazonInfo.MetaDataKey.publicHostname.getName(),
                    (amazonInfo.get(AmazonInfo.MetaDataKey.localIpv4)));
        }
        return info;
    }

    /*
     * (non-Javadoc)
     * @see com.netflix.appinfo.AbstractInstanceConfig#getHostName()
     */
    @Override
    public String getHostName(boolean refresh) {
        return ((AmazonInfo) info).get(AmazonInfo.MetaDataKey.publicHostname);
    }

    @Override
    public String getIpAddress() {
        String publicIp = ((AmazonInfo) info).get(AmazonInfo.MetaDataKey.publicIpv4);
        return  publicIp== null ?
                ((AmazonInfo) info).get(AmazonInfo.MetaDataKey.localIpv4) : publicIp;
    }

    @Override
    public DataCenterInfo getDataCenterInfo() {
        return this.info;
    }
}

Just bean that guy up to use it

 @Bean
  @Profile({"development", "production"})
  public EurekaInstanceConfig eurekaInstanceConfig() {
    return new EurekaInstanceConfig();
  }

from spring-cloud-netflix.

rozhok avatar rozhok commented on May 22, 2024

@dsyer Setting metadata simply doesn't work in Elastic Beanstalk with Docker because Docker runs with his own IP and tries to expose it into service registry. The problem explained more detailed there: http://stackoverflow.com/questions/29971909/use-eureka-despite-having-random-external-port-of-docker-containers and here http://stackoverflow.com/questions/31165181/how-to-set-up-connection-between-docker-containers-using-aws-beanstalk
@wgorder thank you, I'll try this.

from spring-cloud-netflix.

dsyer avatar dsyer commented on May 22, 2024

I guess I never tried it in Elastic Beanstalk so I don't know the detail, but other dockerised PaaS solutions I have used give you an environment variable containing the host IP address. E.g. this is how I did it for lattice: https://github.com/spring-cloud-samples/configserver/blob/master/src/main/resources/application.yml#L50 (via a config server override, but you could do the same thing in each app).

from spring-cloud-netflix.

rozhok avatar rozhok commented on May 22, 2024

@dsyer this stuff not working in beanstalk because

  1. Beanstalk just runs container without possibility to specify command-line options, so I cannot dynamically generate env variables
  2. There is 4 network interfaces in one single instance - containers own, containers bridge, hosts bridge and hosts own.
  3. There is always nginx which acts as reverse proxy for docker so it adds another level of complexity
  4. There is no standard env variables in AWS as in CF

However, seems that @wgorder's example works fine.

from spring-cloud-netflix.

wgorder avatar wgorder commented on May 22, 2024

Yes it works fine on CF and Lattice not on AWS. This includes Beanstalk and their newer ECS service. ECS gives you more control over docker inputs so it maybe could have been made to work but it was easier for me to use the solution above then to hack around, when I was playing with ECS.

I have been more focused on CF and Lattice at work so I have not been playing with AWS as much lately, so I have not tried with the most recent releases.

from spring-cloud-netflix.

spencergibb avatar spencergibb commented on May 22, 2024

@wgorder we have made changes and you should be able to provide a @Bean of CloudEurekaInstanceConfig, does that work?

from spring-cloud-netflix.

wgorder avatar wgorder commented on May 22, 2024

@spencergibb I don't have the environment set up anymore to test this atm. However I reviewed your changes and they look like they should fix the issue. I think it is safe to close this.

Thanks,

from spring-cloud-netflix.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.