第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决

1、问题的背景

在上一篇文章中

第九天:浪迹天涯网上商城(1.0版本)--商品服务中心-基于spring cloud + spring boot + swagger 我们阐述了一个异常,我这里再重复一次。

第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决

分析:从第一处我们可以看到,langjitianya-itemservice从8700端口获取配置信息,这是没有问题的。但是获取完配置信息后,langjitianya-itemservice还是从8700端口启动langjitianya-itemservice的服务,因为8700端口已经被配置中心服务所占用,所以langjitianya-itemservice启动的时候,就抛出 Address already in use: bind 的异常。可是我们明明在application.properties配置文件中指明了server.port=50000, 为什么程序不按照我们指定的端口启动服务呢?为了解决这个问题,我查阅了大量的资料,我很沮丧,网上的那些讲解spring cloud config的博客都是千篇一律,都是抄来抄去。什么有用的价值信息也没有。哎,中国人啊,一点知识版权也没有,没有办法,我没有这个问题折腾了很久很久,最后只能慢慢的debug阅读源代码。终于解决了. 我看到网上也有人提到了这个问题,比如:

springCloudConfig client获取server时出现的问题 这篇文章描述的问题,也是我遇到的问题。

2、解决问题的思路与步骤

1、我们知道获取配置服务的地方是没有问题的。

2、就是获取完配置文件后,启动本服务时,端口号不对。那么就debug一下图片中的第二处地方 。找到

TomcatEmbeddedServletContainer这个类,在下面的地方打断点。

第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决


(1). 运行程序,我们很快就会进入到这里,我们发现这里会调用getPortsDescription方法。我们发现当程序执行到这里的时候,tomcat的port还是默认的8080。

第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决


(2).程序再往下执行,会将conector对象的port值赋值给tomcat的port值,因为此时的connector的port是8700, 所以此时的tomcat的port直接由默认值8080变成8700,那么我们在配置文件中的server.port值又去哪里了呢?从这里我们可以知道,connector里面的port值是关键,我们必须要搞清楚它的值是怎么进来的。

第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决

3、自定义tomcat配置,直接在里面将端口写死成9999, 进行debug测试。

第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决


(1) . 启动程序并debug测试, 启动后跳入的第一个断点就是这里:

第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决

我们清楚的看到此时的端口号是9999。

(2) . 程序继续进行,进入下一个断点。端口又变成了8700。那么在第一个断点调到第二个断点的这段时间,肯定中间执行了setPort这个方法。

第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决

(3). 在setPort这个方法上面打个断点。


(4) . 启动程序并debug如下:

程序启动后进入的第一个断点是如下:

第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决


再往下,进入我们的第二个断点,因为我们这里手动设置了端口号是9999,所以这里很清楚的可以看到:

第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决


再往下执行,进入下一个断点, 我们发现又执行了这个方法,这个时候端口号8700把9999覆盖了。

第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决


一直到了这里,我似乎明白了什么。我们知道TomcatEmbeddedServletContainerFactory这个对象是用来构造EmbeddedServletContainer对象的,如下所示:

第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决

那么我们可以自定义实现这个方式。

(5). 自定义实现

第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决

在产生EmbeddedServletContainer之前,强制调用setPort方法。并且TomcatConfig修改如下:

第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决

启动程序debug验证:

第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决

发现在这里通过server.port读取到的值是8700,可是我明明配置的是50000。一直到这里,我似乎明白了一个道理。因为我们在bootstart.properties配置我们的服务配置中心的地址,程序发起了请注册中心的请求,凡是地址肯定有端口号,spring cloud config 将这个端口号也作为了自己的启动端口号,就导致了异常的发生。因为bootstart.properties配置是有最高优先级的,虽然我们在application.properties中配置了参数的值server.port=50000, 后面配置的都不起作用。

(6). 修改配置

application.properties中的server.port=50000, 修改为tomcat.server.port=50000。程序修改为:

第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决

终于,我们的端口号正确了,一直到这里,我们的问题终于圆满的解决了。可以看到如下的日志:

第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决

4、访问注册中心服务http://localhost:8000/,看我们的商品服务是否已经注册在上面了。

第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决

5、访问swagger对服务进行测试。http://localhost:50000/swagger-ui.html

第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决

测试get方法:

第十天:浪迹天涯网上商城(1.0版本)--商品服务中心-spring cloud client的bug发现与解决

4、代码托管

项目的代码我已经托管在github上面, 地址为:langjitianya-itemservice