dubbo 机器多IP问题的解决
承载dubbo服务的机器多IP时,需要指定dubbo服务需要绑定到的IP(dubbo.protocol.host),确保登记到注册中心的提供者或者消费者的IP之间可以互相ping通
此IP与具体环境有关,上生产环境时,需要进行增量配置
=========================
绑定IP,DUBBO 怎么做的
通常绑定本机ip地址 一般如下
- InetSocketAddress address = new InetSocketAddress(port);
- Channel serverChannel = bootstrap.bind(address);
InetSocketAddress默认使用的是什么ip呢?看看内部代码就明白了:
- public InetSocketAddress(int port) {
- this(InetAddress.anyLocalAddress(), port);
- }
InetAddress.anyLocalAddress()一般就是0.0.0.0/0.0.0.0,如果我们有两块网卡,一块内网,一块外网,那么都能访问这个socket,这通常是不安全的。那么通过InetAddress.getLocalHost().getHostAddress()呢?
结果悲剧了,使用上面的代码取回的是127.0.0.1。
好了,看看dubbo是怎么解决,dubbo获取本机ip地址的方法封装在com.alibaba.dubbo.common.utils.NetUtils类里面。
- import java.net.InetAddress;
- import java.net.NetworkInterface;
- import java.util.Enumeration;
- import java.util.regex.Pattern;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- public class NetUtils {
- private static final Logger logger = LoggerFactory.getLogger(NetUtils.class);
- private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$");
- private static final Pattern LOCAL_IP_PATTERN = Pattern.compile("127(\\.\\d{1,3}){3}$");
- public static final String ANYHOST = "0.0.0.0";
- public static final String LOCALHOST = "127.0.0.1";
- private static boolean isValidAddress(InetAddress address) {
- if (address == null || address.isLoopbackAddress()) return false;
- String name = address.getHostAddress();
- return (name != null && !ANYHOST.equals(name) && !LOCALHOST.equals(name) && IP_PATTERN.matcher(name).matches());
- }
- public static boolean isLocalHost(String host) {
- return host != null && (LOCAL_IP_PATTERN.matcher(host).matches() || host.equalsIgnoreCase("localhost"));
- }
- public static boolean isAnyHost(String host) {
- return "0.0.0.0".equals(host);
- }
- private static volatile InetAddress LOCAL_ADDRESS = null;
- /**
- * 遍历本地网卡,返回第一个合理的IP。
- *
- * @return 本地网卡IP
- */
- public static InetAddress getLocalAddress() {
- if (LOCAL_ADDRESS != null) {
- return LOCAL_ADDRESS;
- }
- InetAddress localAddress = getLocalAddress0();
- LOCAL_ADDRESS = localAddress;
- return localAddress;
- }
- private static InetAddress getLocalAddress0() {
- InetAddress localAddress = null;
- try {
- localAddress = InetAddress.getLocalHost();
- if (isValidAddress(localAddress)) {
- return localAddress;
- }
- } catch (Throwable e) {
- logger.warn("Failed to retriving ip address, " + e.getMessage(), e);
- }
- try {
- Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
- if (interfaces != null) {
- while (interfaces.hasMoreElements()) {
- try {
- NetworkInterface network = interfaces.nextElement();
- Enumeration<InetAddress> addresses = network.getInetAddresses();
- if (addresses != null) {
- while (addresses.hasMoreElements()) {
- try {
- InetAddress address = addresses.nextElement();
- if (isValidAddress(address)) {
- return address;
- }
- } catch (Throwable e) {
- logger.warn("Failed to retriving ip address, " + e.getMessage(), e);
- }
- }
- }
- } catch (Throwable e) {
- logger.warn("Failed to retriving ip address, " + e.getMessage(), e);
- }
- }
- }
- } catch (Throwable e) {
- logger.warn("Failed to retriving ip address, " + e.getMessage(), e);
- }
- logger.error("Could not get local host ip address, will use 127.0.0.1 instead.");
- return localAddress;
- }
- }
简单的说就是通过NetworkInterface遍历网卡address,然后通过isValidAddress校验ip是否正常即可。需要注意的一点是,dubbo通过Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$")判断ip是否合法,也就是说不能保证只返回内网ip!
=====================================
http://curious.iteye.com/blog/2286476