springboot dubbo Address already in use 问题
项目用到了springboot和spring-devtools 用了之后,修改代码可以实现热部署。
但是dubbo在重启的时候 会提示这个错误:
com.alibaba.dubbo.rpc.RpcException: Fail to start server(url: dubbo://192.168.1.26:20880/com.zh.car.service.AgencyService?anyhost=true&application=producers&bind.ip=192.168.1.26&bind.port=20880&channel.readonly.sent=true&codec=dubbo&dubbo=2.6.0&generic=false&heartbeat=60000&interface=com.zh.car.service.AgencyService&methods=getDatagrid,select,insertSelective,getAgencyList,updateByPrimaryKeySelective,updataAgency,deleteAgency,selectOne,getDataGridByModel,selectByPrimaryKey,selectCount,addAgency&pid=28571&side=provider×tamp=1539938821823) Failed to bind NettyServer on /192.168.1.26:20880, cause: Failed to bind to: /0.0.0.0:20880
at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol.createServer(DubboProtocol.java:277) ~[dubbo-2.6.0.jar:2.6.0]
at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol.openServer(DubboProtocol.java:254) ~[dubbo-2.6.0.jar:2.6.0]
at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol.export(DubboProtocol.java:241) ~[dubbo-2.6.0.jar:2.6.0]
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper.export(ProtocolFilterWrapper.java:93) ~[dubbo-2.6.0.jar:2.6.0]
at com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper.export(ProtocolListenerWrapper.java:68) ~[dubbo-2.6.0.jar:2.6.0]
at com.alibaba.dubbo.rpc.Protocol$Adaptive.export(Protocol$Adaptive.java) ~[dubbo-2.6.0.jar:2.6.0]
at com.alibaba.dubbo.registry.integration.RegistryProtocol.doLocalExport(RegistryProtocol.java:181) ~[dubbo-2.6.0.jar:2.6.0]
com.alibaba.dubbo.rpc.RpcException: Fail to start server(url: dubbo://192.168.1.26:20880/com.zh.car.service.AgencyService?anyhost=true&application=producers&bind.ip=192.168.1.26&bind.port=20880&channel.readonly.sent=true&codec=dubbo&dubbo=2.6.0&generic=false&heartbeat=60000&interface=com.zh.car.service.AgencyService&methods=getDatagrid,select,insertSelective,getAgencyList,updateByPrimaryKeySelective,updataAgency,deleteAgency,selectOne,getDataGridByModel,selectByPrimaryKey,selectCount,addAgency&pid=28571&side=provider×tamp=1539938821823) Failed to bind NettyServer on /192.168.1.26:20880, cause: Failed to bind to: /0.0.0.0:20880
at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol.createServer(DubboProtocol.java:277) ~[dubbo-2.6.0.jar:2.6.0]
at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol.openServer(DubboProtocol.java:254) ~[dubbo-2.6.0.jar:2.6.0]
at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol.export(DubboProtocol.java:241) ~[dubbo-2.6.0.jar:2.6.0]
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper.export(ProtocolFilterWrapper.java:93) ~[dubbo-2.6.0.jar:2.6.0]
at com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper.export(ProtocolListenerWrapper.java:68) ~[dubbo-2.6.0.jar:2.6.0]
at com.alibaba.dubbo.rpc.Protocol$Adaptive.export(Protocol$Adaptive.java) ~[dubbo-2.6.0.jar:2.6.0]
at com.alibaba.dubbo.registry.integration.RegistryProtocol.doLocalExport(RegistryProtocol.java:181) ~[dubbo-2.6.0.jar:2.6.0]
原因是dubbo并没有释放端口,查看进程
如果kill -9 28571 这整个进程都会死,热部署也就无任何意义了。
目前没什么好办法来解决,不知道dubbo的文档有没有释放端口的方法,也没时间去翻了。
可以先暂时采用随机端口的方式来解决。
解决方案1
https://blog.csdn.net/leiyong0326/article/details/52260769/
解决方案2
参照上面的方案实现的代码
java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import java.util.Random;
@Component
public class DubboInitializing implements InitializingBean {
private static final Logger logger = LoggerFactory.getLogger(DubboInitializing.class);
@Override
public void afterPropertiesSet() {
//解决dubbo 重启端口未释放问题
//随机生成一个5位数的端口
//30000-60000的之间
//合法的端口范围是0-65536
int port = getRandom(30000, 60000);
System.setProperty("dubbo.protocol.port", String.valueOf(port));
logger.info("准备初始化dubbo,随机端口为:" + port);
}
/**
Java随机数有坑,需要优化,否则启动过慢
将$JAVA_HOME/jre/lib/security/Java.security内,将securerandom.source的内容改为file:/dev/./urandom即可
*
@return
/
private Integer getRandom(int min, int max) {
Random random = new Random();
return random.nextInt(max) % (max - min + 1) + min;
}
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import java.util.Random;
@Component
public class DubboInitializing implements InitializingBean {
private static final Logger logger = LoggerFactory.getLogger(DubboInitializing.class);
@Override
public void afterPropertiesSet() {
//解决dubbo 重启端口未释放问题
//随机生成一个5位数的端口
//30000-60000的之间
//合法的端口范围是0-65536
int port = getRandom(30000, 60000);
System.setProperty("dubbo.protocol.port", String.valueOf(port));
logger.info("准备初始化dubbo,随机端口为:" + port);
}
/**
Java随机数有坑,需要优化,否则启动过慢
将$JAVA_HOME/jre/lib/security/Java.security内,将securerandom.source的内容改为file:/dev/./urandom即可
*
@return
/
private Integer getRandom(int min, int max) {
Random random = new Random();
return random.nextInt(max) % (max - min + 1) + min;
}
}
经测试,以上方法会出现消费者调用错误,因为多个端口向注册中心注册,会造成多个服务生产者。
终极解决方案:
http://www.yl-blog.com/article/617.html
java
/**
Created by marker on 2017/8/21.
/
/**
@author marker
@create 2017-08-21 下午2:04
**/
import ch.qos.logback.core.net.server.ServerListener;
import com.alibaba.dubbo.registry.dubbo.DubboRegistry;
import com.alibaba.dubbo.registry.dubbo.DubboRegistryFactory;
import com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol;
import com.llcloud.order.util.SpringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
*
服务监听器
@author marker
Created by marker on 2016/12/27.
/
public class DubboServiceListener implements ServletContextListener {
/** 日志记录 /
private Logger logger = LoggerFactory.getLogger(DubboServiceListener.class);
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("初始化");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
logger.info("销毁dubbo实例中....");
DubboRegistryFactory.destroyAll();
DubboProtocol.getDubboProtocol().destroy();
logger.info("销毁dubbo服务完成!");
}
}
/**
Created by marker on 2017/8/21.
/
/**
@author marker
@create 2017-08-21 下午2:04
**/
import ch.qos.logback.core.net.server.ServerListener;
import com.alibaba.dubbo.registry.dubbo.DubboRegistry;
import com.alibaba.dubbo.registry.dubbo.DubboRegistryFactory;
import com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol;
import com.llcloud.order.util.SpringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
*
服务监听器
@author marker
Created by marker on 2016/12/27.
/
public class DubboServiceListener implements ServletContextListener {
/** 日志记录 /
private Logger logger = LoggerFactory.getLogger(DubboServiceListener.class);
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("初始化");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
logger.info("销毁dubbo实例中....");
DubboRegistryFactory.destroyAll();
DubboProtocol.getDubboProtocol().destroy();
logger.info("销毁dubbo服务完成!");
}
}