当前位置:   article > 正文

Eureka 下线

eureka下线机器

Eureka 下线

  1. // DiscoveryClient.java
  2. @PreDestroy
  3. @Override
  4. public synchronized void shutdown() {
  5. if (isShutdown.compareAndSet(false, true)) {
  6. logger.info("Shutting down DiscoveryClient ...");
  7. if (statusChangeListener != null && applicationInfoManager != null) {
  8. applicationInfoManager.unregisterStatusChangeListener(statusChangeListener.getId());
  9. }
  10. cancelScheduledTasks();
  11. // If APPINFO was registered
  12. if (applicationInfoManager != null
  13. && clientConfig.shouldRegisterWithEureka()
  14. && clientConfig.shouldUnregisterOnShutdown()) {
  15. //讲服务实例的状态设置为DOWN
  16. applicationInfoManager.setInstanceStatus(InstanceStatus.DOWN);
  17. //取消注册
  18. unregister();
  19. }
  20. //关闭网络通信组件
  21. if (eurekaTransport != null) {
  22. eurekaTransport.shutdown();
  23. }
  24. //关闭监听器
  25. heartbeatStalenessMonitor.shutdown();
  26. registryStalenessMonitor.shutdown();
  27. Monitors.unregisterObject(this);
  28. logger.info("Completed shut down of DiscoveryClient");
  29. }
  30. }
  • 调用 ApplicationInfoManager#setInstanceStatus(...) 方法,设置应用实例为关闭( DOWN )。
  • 调用 #unregister() 方法,实现代码如下:
  1. // DiscoveryClient.java
  2. void unregister() {
  3. // It can be null if shouldRegisterWithEureka == false
  4. if(eurekaTransport != null && eurekaTransport.registrationClient != null) {
  5. try {
  6. logger.info("Unregistering ...");
  7. EurekaHttpResponse<Void> httpResponse = eurekaTransport.registrationClient.cancel(instanceInfo.getAppName(), instanceInfo.getId());
  8. logger.info(PREFIX + appPathIdentifier + " - deregister status: " + httpResponse.getStatusCode());
  9. } catch (Exception e) {
  10. logger.error(PREFIX + appPathIdentifier + " - de-registration failed" + e.getMessage(), e);
  11. }
  12. }
  13. }
  14. // AbstractJerseyEurekaHttpClient.java
  15. @Override
  16. public EurekaHttpResponse<Void> cancel(String appName, String id) {
  17. String urlPath = "apps/" + appName + '/' + id;
  18. ClientResponse response = null;
  19. try {
  20. Builder resourceBuilder = jerseyClient.resource(serviceUrl).path(urlPath).getRequestBuilder();
  21. addExtraHeaders(resourceBuilder);
  22. response = resourceBuilder.delete(ClientResponse.class);
  23. return anEurekaHttpResponse(response.getStatus()).headers(headersOf(response)).build();
  24. } finally {
  25. if (logger.isDebugEnabled()) {
  26. logger.debug("Jersey HTTP DELETE {}/{}; statusCode={}", serviceUrl, urlPath, response == null ? "N/A" : response.getStatus());
  27. }
  28. if (response != null) {
  29. response.close();
  30. }
  31. }
  32. }
  • 调用 AbstractJerseyEurekaHttpClient#cancel(...) 方法,DELETE 请求 Eureka-Server 的 apps/${APP_NAME}/${INSTANCE_INFO_ID} 接口,实现应用实例信息的下线。

com.netflix.eureka.resources.InstanceResource,处理单个应用实例信息的请求操作的 Resource ( Controller )。

下线应用实例信息的请求,映射 InstanceResource#cancelLease() 方法,实现代码如下:

  1. @DELETE
  2. public Response cancelLease(
  3. @HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication) {
  4. // 下线
  5. boolean isSuccess = registry.cancel(app.getName(), id, "true".equals(isReplication));
  6. if (isSuccess) { // 下线成功
  7. logger.debug("Found (Cancel): " + app.getName() + " - " + id);
  8. return Response.ok().build();
  9. } else { // 下线成功
  10. logger.info("Not Found (Cancel): " + app.getName() + " - " + id);
  11. return Response.status(Status.NOT_FOUND).build();
  12. }
  13. }

调用 AbstractInstanceRegistry#cancel(...) 方法,下线应用实例信息,实现代码如下:

  1. @Override
  2. public boolean cancel(String appName, String id, boolean isReplication) {
  3. return internalCancel(appName, id, isReplication);
  4. }
  5. /**
  6. * {@link #cancel(String, String, boolean)} method is overridden by {@link PeerAwareInstanceRegistry}, so each
  7. * cancel request is replicated to the peers. This is however not desired for expires which would be counted
  8. * in the remote peers as valid cancellations, so self preservation mode would not kick-in.
  9. */
  10. protected boolean internalCancel(String appName, String id, boolean isReplication) {
  11. read.lock();
  12. try {
  13. CANCEL.increment(isReplication);
  14. Map<String, Lease<InstanceInfo>> gMap = registry.get(appName);
  15. Lease<InstanceInfo> leaseToCancel = null;
  16. if (gMap != null) {
  17. leaseToCancel = gMap.remove(id);
  18. }
  19. //将服务实例加入最近下线的queue中
  20. recentCanceledQueue.add(new Pair<Long, String>(System.currentTimeMillis(), appName + "(" + id + ")"));
  21. InstanceStatus instanceStatus = overriddenInstanceStatusMap.remove(id);
  22. if (instanceStatus != null) {
  23. logger.debug("Removed instance id {} from the overridden map which has value {}", id, instanceStatus.name());
  24. }
  25. if (leaseToCancel == null) {
  26. CANCEL_NOT_FOUND.increment(isReplication);
  27. logger.warn("DS: Registry: cancel failed because Lease is not registered for: {}/{}", appName, id);
  28. return false;
  29. } else {
  30. //调用cancel,保存一个时间戳
  31. leaseToCancel.cancel();
  32. InstanceInfo instanceInfo = leaseToCancel.getHolder();
  33. String vip = null;
  34. String svip = null;
  35. if (instanceInfo != null) {
  36. instanceInfo.setActionType(ActionType.DELETED);
  37. //丢到最近改变的队列中
  38. recentlyChangedQueue.add(new RecentlyChangedItem(leaseToCancel));
  39. //设置了最近一次变更的时间戳
  40. instanceInfo.setLastUpdatedTimestamp();
  41. vip = instanceInfo.getVIPAddress();
  42. svip = instanceInfo.getSecureVipAddress();
  43. //服务的注册,下线,过期,都会代表这个服务实例变化了,都会将自己放入最近改变的队列中
  44. //这个最近改变的队列,只会保留最近3分钟的实例
  45. //所以说eureka client拉取增量注册表的时候,其实就是拉取最近3分钟有变化的服务实例。
  46. }
  47. invalidateCache(appName, vip, svip);
  48. logger.info("Cancelled instance {}/{} (replication={})", appName, id, isReplication);
  49. }
  50. } finally {
  51. read.unlock();
  52. }
  53. synchronized (lock) {
  54. if (this.expectedNumberOfClientsSendingRenews > 0) {
  55. // Since the client wants to cancel it, reduce the number of clients to send renews.
  56. //修改期望值
  57. this.expectedNumberOfClientsSendingRenews = this.expectedNumberOfClientsSendingRenews - 1;
  58. updateRenewsPerMinThreshold();
  59. }
  60. }
  61. return true;
  62. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/963383
推荐阅读
相关标签
  

闽ICP备14008679号