您的位置: 首页 - 站长

asp网站小迪网站建设

当前位置: 首页 > news >正文

asp网站,小迪网站建设,汕头网,wordpress主题请勿删除版权信息一。技术背景 由于升级jdk17的需要 我们将项目中的 spring cloud spring cloud alibaba 以及springboot进行了升级 各版本如下 spring cloud 2021.0.5 spring cloud alibaba 2021.0.5.0 spring boot 2.6.13 二。问题表现 当启动项目服务后#xff0c;服务无法注册到 sentin…一。技术背景 由于升级jdk17的需要 我们将项目中的 spring cloud spring cloud alibaba 以及springboot进行了升级 各版本如下 spring cloud 2021.0.5 spring cloud alibaba 2021.0.5.0 spring boot 2.6.13 二。问题表现 当启动项目服务后服务无法注册到 sentinel-dashboard 三。错误排查 首先检查sentinel-dashboard 启动状态 启动成功并且可以正常访问且不存在网络问题环境配置检查 !– 依赖检查 无误 – dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactId /dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-sentinel/artifactId /dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-alibaba-sentinel-gateway/artifactId /dependency配置检查 #配置也正常 spring.cloud.sentinel.transport.dashboardlocalhost:8080 spring.cloud.sentinel.transport.port8719第三步源码追踪 接下来开始漫长源码分析步骤 然后点击 spring.cloud.sentinel.transport.dashboard 这条配置 跳转 com.alibaba.cloud.sentinel.SentinelProperties.Transport#setDashboard 然后点击 getDashboard() 方法查看在哪里调用 最后来到了 com.alibaba.cloud.sentinel.custom.SentinelAutoConfiguration#init 在如下代码中 Configuration(proxyBeanMethods false) ConditionalOnProperty(name spring.cloud.sentinel.enabled, matchIfMissing true) EnableConfigurationProperties(SentinelProperties.class) public class SentinelAutoConfiguration {PostConstructprivate void init() {///省略部分逻辑 if (StringUtils.isEmpty(System.getProperty(TransportConfig.SERVER_PORT)) StringUtils.isNotBlank(properties.getTransport().getPort())) {System.setProperty(TransportConfig.SERVER_PORT,properties.getTransport().getPort());}if (StringUtils.isEmpty(System.getProperty(TransportConfig.CONSOLE_SERVER)) StringUtils.isNotBlank(properties.getTransport().getDashboard())) {System.setProperty(TransportConfig.CONSOLE_SERVER,properties.getTransport().getDashboard());}} }断点时 发现配置成功被设置到 系统的属性配置中 接下来再来看 心跳发送具体类 HeartbeatSenderInitFunc com.alibaba.csp.sentinel.transport.init.HeartbeatSenderInitFunc#init Override public void init() {HeartbeatSender sender HeartbeatSenderProvider.getHeartbeatSender();if (sender null) {RecordLog.warn([HeartbeatSenderInitFunc] WARN: No HeartbeatSender loaded);return;}initSchedulerIfNeeded();long interval retrieveInterval(sender);setIntervalIfNotExists(interval);//定时调度发送心跳scheduleHeartbeatTask(sender, interval); }具体得调度逻辑 每5秒发送一次心跳 private void scheduleHeartbeatTask(/NonNull/ final HeartbeatSender sender, /Valid/ long interval) {pool.scheduleAtFixedRate(new Runnable() {Overridepublic void run() {try {sender.sendHeartbeat();} catch (Throwable e) {RecordLog.warn([HeartbeatSender] Send heartbeat error, e);}}}, 5000, interval, TimeUnit.MILLISECONDS);RecordLog.info([HeartbeatSenderInit] HeartbeatSender started: sender.getClass().getCanonicalName()); }我们再来看下具体的实现 sender.sendHeartbeat(); 实现类只有一个 SimpleHttpHeartbeatSender com.alibaba.csp.sentinel.transport.heartbeat.SimpleHttpHeartbeatSender#sendHeartbeat Override
public boolean sendHeartbeat() throws Exception { if (TransportConfig.getRuntimePort() 0) { RecordLog.info([SimpleHttpHeartbeatSender] Command server port not initialized, wont send heartbeatreturn false; } Endpoint addrInfo getAvailableAddress(); if (addrInfo null) { return false; } SimpleHttpRequest request new SimpleHttpRequest(addrInfo, TransportConfig.getHeartbeatApiPath()); request.setParams(heartBeat.generateCurrentMessage()); try { SimpleHttpResponse response httpClient.post(request); if (response.getStatusCode() OK_STATUS) { return true; } else if (clientErrorCode(response.getStatusCode()) || serverErrorCode(response.getStatusCode())) { RecordLog.warn([SimpleHttpHeartbeatSender] Failed to send heartbeat to addrInfo , http status code: response.getStatusCode()); } } catch (Exception e) { RecordLog.warn([SimpleHttpHeartbeatSender] Failed to send heartbeat to addrInfo, e); } return false;
}
以上就是发送心跳的逻辑 核心逻辑 获取有效的链接创建连接发送心跳请求响应以及异常处理 但是在断点过程中 有效的链接列表居然是空的 这就是导致代码无法继续向下 然后我们继续围绕这个点进行排查 获取有效的地址列表方法如下 private Endpoint getAvailableAddress() {if (addressList null || addressList.isEmpty()) {return null;}if (currentAddressIdx 0) {currentAddressIdx 0;}int index currentAddressIdx % addressList.size();return addressList.get(index); }发现使用的成员变量 addressList 我们再来找下这个值的赋值操作 赋值操作只有一个地方 在SimpleHttpHeartbeatSender的构造方法中 public SimpleHttpHeartbeatSender() {// Retrieve the list of default addresses.ListEndpoint newAddrs TransportConfig.getConsoleServerList();if (newAddrs.isEmpty()) {RecordLog.warn([SimpleHttpHeartbeatSender] Dashboard server address not configured or not available);} else {RecordLog.info([SimpleHttpHeartbeatSender] Default console address list retrieved: {}, newAddrs);}this.addressList newAddrs; }com.alibaba.csp.sentinel.transport.config.TransportConfig#getConsoleServerList public static ListEndpoint getConsoleServerList() {String config SentinelConfig.getConfig(CONSOLE_SERVER);ListEndpoint list new ArrayListEndpoint();if (StringUtil.isBlank(config)) {return list;}//。。。。。省略部分return list; }com.alibaba.csp.sentinel.config.SentinelConfig#getConfig(java.lang.String) public static String getConfig(String key) {AssertUtil.notNull(key, key cannot be null);return props.get(key); }我们再来看下 props的初始化 在SentinelConfig的静态构造中 static {try {initialize();//加载配置loadProps();resolveAppName();resolveAppType();RecordLog.info([SentinelConfig] Application type resolved: {}, appType);} catch (Throwable ex) {RecordLog.warn([SentinelConfig] Failed to initialize, ex);ex.printStackTrace();} }com.alibaba.csp.sentinel.config.SentinelConfig#loadProps private static void loadProps() {///从配置加载中获取配置Properties properties SentinelConfigLoader.getProperties();for (Object key : properties.keySet()) {setConfig((String) key, (String) properties.get(key));} }从SentinelConfigLoader 获取到配置 public static Properties getProperties() {return properties; }而这个properties的初始化是在SentinelConfigLoader 静态构造方法中 static {try {load();} catch (Throwable t) {RecordLog.warn([SentinelConfigLoader] Failed to initialize configuration items, t);} }private static void load() {// Order: system property - system env - default file (classpath:sentinel.properties) - legacy pathString fileName System.getProperty(SENTINEL_CONFIG_PROPERTY_KEY);if (StringUtil.isBlank(fileName)) {fileName System.getenv(SENTINEL_CONFIG_ENV_KEY);if (StringUtil.isBlank(fileName)) {fileName DEFAULT_SENTINEL_CONFIG_FILE;}}Properties p ConfigUtil.loadProperties(fileName);if (p ! null !p.isEmpty()) {RecordLog.info([SentinelConfigLoader] Loading Sentinel config from {}, fileName);properties.putAll(p);}for (Map.EntryObject, Object entry : new CopyOnWriteArraySet(System.getProperties().entrySet())) {String configKey entry.getKey().toString();String newConfigValue entry.getValue().toString();String oldConfigValue properties.getProperty(configKey);properties.put(configKey, newConfigValue);if (oldConfigValue ! null) {RecordLog.info([SentinelConfigLoader] JVM parameter overrides {}: {} - {},configKey, oldConfigValue, newConfigValue);}} }看到这里就大概明白了因为这是静态代码话 肯定优先初始化而我们的地址在项目启动bean加载中才会设置到System的Properties里 所以获取的 地址一直是空的。 也无法注册到sentinel-dashboard上 四。解决办法 idea 启动类 增加参数 指定dashboard server地址 以及应用名称 -Dcsp.sentinel.dashboard.serverlocalhost:8080 -Dcsp.sentinel.app.namegateway-service启动类设置系统变量 SpringBootApplication EnableDiscoveryClient public class GatewayServiceApplication {public static void main(String[] args) {System.setProperty(csp.sentinel.dashboard.server,localhost:8080);System.setProperty(csp.sentinel.app.name,gateway-service);SpringApplication.run(GatewayServiceApplication.class, args);}}五。后续分析旧的版本的依赖对应的实现方式 旧的依赖版本为 springboot 2.3.12.RELEASE spring cloud Hoxton.SR12 spring cloud alibaba 2.2.9.RELEASE