侧边栏壁纸
博主头像
JavaLYG 博主等级

行动起来,活在当下

  • 累计撰写 32 篇文章
  • 累计创建 8 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

腾讯云\阿里云部署服务时向nacos注册的外网ip的解决方案

liuyg
2023-01-04 / 0 评论 / 0 点赞 / 91 阅读 / 0 字 / 正在检测是否收录...

问题描述:

两个腾讯云服务器,在B服务器的服务向A服务器的nacos注册时,用的内网ip,因为俩服务器不在同一个网段,造成B服务器注册上nacos后无法访问服务的情况。又不想每次运行输入ip端口,也不想在每个服务器都放sh脚本,所以有了这个方案

20221203224928566-1024x325.png

百度一大通后,发现其他博主这个方案很野,我很喜欢!又稍微改良了一下。可以区分本地和服务器,本地运行注册还是要用内网ip的嘛

关于将服务注册上nacos的过程(这里是原理可以跳过)

如果没有配置ip配置选项 走的是这些配置

@Bean
@ConditionalOnMissingBean
public SimpleDiscoveryProperties simpleDiscoveryProperties(@Value("${spring.application.name:application}") String serviceId) {
    this.simple.getLocal().setServiceId(serviceId);
    this.simple.getLocal().setUri(URI.create("http://" + this.inet.findFirstNonLoopbackHostInfo().getHostname() + ":" + this.findPort()));
    return this.simple;
}

其中 findFirstNonLoopbackHostInfo()

public HostInfo findFirstNonLoopbackHostInfo() {
    InetAddress address = this.findFirstNonLoopbackAddress();
    if (address != null) {
        return this.convertAddress(address);
    } else {
        HostInfo hostInfo = new HostInfo();
        hostInfo.setHostname(this.properties.getDefaultHostname());
        hostInfo.setIpAddress(this.properties.getDefaultIpAddress());
        return hostInfo;
    }
}

所以,想要注册公网ip,只能配置网卡或者spring.cloud.nacos.discovery.ip=xxx.xxx.xxx.xxx

野路子,无需配置公网ip或者适配网卡

  1. 配置nginx,获取部署服务的服务器的公网ip。
    在主服务器的nginx上配置
    location = /getIp{
    return 200 “$remote_addr”;
    }
    这里有个坑,如果你挂了cdn,请不要用域名去请求,用ip,不然你会获取到cdn的ip。或者你改成取cdn转发的真实ip

  2. 判断这个公网地址是本地开发环境or线上运行环境,并且如果是线上环境把公网ip更新到配置中去

    public class AfterConfigListener implements SmartApplicationListener, Ordered {
    
    	@Override
    	public boolean supportsEventType(Class<? extends ApplicationEvent> aClass) {
    		return (ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(aClass)
    				|| ApplicationPreparedEvent.class.isAssignableFrom(aClass));
    	}
    
    	@Override
    	public int getOrder() {
    		return (ConfigFileApplicationListener.DEFAULT_ORDER + 1);
    	}
    
    	@Override
    	public void onApplicationEvent(ApplicationEvent applicationEvent) {
    		// 判断服务ip+端口是否通,不通则大概率是本地,不设置公网ip
    		String ip = null;
    		try {
    			ip = InetAddress.getLocalHost().getHostAddress();
    		}
    		catch (UnknownHostException e) {
    			throw new RuntimeException(e);
    		}
    		// 设置端口,服务器linux设置22,windows设置3389
    		int port = 22;
    		int timeOut = 3000;
    		if (testIpAndPort(ip, port, timeOut)) {
    			// 可以访问通,证明是公网ip,设置注册nacos为公网获取到的ip
    			RestTemplate restTemplate = new RestTemplate();
    			ResponseEntity<String> response = restTemplate.getForEntity("http://域名 或者 服务器ip/getIp", String.class);
    			String currenIp = response.getBody();
    			if (applicationEvent instanceof ApplicationEnvironmentPreparedEvent) {
    				System.setProperty("spring.cloud.nacos.discovery.ip", currenIp);
    			}
    		}
    	}
    
    	/**
    	 * 测试ip及端口连通性
    	 * @param host
    	 * @param port
    	 * @param timeout
    	 * @return boolean
    	 */
    	public static boolean testIpAndPort(String host, int port, int timeout) {
    		Socket s = new Socket();
    		boolean status = false;
    		try {
    			s.connect(new InetSocketAddress(host, port), timeout);
    			System.out.println("ip及端口访问正常");
    			status = true;
    		}
    		catch (IOException e) {
    			System.out.println(host + ":" + port + "无法访问!");
    		}
    		finally {
    			try {
    				s.close();
    			}
    			catch (IOException ex) {
    				System.out.println("关闭socket异常" + ex);
    			}
    		}
    		return status;
    	}
    
    }

    因为本地大概率你的3389和22端口是不开放的。所以这里如果你的开发环境很特殊请使用其他方案:比如在服务器运行一个nginx什么的都放,打开80端口。访问的时候访问80端口

  3. 在启动类的main方法中注册这个listener

    SpringApplication springApplication = new SpringApplication(xxxxApplication.class);
    springApplication.addListeners(new AfterConfigListener());
    springApplication.run(args);

这时候你到nacos控制台上就能发现,ip已经是公网ip了

两个服务之间就不用在同个局域网内了

20221203224702196-1024x191.png

参考博客地址:https://juejin.cn/post/7111912514744500238

0

评论区