
org.refcodes.rest.ext.eureka.EurekaRegistrySidecar Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of refcodes-rest-ext-eureka Show documentation
Show all versions of refcodes-rest-ext-eureka Show documentation
Artifact for providing Spring Boot's Eureka microservice registry/
discovery support.
The newest version!
// /////////////////////////////////////////////////////////////////////////////
// REFCODES.ORG
// /////////////////////////////////////////////////////////////////////////////
// This code is copyright (c) by Siegfried Steiner, Munich, Germany, distributed
// on an "AS IS" BASIS WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, and licen-
// sed under the following (see "http://en.wikipedia.org/wiki/Multi-licensing")
// licenses:
// -----------------------------------------------------------------------------
// GNU General Public License, v3.0 ("http://www.gnu.org/licenses/gpl-3.0.html")
// -----------------------------------------------------------------------------
// Apache License, v2.0 ("http://www.apache.org/licenses/TEXT-2.0")
// -----------------------------------------------------------------------------
// Please contact the copyright holding author(s) of the software artifacts in
// question for licensing issues not being covered by the above listed licenses,
// also regarding commercial licensing models or regarding the compatibility
// with other open source licenses.
// /////////////////////////////////////////////////////////////////////////////
package org.refcodes.rest.ext.eureka;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.refcodes.component.InitializeException;
import org.refcodes.component.LifecycleStatus;
import org.refcodes.component.PauseException;
import org.refcodes.component.ResumeException;
import org.refcodes.component.StartException;
import org.refcodes.component.StopException;
import org.refcodes.data.Scheme;
import org.refcodes.exception.Trap;
import org.refcodes.net.IpAddress;
import org.refcodes.rest.AbstractHttpRegistrySidecar;
import org.refcodes.rest.HttpRegistrySidecar;
import org.refcodes.rest.HttpRestClient;
import org.refcodes.rest.HttpServerDescriptor;
import org.refcodes.rest.RestRequestBuilder;
import org.refcodes.rest.RestResponse;
import org.refcodes.rest.RestfulHttpClient;
import org.refcodes.runtime.Host;
import org.refcodes.security.TrustStoreDescriptor;
import org.refcodes.web.HttpResponseException;
import org.refcodes.web.HttpStatusException;
import org.refcodes.web.MediaType;
import org.refcodes.web.Url;
import org.refcodes.web.UrlBuilder;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.regions.internal.util.EC2MetadataUtils;
import software.amazon.awssdk.regions.internal.util.EC2MetadataUtils.NetworkInterface;
/**
* The {@link EurekaRegistrySidecar} provides you with a library for registering
* your web-services at Eureka service registry and discovery.
*/
public class EurekaRegistrySidecar extends AbstractHttpRegistrySidecar implements EurekaRegistry {
// /////////////////////////////////////////////////////////////////////////
// STATICS:
// /////////////////////////////////////////////////////////////////////////
private static final Logger LOGGER = Logger.getLogger( EurekaRegistrySidecar.class.getName() );
// /////////////////////////////////////////////////////////////////////////
// CONSTANTS:
// /////////////////////////////////////////////////////////////////////////
public static final String EUREKA_BASE_PATH = "/eureka/apps";
private static final String DEFAULT_PING_PATH = "/ping";
private static final String DEFAULT_HOME_PATH = "/home";
private static final String DEFAULT_STATUS_PATH = "/status";
// /////////////////////////////////////////////////////////////////////////
// VARIABLES:
// /////////////////////////////////////////////////////////////////////////
private ExecutorService _executorService;
private Timer _scheduler;
private EurekaDataCenterType _dataCenterType;
private String _statusPath;
private String _homePath;
private int _port = -1;
private Scheme _scheme = null;
private String _protocol = null;
// /////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS:
// /////////////////////////////////////////////////////////////////////////
/**
* Instantiates a new eureka registry sidecar.
*
* @param aExecutorService An executor service to be used when creating
* {@link Thread}s.
*/
public EurekaRegistrySidecar( ExecutorService aExecutorService ) {
_executorService = aExecutorService;
}
// /////////////////////////////////////////////////////////////////////////
// LIFECYCLE:
// /////////////////////////////////////////////////////////////////////////
/**
* {@inheritDoc}
*/
@Override
public synchronized void initialize( EurekaServerDescriptor aServerDescriptor, Url aRegistryUrl, TrustStoreDescriptor aStoreDescriptor ) throws InitializeException {
super.initialize();
aRegistryUrl = toHttpRegistryUrl( aRegistryUrl, this );
aStoreDescriptor = toTrustStoreDescriptor( aStoreDescriptor, this );
aServerDescriptor = toHttpServerDescriptor( aServerDescriptor, this );
try {
doRegister( EurekaServiceStatus.STARTING );
}
catch ( Exception e ) {
_lifeCycleAutomaton.setLifecycleStatus( LifecycleStatus.ERROR );
throw new InitializeException( "Cannot enter the initialize lifecycle!", e );
}
}
/**
* {@inheritDoc}
*/
@Override
public synchronized void start() throws StartException {
try {
super.start();
doStatusUpdate( EurekaServiceStatus.UP );
_scheduler = new Timer( true );
_scheduler.schedule( new HeartBeatDaemon( this, _executorService ), EurekaLoopSleepTime.REGISTRY_SERVICE_HEARBEAT.getTimeMillis(), EurekaLoopSleepTime.REGISTRY_SERVICE_HEARBEAT.getTimeMillis() );
}
catch ( Exception e ) {
_lifeCycleAutomaton.setLifecycleStatus( LifecycleStatus.ERROR );
throw new StartException( "Cannot enter the start lifecycle!", e );
}
}
/**
* {@inheritDoc}
*/
@Override
public synchronized void pause() throws PauseException {
super.pause();
try {
doStatusUpdate( EurekaServiceStatus.DOWN );
}
catch ( Exception e ) {
_lifeCycleAutomaton.setLifecycleStatus( LifecycleStatus.ERROR );
throw new PauseException( "Cannot enter the pause lifecycle!", e );
}
}
/**
* {@inheritDoc}
*/
@Override
public synchronized void resume() throws ResumeException {
super.resume();
try {
doStatusUpdate( EurekaServiceStatus.UP );
}
catch ( Exception e ) {
_lifeCycleAutomaton.setLifecycleStatus( LifecycleStatus.ERROR );
throw new ResumeException( "Cannot enter the resume lifecycle!", e );
}
}
/**
* {@inheritDoc}
*/
@Override
public synchronized void stop() throws StopException {
super.stop();
try {
_scheduler.cancel();
doStatusUpdate( EurekaServiceStatus.OUT_OF_SERVICE );
}
catch ( Exception e ) {
_lifeCycleAutomaton.setLifecycleStatus( LifecycleStatus.ERROR );
throw new StopException( "Cannot enter the stop lifecycle!", e );
}
}
/**
* {@inheritDoc}
*/
@Override
public synchronized void destroy() {
super.destroy();
try {
_scheduler.cancel();
doDeregister();
}
catch ( Exception e ) {
LOGGER.log( Level.WARNING, Trap.asMessage( e ), e );
_lifeCycleAutomaton.setLifecycleStatus( LifecycleStatus.ERROR );
}
}
// /////////////////////////////////////////////////////////////////////////
// METHODS:
// /////////////////////////////////////////////////////////////////////////
/**
* {@inheritDoc}
*/
@Override
public void setPort( int aPort ) {
_port = aPort;
}
/**
* {@inheritDoc}
*/
@Override
public int getPort() {
return _port;
}
/**
* {@inheritDoc}
*/
@Override
public String toProtocol() {
return _scheme != null ? _scheme.toProtocol() : _protocol;
}
/**
* {@inheritDoc}
*/
@Override
public void setProtocol( String aProtocol ) {
final Scheme theScheme = Scheme.fromProtocol( aProtocol );
if ( theScheme != null ) {
_scheme = theScheme;
_protocol = null;
}
else {
_protocol = aProtocol;
_scheme = null;
}
}
/**
* {@inheritDoc}
*/
@Override
public void setScheme( Scheme aScheme ) {
_scheme = aScheme;
_protocol = null;
}
/**
* {@inheritDoc}
*/
@Override
public Scheme getScheme() {
return _scheme;
}
/**
* {@inheritDoc}
*/
@Override
public String getHomePath() {
return _homePath;
}
/**
* {@inheritDoc}
*/
@Override
public void setHomePath( String aHomePath ) {
_homePath = aHomePath;
}
/**
* {@inheritDoc}
*/
@Override
public String getStatusPath() {
return _statusPath;
}
/**
* {@inheritDoc}
*/
@Override
public void setStatusPath( String aStatusPath ) {
_statusPath = aStatusPath;
}
/**
* {@inheritDoc}
*/
@Override
public EurekaDataCenterType getEurekaDataCenterType() {
return _dataCenterType;
}
/**
* {@inheritDoc}
*/
@Override
public void setEurekaDataCenterType( EurekaDataCenterType aDataCenterType ) {
_dataCenterType = aDataCenterType;
}
// /////////////////////////////////////////////////////////////////////////
// TWEAKS:
// /////////////////////////////////////////////////////////////////////////
/**
* {@inheritDoc}
*/
@Override
public EurekaServerDescriptor toHttpServerDescriptor( String aAlias, String aInstanceId, Scheme aScheme, String aHost, String aVirtualHost, int[] aIpAddress, int aPort, String aPingPath, String aStatusPath, String aHomePath, EurekaDataCenterType aDataCenterType ) {
return toHttpServerDescriptor( aAlias, aInstanceId, aScheme, aHost, aVirtualHost, aIpAddress, aPort, aPingPath, aStatusPath, aHomePath, aDataCenterType, this );
}
/**
* Attention: This method is package local! As it does some well known casts
* which are not obvious from the method signature! !!! ONLY INTENDED TO BE
* USED BY THE MAINTAINER OF THIS CLASS !!! Prepares the
* {@link HttpServerDescriptor} by creating it from this instance's state
* and the provided arguments. The provided arguments can modify
* theinstance's state. The {@link HttpServerDescriptor} as finally used is
* returned. You may modify this context and use it after modification to
* initialize the server via
* {@link HttpRegistrySidecar#initialize(HttpServerDescriptor, Url)} or
* {@link HttpRegistrySidecar#initialize(HttpServerDescriptor, Url, TrustStoreDescriptor)}.
*
* @param aAlias The name ("alias") which identifies the server in the
* registry.
* @param aInstanceId The TID for the instance when being registered at the
* service registry. If omitted, then the host name is used.
* @param aScheme The {@link Scheme} to which this server is being attached
* (HTTP or HTTPS).
* @param aHost The host name to be used to address this server. If omitted,
* then the system's host name should be used.
* @param aVirtualHost The virtual host name to be used for resolving.
* @param aIpAddress The IP-Address identifying the host.
* @param aPort The port of your service being registered. Make sure, you do
* not
* @param aPingPath The path to use as health-check end-point by this
* server.
* @param aStatusPath The path to use as status-page end-point by this
* server.
* @param aHomePath The path to use as home-page end-point by this server.
* @param aDataCenterType The data center type to be used.
* @param aRegistryService The service which's state is to be used.
*
* @return The {@link HttpServerDescriptor} as would be used when
* initializing this instance via
* {@link HttpRegistrySidecar#initialize()}
*/
static EurekaServerDescriptor toHttpServerDescriptor( String aAlias, String aInstanceId, Scheme aScheme, String aHost, String aVirtualHost, int[] aIpAddress, int aPort, String aPingPath, String aStatusPath, String aHomePath, EurekaDataCenterType aDataCenterType, EurekaRegistry> aRegistryService ) {
try {
aHost = toHost( aHost, aRegistryService );
}
catch ( UnknownHostException e ) {
LOGGER.log( Level.WARNING, "Unable to determine host for <" + aHomePath + "> as of: " + Trap.asMessage( e ), e );
}
try {
aIpAddress = toIpAddress( aIpAddress, aRegistryService );
}
catch ( IOException e ) {
LOGGER.log( Level.WARNING, "Unable to determine IP address for host <" + aHost + "> as of: " + Trap.asMessage( e ), e );
}
aPort = toPort( aPort, (PortProperty) aRegistryService );
aScheme = toScheme( aScheme, (SchemeProperty) aRegistryService );
aAlias = toAlias( aAlias, aRegistryService );
aVirtualHost = toVirtualHost( aVirtualHost, aRegistryService );
aDataCenterType = toDataCenterType( aDataCenterType, aRegistryService );
aInstanceId = toInstanceId( aInstanceId, aHost, aRegistryService );
final EurekaServerDescriptor theServerDescriptor = new EurekaServerDescriptor();
aPingPath = toPingPath( aPingPath, DEFAULT_PING_PATH, aRegistryService );
final Url thePingUrl = new Url( aScheme, aHost, ( (PortProperty) aRegistryService ).getPort(), aPingPath );
theServerDescriptor.setPingUrl( thePingUrl );
aHomePath = toHomePath( aHomePath, DEFAULT_HOME_PATH, aRegistryService );
final Url theHomeUrl = new Url( aScheme, aHost, ( (PortProperty) aRegistryService ).getPort(), aHomePath );
theServerDescriptor.setHomeUrl( theHomeUrl );
aStatusPath = toStatusPath( aStatusPath, DEFAULT_STATUS_PATH, aRegistryService );
final Url theStatusUrl = new Url( aScheme, aHost, ( (PortProperty) aRegistryService ).getPort(), aStatusPath );
theServerDescriptor.setStatusUrl( theStatusUrl );
theServerDescriptor.setHost( aInstanceId ); // Host := instance!
theServerDescriptor.setAlias( aAlias );
theServerDescriptor.setPort( aPort );
theServerDescriptor.setIpAddress( aIpAddress );
theServerDescriptor.setLeaseEvictionDurationInSecs( 30 );
theServerDescriptor.setVirtualHost( aVirtualHost );
final AmazonMetaData theMetaData = toAmazonMetaData();
if ( theMetaData != null ) {
theServerDescriptor.setAmazonMetaData( theMetaData );
}
if ( aDataCenterType == null ) {
aDataCenterType = theMetaData != null ? EurekaDataCenterType.AMAZON : EurekaDataCenterType.MY_OWN;
}
theServerDescriptor.setEurekaDataCenterType( aDataCenterType );
// Meta-Data |-->
theServerDescriptor.putMetaData( "host", aHost );
theServerDescriptor.putMetaData( "uname", Host.getUname() );
theServerDescriptor.putMetaData( "ipAddress", IpAddress.toString( aIpAddress ) );
// Meta-Data <--|
return theServerDescriptor;
}
// /////////////////////////////////////////////////////////////////////////
// HOOKS:
// /////////////////////////////////////////////////////////////////////////
/**
* Resolves the property from the provided value and the provided property
* and sets the property in case the provided value is not null.
*
* @param aHomePath The value to be used when not null.
* @param aDefaultHomePath The value to be used when instance TID is null.
* @param aProperty The property to be used when the value is null and which
* is to be set when the value is not null.
*
* @return The value when not null, else the value of the provided property.
*/
protected static String toHomePath( String aHomePath, String aDefaultHomePath, HomePathProperty aProperty ) {
if ( aHomePath != null ) {
aProperty.setHomePath( aHomePath );
}
else {
aHomePath = aProperty.getHomePath();
if ( aHomePath == null ) {
aHomePath = aDefaultHomePath;
aProperty.setHomePath( aHomePath );
}
}
return aHomePath;
}
/**
* Resolves the property from the provided value and the provided property
* and sets the property in case the provided value is not null.
*
* @param aStatusPath The value to be used when not null.
* @param aDefaultStatusPath The value to be used when instance TID is null.
* @param aProperty The property to be used when the value is null and which
* is to be set when the value is not null.
*
* @return The value when not null, else the value of the provided property.
*/
protected static String toStatusPath( String aStatusPath, String aDefaultStatusPath, StatusPathProperty aProperty ) {
if ( aStatusPath != null ) {
aProperty.setStatusPath( aStatusPath );
}
else {
aStatusPath = aProperty.getStatusPath();
if ( aStatusPath == null ) {
aStatusPath = aDefaultStatusPath;
aProperty.setStatusPath( aStatusPath );
}
}
return aStatusPath;
}
/**
* Resolves the property from the provided value and the provided property
* and sets the property in case the provided value is not null.
*
* @param aInstanceId The value to be used when not null.
* @param aHost The value to be used when instance TID is null.
* @param aProperty The property to be used when the value is null and which
* is to be set when the value is not null.
*
* @return The value when not null, else the value of the provided property.
*/
protected static String toInstanceId( String aInstanceId, String aHost, InstanceIdProperty aProperty ) {
if ( aInstanceId != null ) {
aProperty.setInstanceId( aInstanceId );
}
else {
aInstanceId = aProperty.getInstanceId();
if ( aInstanceId == null ) {
try {
final String theInstanceId = EC2MetadataUtils.getInstanceId();
if ( theInstanceId != null && theInstanceId.length() != 0 ) {
aInstanceId = theInstanceId;
aProperty.setInstanceId( aInstanceId );
}
}
catch ( Throwable ignore ) { /* ignore */ }
if ( aInstanceId == null ) {
aInstanceId = aHost;
aProperty.setInstanceId( aInstanceId );
}
}
}
return aInstanceId;
}
/**
* Registers the given service at Eureka.
*
* @param aServiceStatus The {@link EurekaServiceStatus} to be set.
*
* @throws HttpStatusException Thrown in case a HTTP response was of an
* erroneous status.
* @throws IOException Thrown in case opening or accessing an open line
* (connection, junction, link) caused problems.
*/
protected void doRegister( EurekaServiceStatus aServiceStatus ) throws HttpStatusException, IOException {
doRegister( aServiceStatus, this, _executorService );
}
/**
* Registers the given service at Eureka.
*
* @param aServiceStatus The {@link EurekaServiceStatus} to be set.
* @param aRegistryService The registry service to be used for registering.
* @param aExecutorService The {@link ExecutorService} used to create
* threads.
*
* @throws HttpStatusException Thrown in case a HTTP response was of an
* erroneous status.
* @throws IOException Thrown in case opening or accessing an open line
* (connection, junction, link) caused problems.
*/
protected static void doRegister( EurekaServiceStatus aServiceStatus, EurekaRegistry> aRegistryService, ExecutorService aExecutorService ) throws HttpStatusException, IOException {
final Url theRegistryUrl = new Url( aRegistryService.getHttpRegistryUrl(), aRegistryService.getHttpServerDescriptor().getAlias() );
final RestfulHttpClient theRestClient = new HttpRestClient( aExecutorService );
theRestClient.open( aRegistryService.getTrustStoreDescriptor() );
final RestRequestBuilder theBuilder = theRestClient.buildPost( theRegistryUrl );
aRegistryService.getHttpServerDescriptor().put( "instance/status", aServiceStatus != null ? aServiceStatus.name() : EurekaServiceStatus.UNKNOWN.name() );
theBuilder.setRequest( aRegistryService.getHttpServerDescriptor() );
theBuilder.getHeaderFields().putContentType( MediaType.APPLICATION_XML );
LOGGER.info( "Registering status <" + aServiceStatus + "> at <" + aRegistryService.getHttpRegistryUrl().toHttpUrl() + "> Eureka service registry for app-TID <" + aRegistryService.getHttpServerDescriptor().getAlias() + "> with instance-TID <" + aRegistryService.getHttpServerDescriptor().getHost() + "> ..." );
final RestResponse theResponse = theBuilder.toRestResponse();
if ( theResponse.getHttpStatusCode().isErrorStatus() ) {
throw theResponse.getHttpStatusCode().toHttpStatusException( "Cannot register service with alias <" + aRegistryService.getHttpServerDescriptor().getAlias() + "> with service registry <" + aRegistryService.getHttpRegistryUrl().toHttpUrl() + "> due to HTTP-Status-Code " + theResponse.getHttpStatusCode() + " <" + theResponse.getHttpStatusCode().getStatusCode() + ">: " + theResponse.getHttpBody() );
}
}
/**
* Does a Eureka status update for the given service.
*
* @param aServiceStatus The {@link EurekaServiceStatus} to be set.
*
* @throws HttpStatusException Thrown in case a HTTP response was of an
* erroneous status.
* @throws IOException Thrown in case opening or accessing an open line
* (connection, junction, link) caused problems.
* @throws UnknownHostException Thrown in case the targeted host is unknown.
*/
protected void doStatusUpdate( EurekaServiceStatus aServiceStatus ) throws IOException, HttpStatusException {
doStatusUpdate( aServiceStatus, this, _executorService );
}
/**
* Does a Eureka status update for the given service.
*
* @param aServiceStatus The {@link EurekaServiceStatus} to be set.
* @param aRegistryService The registry service to be used for registering.
* @param aExecutorService The {@link ExecutorService} used to create
* threads.
*
* @throws HttpStatusException Thrown in case a HTTP response was of an
* erroneous status.
* @throws IOException Thrown in case opening or accessing an open line
* (connection, junction, link) caused problems.
* @throws UnknownHostException Thrown in case the targeted host is unknown.
*/
protected static void doStatusUpdate( EurekaServiceStatus aServiceStatus, EurekaRegistry> aRegistryService, ExecutorService aExecutorService ) throws IOException, HttpStatusException {
final Url theRegistryUrl = new UrlBuilder( aRegistryService.getHttpRegistryUrl(), aRegistryService.getAlias(), aRegistryService.getInstanceId(), "status" );
theRegistryUrl.getQueryFields().put( "value", aServiceStatus.name() );
final RestfulHttpClient theRestClient = new HttpRestClient( aExecutorService );
theRestClient.open( aRegistryService.getTrustStoreDescriptor() );
LOGGER.info( "Status update <" + aServiceStatus + "> at <" + theRegistryUrl.toHttpUrl() + "> Eureka service registry for app-TID <" + aRegistryService.getAlias() + "> with instance-TID <" + aRegistryService.getInstanceId() + "> ..." );
final RestResponse theResponse;
theResponse = theRestClient.doPut( theRegistryUrl );
if ( theResponse.getHttpStatusCode().isErrorStatus() ) {
throw theResponse.getHttpStatusCode().toHttpStatusException( "Cannot register service with alias <" + aRegistryService.getAlias() + "> with service registry <" + aRegistryService.getHttpRegistryUrl().toHttpUrl() + "> due to HTTP-Status-Code " + theResponse.getHttpStatusCode() + " <" + theResponse.getHttpStatusCode().getStatusCode() + ">: " + theResponse.getHttpBody() );
}
}
/**
* Unregisters the given service at Eureka.
*
* @throws HttpStatusException Thrown in case a HTTP response was of an
* erroneous status.t
* @throws IOException Thrown in case opening or accessing an open line
* (connection, junction, link) caused problems.
*/
protected void doDeregister() throws IOException, HttpStatusException {
doDeregister( this, _executorService );
}
/**
* Unregisters the given service at Eureka.
*
* @param aRegistryService The registry service to be used for registering.
* @param aExecutorService The {@link ExecutorService} used to create
* threads.
*
* @throws HttpStatusException Thrown in case a HTTP response was of an
* erroneous status.t
* @throws IOException Thrown in case opening or accessing an open line
* (connection, junction, link) caused problems.
*/
protected static void doDeregister( EurekaRegistry> aRegistryService, ExecutorService aExecutorService ) throws IOException, HttpStatusException {
final Url theRegistryUrl = new Url( aRegistryService.getHttpRegistryUrl(), aRegistryService.getAlias(), aRegistryService.getInstanceId() );
final RestfulHttpClient theRestClient = new HttpRestClient( aExecutorService );
theRestClient.open( aRegistryService.getTrustStoreDescriptor() );
final RestResponse theResponse;
LOGGER.info( "Derigstering at <" + aRegistryService.getHttpRegistryUrl().toHttpUrl() + "> Eureka service registry for app-TID <" + aRegistryService.getAlias() + "> with instance-TID <" + aRegistryService.getInstanceId() + "> ..." );
theResponse = theRestClient.doDelete( theRegistryUrl );
if ( theResponse.getHttpStatusCode().isErrorStatus() ) {
throw theResponse.getHttpStatusCode().toHttpStatusException( "Cannot register service with alias <" + aRegistryService.getAlias() + "> with service registry <" + aRegistryService.getHttpRegistryUrl().toHttpUrl() + "> due to HTTP-Status-Code " + theResponse.getHttpStatusCode() + " <" + theResponse.getHttpStatusCode().getStatusCode() + ">: " + theResponse.getHttpBody() );
}
}
/**
* Resolves the property from the provided value and the provided property
* and sets the property in case the provided value is not null.
*
* @param aRegistryUrl The value to be used when not null.
* @param aProperty The property to be used when the value is null and which
* is to be set when the value is not null.
*
* @return The value when not null, else the value of the provided property.
*/
protected static Url toHttpRegistryUrl( Url aRegistryUrl, HttpRegistryUrlProperty aProperty ) {
aRegistryUrl = AbstractHttpRegistrySidecar.toHttpRegistryUrl( aRegistryUrl, aProperty );
if ( aRegistryUrl != null && aRegistryUrl.getPath() == null ) {
aRegistryUrl = new Url( aRegistryUrl, EUREKA_BASE_PATH );
aProperty.setHttpRegistryUrl( aRegistryUrl );
}
return aRegistryUrl;
}
/**
* Resolves the property from the provided value and the provided property
* and sets the property in case the provided value is not null.
*
* @param aDataCenterType The value to be used when not null.
* @param aProperty The property to be used when the value is null and which
* is to be set when the value is not null.
*
* @return The value when not null, else the value of the provided property.
*/
protected static EurekaDataCenterType toDataCenterType( EurekaDataCenterType aDataCenterType, EurekaDataCenterTypeProperty aProperty ) {
if ( aDataCenterType != null ) {
aProperty.setEurekaDataCenterType( aDataCenterType );
}
else {
aDataCenterType = aProperty.getEurekaDataCenterType();
}
return aDataCenterType;
}
/**
* Constructs the Amazon Meta-Data from the Machine's network and AWS
* settings.
*
* @return The according Amazon Meta-Data.
*/
protected static AmazonMetaData toAmazonMetaData() {
AmazonMetaData theMetaData = null;
try {
// Precondition for setting up AWS instance data |-->
final Region theRegion = Region.of( EC2MetadataUtils.getEC2InstanceRegion() );
if ( theRegion != null ) {
// Precondition for setting up AWS instance data <--|
theMetaData = new AmazonMetaData();
theMetaData.setAmiId( EC2MetadataUtils.getAmiId() );
final String theAmiLaunchIndex = EC2MetadataUtils.getAmiLaunchIndex();
Integer theLaunchIndex = 0;
if ( theAmiLaunchIndex != null ) {
theLaunchIndex = Integer.valueOf( theAmiLaunchIndex );
theMetaData.setAmiLaunchIndex( theLaunchIndex );
}
theMetaData.setAmiManifestPath( EC2MetadataUtils.getAmiManifestPath() );
theMetaData.setAvailabilityZone( EC2MetadataUtils.getAvailabilityZone() );
theMetaData.setInstanceId( EC2MetadataUtils.getInstanceId() );
theMetaData.setInstanceType( EC2MetadataUtils.getInstanceType() );
theMetaData.setLocalHostName( EC2MetadataUtils.getLocalHostName() );
// Too much information |-->
final List theInterfaces = EC2MetadataUtils.getNetworkInterfaces();
if ( theInterfaces != null ) {
List eLocalIPv4s = null;
List ePublicIPv4s = null;
String ePublicHostName = null;
for ( NetworkInterface eInterface : theInterfaces ) {
if ( eLocalIPv4s == null || eLocalIPv4s.size() == 0 ) {
eLocalIPv4s = eInterface.getLocalIPv4s();
if ( eLocalIPv4s != null && eLocalIPv4s.size() != 0 ) {
theMetaData.setLocalIpv4( eLocalIPv4s.get( 0 ) );
}
}
if ( ePublicHostName == null || ePublicHostName.isEmpty() ) {
ePublicHostName = eInterface.getPublicHostname();
if ( ePublicHostName != null && ePublicHostName.length() != 0 ) {
theMetaData.setPublicHostname( ePublicHostName );
}
}
if ( ePublicIPv4s == null || ePublicIPv4s.size() == 0 ) {
ePublicIPv4s = eInterface.getPublicIPv4s();
if ( ePublicIPv4s != null && ePublicIPv4s.size() != 0 ) {
theMetaData.setPublicIpv4( ePublicIPv4s.get( 0 ) );
}
}
}
}
// Too much information <--|
}
}
catch ( Throwable ignore ) { /* ignore */ }
return theMetaData;
}
// /////////////////////////////////////////////////////////////////////////
// INNER CLASSES:
// /////////////////////////////////////////////////////////////////////////
public static class HeartBeatDaemon extends TimerTask {
private final RestfulHttpClient _client;
private final EurekaRegistry> _registry;
/**
* Instantiates a new heart beat daemon.
*
* @param aRegistry the registry
* @param aExecutorService the executor service
*/
public HeartBeatDaemon( EurekaRegistry> aRegistry, ExecutorService aExecutorService ) {
_client = new HttpRestClient( aExecutorService ).withTrustStoreDescriptor( aRegistry.getTrustStoreDescriptor() );
_registry = aRegistry;
}
/**
* {@inheritDoc}
*/
@Override
public void run() {
if ( _registry.isRunning() ) {
final Url theUrl = new Url( _registry.getHttpRegistryUrl(), _registry.getAlias(), _registry.getInstanceId() );
LOGGER.log( Level.FINE, "Sending heartbeat to <" + theUrl.toHttpUrl() + "> ..." );
try {
final RestResponse theResponse = _client.doPut( theUrl );
if ( theResponse.getHttpStatusCode().isErrorStatus() ) {
LOGGER.log( Level.WARNING, "Received HTTP status code <" + theResponse.getHttpStatusCode().getStatusCode() + "> (" + theResponse.getHttpStatusCode() + ") send heartbeat to URL <" + theUrl.toHttpUrl() + ">: " + theResponse.getHttpBody() );
}
}
catch ( HttpResponseException e ) {
LOGGER.log( Level.WARNING, "Unable to notify heartbeat to URL <" + theUrl.toHttpUrl() + "> as of: " + Trap.asMessage( e ), e );
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy