springcloud(暂时结束)
来源:互联网 发布:客户端软件开发 编辑:程序博客网 时间:2024/05/19 18:40
最近被人鄙视了,心情低落了很久,被嘲讽基础差,了解的不少,掌握的没几个。还有一些个人原因,暂时终结了springcloud学习,准备从最基础开始,重新学习总结,免得以后被人鄙视。
闲话不多说,最事情还是要有头有尾,把最后一点的eureka学习完整,也算是对springcloud有了一个概括上的了解,掌握还差的远。
首先学习服务注册,当服务启动时,要把自身的信息发送到服务中心。从上一章中我们学习到了springcloud利用的EurekaClient来获取服务。我们从这个接口入手。
该接口的实现类是DiscoveryClient,看到其注册服务的方法:
boolean register() throws Throwable { logger.info(PREFIX + appPathIdentifier + ": registering service..."); EurekaHttpResponse<Void> httpResponse; try { httpResponse = eurekaTransport.registrationClient.register(instanceInfo); } catch (Exception e) { logger.warn("{} - registration failed {}", PREFIX + appPathIdentifier, e.getMessage(), e); throw e; } if (logger.isInfoEnabled()) { logger.info("{} - registration status: {}", PREFIX + appPathIdentifier, httpResponse.getStatusCode()); } return httpResponse.getStatusCode() == 204; }
继续追踪,可以看到最终调用的是AbstractJerseyEurekaHttpClient的方法:
public EurekaHttpResponse<Void> register(InstanceInfo info) { String urlPath = "apps/" + info.getAppName(); ClientResponse response = null; try { Builder resourceBuilder = jerseyClient.resource(serviceUrl).path(urlPath).getRequestBuilder(); addExtraHeaders(resourceBuilder); response = resourceBuilder .header("Accept-Encoding", "gzip") .type(MediaType.APPLICATION_JSON_TYPE) .accept(MediaType.APPLICATION_JSON) .post(ClientResponse.class, info); return anEurekaHttpResponse(response.getStatus()).headers(headersOf(response)).build(); } finally { if (logger.isDebugEnabled()) { logger.debug("Jersey HTTP POST {}/{} with instance {}; statusCode={}", serviceUrl, urlPath, info.getId(), response == null ? "N/A" : response.getStatus()); } if (response != null) { response.close(); } } }
看到其中serviceUrl就是我们配置的服务中心zone的地址,info就是该客户端的基本信息:
我们再看一下是什么地方调用了这个注册方法,InstanceInfoReplicator在这个类中,这个类实现了Runnable接口,在其run方法中会调用注册方法。
这个类又在DiscoveryClient初始化时启动线程。
private void initScheduledTasks() { if (clientConfig.shouldFetchRegistry()) { // registry cache refresh timer int registryFetchIntervalSeconds = clientConfig.getRegistryFetchIntervalSeconds(); int expBackOffBound = clientConfig.getCacheRefreshExecutorExponentialBackOffBound(); scheduler.schedule( new TimedSupervisorTask( "cacheRefresh", scheduler, cacheRefreshExecutor, registryFetchIntervalSeconds, TimeUnit.SECONDS, expBackOffBound, new CacheRefreshThread() ), registryFetchIntervalSeconds, TimeUnit.SECONDS); } if (clientConfig.shouldRegisterWithEureka()) { int renewalIntervalInSecs = instanceInfo.getLeaseInfo().getRenewalIntervalInSecs(); int expBackOffBound = clientConfig.getHeartbeatExecutorExponentialBackOffBound(); logger.info("Starting heartbeat executor: " + "renew interval is: " + renewalIntervalInSecs); // Heartbeat timer scheduler.schedule( new TimedSupervisorTask( "heartbeat", scheduler, heartbeatExecutor, renewalIntervalInSecs, TimeUnit.SECONDS, expBackOffBound, new HeartbeatThread() ), renewalIntervalInSecs, TimeUnit.SECONDS); // InstanceInfo replicator instanceInfoReplicator = new InstanceInfoReplicator( this, instanceInfo, clientConfig.getInstanceInfoReplicationIntervalSeconds(), 2); // burstSize statusChangeListener = new ApplicationInfoManager.StatusChangeListener() { @Override public String getId() { return "statusChangeListener"; } @Override public void notify(StatusChangeEvent statusChangeEvent) { if (InstanceStatus.DOWN == statusChangeEvent.getStatus() || InstanceStatus.DOWN == statusChangeEvent.getPreviousStatus()) { // log at warn level if DOWN was involved logger.warn("Saw local status change event {}", statusChangeEvent); } else { logger.info("Saw local status change event {}", statusChangeEvent); } instanceInfoReplicator.onDemandUpdate(); } }; if (clientConfig.shouldOnDemandUpdateStatusChange()) { applicationInfoManager.registerStatusChangeListener(statusChangeListener); } instanceInfoReplicator.start(clientConfig.getInitialInstanceInfoReplicationIntervalSeconds()); } else { logger.info("Not registering with Eureka server per configuration"); } }
如果需要向eureka注册服务,则开启心跳检测,并注册服务。
接下来看服务中心的代码,服务中心的启动类EurekaBootStrap,有以下方法开始初始化:
public void contextInitialized(ServletContextEvent event) { try { initEurekaEnvironment(); initEurekaServerContext(); ServletContext sc = event.getServletContext(); sc.setAttribute(EurekaServerContext.class.getName(), serverContext); } catch (Throwable e) { logger.error("Cannot bootstrap eureka server :", e); throw new RuntimeException("Cannot bootstrap eureka server :", e); } }
在initEurekaServerContect()方法中初始化了两个类的对象:PeerAwareInstanceRegistry和PeerEurekaNodes
分别看这两个类:这连个类的作用就是服务注册和多个服务中心的服务同步。
看PeerAwareInstanceRegistry这个类的方法:
public void register(final InstanceInfo info, final boolean isReplication) { int leaseDuration = Lease.DEFAULT_DURATION_IN_SECS; if (info.getLeaseInfo() != null && info.getLeaseInfo().getDurationInSecs() > 0) { leaseDuration = info.getLeaseInfo().getDurationInSecs(); } super.register(info, leaseDuration, isReplication); replicateToPeers(Action.Register, info.getAppName(), info.getId(), info, null, isReplication); }
就是注册服务和同步服务到其他的中心,我们看一看到其父类中维护了一个map,保存了所有的服务。
private final ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>> registry = new ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>>();
ApplicationResource这个类,就是用来接收请求的。
@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.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
最终如果注册成功,则返回了204,和我们在实际应用中看到的日志信息是完全一样的。
eureka的一些配置信息都在DefaultEurekaClientConfig这里,默认值之类的可以来这里查找。
例如
@Override public int getEurekaServerReadTimeoutSeconds() { return configInstance.getIntProperty( namespace + EUREKA_SERVER_READ_TIMEOUT_KEY, 8).get(); }等等。
springcloud就暂时放一放了,恶补一下基础,接下来准备先从jvm开始,好好系统的学习一遍。同时也再过一遍设计模式,准备把每个设计模式用java实现一遍加深印象。
代码会一点一点的上传到github上。不要再被鄙视了。https://github.com/Begro/acm.git
- springcloud(暂时结束)
- QQ模拟---暂时结束
- 暂时结束《C程序设计语言》
- Linux学习暂时结束
- 暂时
- 暂时
- 暂时
- 暂时
- 软考结束了,考试暂时结束了,学习却没有尽头
- SpringCloud
- springcloud
- SpringCloud
- springcloud
- springcloud
- springcloud
- SpringCloud(六)springcloud feign
- 【springCloud】springCloud中文手册
- 【SpringCloud】SpringCloud简介
- 详解SQL盲注测试高级技巧
- 关于js根据类名获取元素
- 【多线程系列二】-master-woker模式:统计单次频率
- 很好用的下拉刷新上拉加载的框架smartrefreshlayout属性
- 牛客网错题集锦3
- springcloud(暂时结束)
- 12种不宜使用的Javascript语法---《Javascript语言精粹》
- 自动轮播加Scrollview加tablyout加多条目
- (算法)初级排序算法
- 购物车
- CS 300 Tree Antichain 构造,树,二分染色
- gomicro微服务系列之一
- How to Construct Basic Logic Gates from Nand Gate Using Bool Algebra
- hadoop streaming 遇到的问题小结