序
本文主要研究一下eureka server的instance注册及元数据变更接口
ApplicationResource.addInstance
eureka-core-1.8.8-sources.jar!/com/netflix/eureka/resources/ApplicationResource.java
@POST
@Consumes({"application/json", "application/xml"})
public Response addInstance(InstanceInfo info,
@HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication) {
logger.debug("Registering instance {} (replication={})", info.getId(), isReplication);
// validate that the instanceinfo contains all the necessary required fields
if (isBlank(info.getId())) {
return Response.status(400).entity("Missing instanceId").build();
} else if (isBlank(info.getHostName())) {
return Response.status(400).entity("Missing hostname").build();
} else if (isBlank(info.getIPAddr())) {
return Response.status(400).entity("Missing ip address").build();
} else if (isBlank(info.getAppName())) {
return Response.status(400).entity("Missing appName").build();
} else if (!appName.equals(info.getAppName())) {
return Response.status(400).entity("Mismatched appName, expecting " + appName + " but was " + info.getAppName()).build();
} else if (info.getDataCenterInfo() == null) {
return Response.status(400).entity("Missing dataCenterInfo").build();
} else if (info.getDataCenterInfo().getName() == null) {
return Response.status(400).entity("Missing dataCenterInfo Name").build();
}
// handle cases where clients may be registering with bad DataCenterInfo with missing data
DataCenterInfo dataCenterInfo = info.getDataCenterInfo();
if (dataCenterInfo instanceof UniqueIdentifier) {
String dataCenterInfoId = ((UniqueIdentifier) dataCenterInfo).getId();
if (isBlank(dataCenterInfoId)) {
boolean experimental = "true".equalsIgnoreCase(serverConfig.getExperimental("registration.validation.dataCenterInfoId"));
if (experimental) {
String entity = "DataCenterInfo of type " + dataCenterInfo.getClass() + " must contain a valid id";
return Response.status(400).entity(entity).build();
} else if (dataCenterInfo instanceof AmazonInfo) {
AmazonInfo amazonInfo = (AmazonInfo) dataCenterInfo;
String effectiveId = amazonInfo.get(AmazonInfo.MetaDataKey.instanceId);
if (effectiveId == null) {
amazonInfo.getMetadata().put(AmazonInfo.MetaDataKey.instanceId.getName(), info.getId());
}
} else {
logger.warn("Registering DataCenterInfo of type {} without an appropriate id", dataCenterInfo.getClass());
}
}
}
registry.register(info, "true".equals(isReplication));
return Response.status(204).build(); // 204 to be backwards compatible
}
这个是注册应用实例的服务端处理逻辑
实例
curl -i -H "Content-Type: application/json" -H "Accept-Encoding: gzip" -X POST -d '{
"instance": {
"instanceId": "test1",
"app": "test-service",
"appGroupName": null,
"ipAddr": "127.0.0.1",
"sid": "na",
"homePageUrl": null,
"statusPageUrl": null,
"healthCheckUrl": null,
"secureHealthCheckUrl": null,
"vipAddress": "test-service",
"secureVipAddress": "test-service",
"countryId": 1,
"dataCenterInfo": {
"@class": "com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo",
"name": "MyOwn"
},
"hostName": "127.0.0.1",
"status": "UP",
"leaseInfo": null,
"isCoordinatingDiscoveryServer": false,
"lastUpdatedTimestamp": 1525661162147,
"lastDirtyTimestamp": 1525661162147,
"actionType": null,
"asgName": null,
"overridden_status": "UNKNOWN",
"port": {
"$": 9090,
"@enabled": "true"
},
"securePort": {
"$": 7002,
"@enabled": "false"
},
"metadata": {
"@class": "java.util.Collections$EmptyMap"
}
}
}' http://localhost:8761/eureka/apps/test-service
返回
HTTP/1.1 204
Content-Type: application/xml
Date: Mon, 07 May 2018 03:01:23 GMT
InstanceResource.updateMetadata
eureka-core-1.8.8-sources.jar!/com/netflix/eureka/resources/InstanceResource.java
@PUT
@Path("metadata")
public Response updateMetadata(@Context UriInfo uriInfo) {
try {
InstanceInfo instanceInfo = registry.getInstanceByAppAndId(app.getName(), id);
// ReplicationInstance information is not found, generate an error
if (instanceInfo == null) {
logger.error("Cannot find instance while updating metadata for instance {}", id);
return Response.serverError().build();
}
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
Set<Entry<String, List<String>>> entrySet = queryParams.entrySet();
Map<String, String> metadataMap = instanceInfo.getMetadata();
// Metadata map is empty - create a new map
if (Collections.emptyMap().getClass().equals(metadataMap.getClass())) {
metadataMap = new ConcurrentHashMap<String, String>();
InstanceInfo.Builder builder = new InstanceInfo.Builder(instanceInfo);
builder.setMetadata(metadataMap);
instanceInfo = builder.build();
}
// Add all the user supplied entries to the map
for (Entry<String, List<String>> entry : entrySet) {
metadataMap.put(entry.getKey(), entry.getValue().get(0));
}
registry.register(instanceInfo, false);
return Response.ok().build();
} catch (Throwable e) {
logger.error("Error updating metadata for instance {}", id, e);
return Response.serverError().build();
}
}
这个是更改meta的服务端处理逻辑
实例
curl -i -X PUT http://localhost:8761/eureka/apps/test-service/test1/metadata?env=prod
返回
HTTP/1.1 200
Content-Type: application/xml
Content-Length: 0
Date: Mon, 07 May 2018 03:03:37 GMT
小结
- POST /eureka/apps/{appId}
可以注册/更新实例信息 - PUT /eureka/apps/{appId}/{instanceId}/metadata?metaKey1=metaValue1
可以用来更新meta信息