昨天一个同事说按下面链接,最新demo无法启动
我试了一下,的确是错误,感觉端口占用了,要么注册地址有误
com.alibaba.dubbo.rpc.RpcException: Failed to invoke the method sayHello in the service com.alibaba.dubbo.demo.DemoService. Tried 3 times of the providers [0.0.7.226:20880] (1/1) from the registry 127.0.0.1:2181 on the consumer 0.0.7.226 using the dubbo version . Last error is: Failed to invoke remote method: sayHello, provider: dubbo://0.0.7.226:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-consumer&check=false&dubbo=2.0.2&generic=false&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=42712&qos.port=33333®ister.ip=0.0.7.226&remote.timestamp=1554056704529&side=consumer×tamp=1554056712432, cause: message can not send, because channel is closed . url:dubbo://0.0.7.226:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-consumer&check=false&codec=dubbo&dubbo=2.0.2&generic=false&heartbeat=60000&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=42712&qos.port=33333®ister.ip=0.0.7.226&remote.timestamp=1554056704529&side=consumer×tamp=1554056712432 at com.alibaba.dubbo.rpc.cluster.support.FailoverClusterInvoker.doInvoke(FailoverClusterInvoker.java:109) at com.alibaba.dubbo.rpc.cluster.support.AbstractClusterInvoker.invoke(AbstractClusterInvoker.java:234) at com.alibaba.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker.invoke(MockClusterInvoker.java:75) at com.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler.invoke(InvokerInvocationHandler.java:52) at com.alibaba.dubbo.common.bytecode.proxy0.sayHello(proxy0.java) at com.alibaba.dubbo.demo.consumer.Consumer.main(Consumer.java:35) Caused by: com.alibaba.dubbo.remoting.RemotingException: message can not send, because channel is closed . url:dubbo://0.0.7.226:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-consumer&check=false&codec=dubbo&dubbo=2.0.2&generic=false&heartbeat=60000&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=42712&qos.port=33333®ister.ip=0.0.7.226&remote.timestamp=1554056704529&side=consumer×tamp=1554056712432 at com.alibaba.dubbo.remoting.transport.AbstractClient.send(AbstractClient.java:263) at com.alibaba.dubbo.remoting.transport.AbstractPeer.send(AbstractPeer.java:53) at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeChannel.request(HeaderExchangeChannel.java:116) at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeClient.request(HeaderExchangeClient.java:90) at com.alibaba.dubbo.rpc.protocol.dubbo.ReferenceCountExchangeClient.request(ReferenceCountExchangeClient.java:83) at com.alibaba.dubbo.rpc.protocol.dubbo.DubboInvoker.doInvoke(DubboInvoker.java:95) at com.alibaba.dubbo.rpc.protocol.AbstractInvoker.invoke(AbstractInvoker.java:154) at com.alibaba.dubbo.rpc.listener.ListenerInvokerWrapper.invoke(ListenerInvokerWrapper.java:77) at com.alibaba.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:75) at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:72) at com.alibaba.dubbo.rpc.protocol.dubbo.filter.FutureFilter.invoke(FutureFilter.java:54) at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:72) at com.alibaba.dubbo.rpc.filter.ConsumerContextFilter.invoke(ConsumerContextFilter.java:49) at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:72) at com.alibaba.dubbo.rpc.protocol.InvokerWrapper.invoke(InvokerWrapper.java:56) at com.alibaba.dubbo.rpc.cluster.support.FailoverClusterInvoker.doInvoke(FailoverClusterInvoker.java:78) ... 5 more
将zookeeper的地址都设置为本地
<!-- use multicast registry center to export service --> <!-- dubbo:registry address="multicast://224.5.6.7:1234"/ --> <dubbo:registry address="zookeeper://127.0.0.1:2181"/> <!-- use dubbo protocol to export service on port 20880 --> <dubbo:protocol name="dubbo" port="20880"/>
先启动provider
lihui@2018 ~ lsof -i:20880 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME java 41918 lihui 61u IPv6 0xfdabfa92d1715e4d 0t0 TCP *:20880 (LISTEN)
看看zk注册情况
✘ lihui@2018 ~ zkCli Connecting to localhost:2181 Welcome to ZooKeeper! JLine support is enabled WATCHER:: WatchedEvent state:SyncConnected type:None path:null [zk: localhost:2181(CONNECTED) 0] ls [zk: localhost:2181(CONNECTED) 1] ls / [dubbo, zookeeper] [zk: localhost:2181(CONNECTED) 2] ls /zookeeper [quota] [zk: localhost:2181(CONNECTED) 3] ls /zookeeper/quota [] [zk: localhost:2181(CONNECTED) 4] ls /zookeeper [quota] [zk: localhost:2181(CONNECTED) 5] ls /dubbo [com.maoxiaomeng.service.HelloService, com.alibaba.dubbo.demo.DemoService]
这就奇怪了,再次看看provider的执行结果
[01/04/19 02:11:50:050 CST] main INFO zookeeper.ZooKeeper: Client environment:os.name=Mac OS X [01/04/19 02:11:50:050 CST] main INFO zookeeper.ZooKeeper: Client environment:os.arch=x86_64 [01/04/19 02:11:50:050 CST] main INFO zookeeper.ZooKeeper: Client environment:os.version=10.14.4 [01/04/19 02:11:50:050 CST] main INFO zookeeper.ZooKeeper: Client environment:user.name=lihui [01/04/19 02:11:50:050 CST] main INFO zookeeper.ZooKeeper: Client environment:user.home=/Users/lihui [01/04/19 02:11:50:050 CST] main INFO zookeeper.ZooKeeper: Client environment:user.dir=/Users/lihui/caocao/dubbo/incubator-dubbo [01/04/19 02:11:50:050 CST] main INFO zookeeper.ZooKeeper: Initiating client connection, connectString=127.0.0.1:2181 sessionTimeout=60000 watcher=org.apache.curator.ConnectionState@1ff4931d [01/04/19 02:11:50:050 CST] main-SendThread(127.0.0.1:2181) INFO zookeeper.ClientCnxn: Opening socket connection to server 127.0.0.1/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error) [01/04/19 02:11:50:050 CST] main INFO zookeeper.ZookeeperRegistry: [DUBBO] Register: dubbo://0.0.7.226:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&dubbo=2.0.2&generic=false&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=42519&side=provider×tamp=1554055910026, dubbo version: , current host: 0.0.7.226 [01/04/19 02:11:50:050 CST] main-SendThread(127.0.0.1:2181) INFO zookeeper.ClientCnxn: Socket connection established to 127.0.0.1/127.0.0.1:2181, initiating session [01/04/19 02:11:50:050 CST] main-SendThread(127.0.0.1:2181) INFO zookeeper.ClientCnxn: Session establishment complete on server 127.0.0.1/127.0.0.1:2181, sessionid = 0x100081863b90013, negotiated timeout = 40000 [01/04/19 02:11:50:050 CST] main-EventThread INFO state.ConnectionStateManager: State change: CONNECTED [01/04/19 02:11:50:050 CST] main INFO zookeeper.ZookeeperRegistry: [DUBBO] Subscribe: provider://0.0.7.226:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.0.2&generic=false&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=42519&side=provider×tamp=1554055910026, dubbo version: , current host: 0.0.7.226 [01/04/19 02:11:50:050 CST] main INFO zookeeper.ZookeeperRegistry: [DUBBO] Notify urls for subscribe url provider://0.0.7.226:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.0.2&generic=false&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=42519&side=provider×tamp=1554055910026, urls: [empty://0.0.7.226:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.0.2&generic=false&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=42519&side=provider×tamp=1554055910026], dubbo version: , current host: 0.0.7.226
看这个注册的host不对,手动配置provider的host
<!-- use multicast registry center to export service --> <!-- dubbo:registry address="multicast://224.5.6.7:1234"/ --> <dubbo:registry address="zookeeper://127.0.0.1:2181"/> <!-- use dubbo protocol to export service on port 20880 --> <dubbo:protocol host="127.0.0.1" name="dubbo" port="20880"/>
还是不行,直接看下源码,错误信息
首先是current host不对
private String appendContextMessage(String msg) { return " [DUBBO] " + msg + ", dubbo version: " + Version.getVersion() + ", current host: " + NetUtils.getLocalHost(); }
直接看调用关系,getLocalHost
public static String getLocalHost() { InetAddress address = getLocalAddress(); return address == null ? LOCALHOST : address.getHostAddress(); }
接着getLocalAddress
/** * Find first valid IP from local network card * * @return first valid local IP */ public static InetAddress getLocalAddress() { if (LOCAL_ADDRESS != null) return LOCAL_ADDRESS; InetAddress localAddress = getLocalAddress0(); LOCAL_ADDRESS = localAddress; return localAddress; }
查看getLocalAddress0
private static InetAddress getLocalAddress0() { InetAddress localAddress = null; try { localAddress = InetAddress.getLocalHost(); if (isValidAddress(localAddress)) { return localAddress; } } catch (Throwable e) { logger.warn("Failed to retrieving 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 retrieving ip address, " + e.getMessage(), e); } } } } catch (Throwable e) { logger.warn("Failed to retrieving ip address, " + e.getMessage(), e); } } } } catch (Throwable e) { logger.warn("Failed to retrieving ip address, " + e.getMessage(), e); } logger.error("Could not get local host ip address, will use 127.0.0.1 instead."); return localAddress; }
注释挺多,顺便看看
/** * Returns the address of the local host. This is achieved by retrieving * the name of the host from the system, then resolving that name into * an {@code InetAddress}. * * <P>Note: The resolved address may be cached for a short period of time. * </P> * * <p>If there is a security manager, its * {@code checkConnect} method is called * with the local host name and {@code -1} * as its arguments to see if the operation is allowed. * If the operation is not allowed, an InetAddress representing * the loopback address is returned. * * @return the address of the local host. * * @exception UnknownHostException if the local host name could not * be resolved into an address. * * @see SecurityManager#checkConnect * @see java.net.InetAddress#getByName(java.lang.String) */ public static InetAddress getLocalHost() throws UnknownHostException { SecurityManager security = System.getSecurityManager(); try { String local = impl.getLocalHostName(); if (security != null) { security.checkConnect(local, -1); } if (local.equals("localhost")) { return impl.loopbackAddress(); } InetAddress ret = null; synchronized (cacheLock) { long now = System.currentTimeMillis(); if (cachedLocalHost != null) { if ((now - cacheTime) < maxCacheTime) // Less than 5s old? ret = cachedLocalHost; else cachedLocalHost = null; } // we are calling getAddressesFromNameService directly // to avoid getting localHost from cache if (ret == null) { InetAddress[] localAddrs; try { localAddrs = InetAddress.getAddressesFromNameService(local, null); } catch (UnknownHostException uhe) { // Rethrow with a more informative error message. UnknownHostException uhe2 = new UnknownHostException(local + ": " + uhe.getMessage()); uhe2.initCause(uhe); throw uhe2; } cachedLocalHost = localAddrs[0]; cacheTime = now; ret = localAddrs[0]; } } return ret; } catch (java.lang.SecurityException e) { return impl.loopbackAddress(); } }
其实从这个方法命名基本知道获取IP地址的流程
private static InetAddress[] getAddressesFromNameService(String host, InetAddress reqAddr) throws UnknownHostException { InetAddress[] addresses = null; boolean success = false; UnknownHostException ex = null; // Check whether the host is in the lookupTable. // 1) If the host isn't in the lookupTable when // checkLookupTable() is called, checkLookupTable() // would add the host in the lookupTable and // return null. So we will do the lookup. // 2) If the host is in the lookupTable when // checkLookupTable() is called, the current thread // would be blocked until the host is removed // from the lookupTable. Then this thread // should try to look up the addressCache. // i) if it found the addresses in the // addressCache, checkLookupTable() would // return the addresses. // ii) if it didn't find the addresses in the // addressCache for any reason, // it should add the host in the // lookupTable and return null so the // following code would do a lookup itself. if ((addresses = checkLookupTable(host)) == null) { try { // This is the first thread which looks up the addresses // this host or the cache entry for this host has been // expired so this thread should do the lookup. for (NameService nameService : nameServices) { try { /* * Do not put the call to lookup() inside the * constructor. if you do you will still be * allocating space when the lookup fails. */ addresses = nameService.lookupAllHostAddr(host); success = true; break; } catch (UnknownHostException uhe) { if (host.equalsIgnoreCase("localhost")) { InetAddress[] local = new InetAddress[] { impl.loopbackAddress() }; addresses = local; success = true; break; } else { addresses = unknown_array; success = false; ex = uhe; } } } // More to do? if (reqAddr != null && addresses.length > 1 && !addresses[0].equals(reqAddr)) { // Find it? int i = 1; for (; i < addresses.length; i++) { if (addresses[i].equals(reqAddr)) { break; } } // Rotate if (i < addresses.length) { InetAddress tmp, tmp2 = reqAddr; for (int j = 0; j < i; j++) { tmp = addresses[j]; addresses[j] = tmp2; tmp2 = tmp; } addresses[i] = tmp2; } } // Cache the address. cacheAddresses(host, addresses, success); if (!success && ex != null) throw ex; } finally { // Delete host from the lookupTable and notify // all threads waiting on the lookupTable monitor. updateLookupTable(host); } } return addresses; }
最终是调用了这个接口,但是我本地是没有的
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package sun.net.spi.nameservice; import java.net.InetAddress; import java.net.UnknownHostException; public interface NameService { InetAddress[] lookupAllHostAddr(String var1) throws UnknownHostException; String getHostByAddr(byte[] var1) throws UnknownHostException; }
但是根据整个流程,已经是库函数InetAddress.getLocalHost()不兼容我本地的环境,无法正确获取IP地址,不用继续看了,具体的解决方法可以查看下帖子: