一、访问页面报502错误
常见问题:
- 最大可能是应用启动报错,没有启动起来
- 应用虽然起来了,但是由于遇到运行时error,比如:内存不够,cpu占满等,导致不能响应
- 应用默认端口被修改了,导致nginx找不到服务。可以通过telnet ip port方式查看下8080端口是否启用了。我这次遇到的就是这个问题,其他开发不小心修改了port,但是没有通知前端,用的都还是默认端口。导致无法找到服务。
二、网络带宽和网卡网卡打满后,后面的请求数据包会被抛弃吗?
网络带宽是啥? 你在网络运营商购买的带宽。一般家用10M,50M带宽
网卡带宽是啥? 电脑设备或者服务器上,用来网络数据接收和发送
百兆网卡的峰值传送速度是100Mb/s=12.5MB/s,千兆网卡的峰值1000Mb/s=125MB/s。带宽也限制了数据传输。所以,数据最终传输速度取决于两者的最小那个。所以,基本上网络带宽比网卡带宽更容易被打满。所以,对于一个物理机上面创建多个虚拟机应用,就很容易打满带宽。比如docker之类的应用。
三、带宽和流量的区别?
做个通俗的比喻:带宽其实就是水管里水的流速,而流量就是流出的水的总量
比如做个计算,10Mb带宽,一个月最大流量是多少?
10Mb = 1.25MB/s,1个月总流量:1.25 * 60 * 60 * 24 * 30 / 1024 = 3164GB,也就是十兆带宽,一个月不停地用,最多也就3164GB。对于一个大型网站来说,每天也就100GB流量,每个页面100KB,也就100万pv/d。对于大型网站动不动就上亿pv的请求,这个流量是远远不够的,小网站倒是足够了。
四、redis的性能瓶颈,以及redis为啥是单线程?
redis单线程比多线程性能高的原因?
假设单核cpu情况下,多线程执行命令会发生线程切换,用户态到内核态切换,这种操作属于重量级操作,消耗资源。大概每次切换需要消耗2000ns,一次指令执行只要0.38ns。所以,单线程执行把cpu时间花在刀刃上,比切换保存上下文来得实在。
redis的性能瓶颈在哪?
首先基于内存了,磁盘IO就不是瓶颈了。那么瓶颈就在网络IO上,而影响到网络IO的因素:带宽(包括:网卡带宽和网络带宽),客户端到服务端的物理距离。第一个带宽容易理解,如果请求数据或者响应数据很大,在高并发场景下,很有可能数据包把带宽占满了,请求进不来了。第二个距离可能会让人丈二和尚摸不着头脑,不明觉厉。其实距离是和一个数据包的RTT(往还时间)有关。比如:客户端在北京,服务端在上海。距离1300km,一次RTT=13ms,那么1s内客户端只能执行80次左右的命令,因为数据包在tcp连接传输过程中,无法在发送新的请求包。
总结:RTT与tcp窗口大小对带宽利用率有很大影响
参考文章:
RTT与tcp窗口对带宽的影响
TCP速率与窗口,带宽,RTT之间的关系
比如:到某个服务器一个RTT需要30ms,如果窗口大小为1。那么1s内最多发送33个命令。每个命令如果是1500B,这个带宽只能到50KB/s=400Kbits/s,简直不能忍。这个时候需要增大窗口大小,如果窗口大小增大到10000个,那么1s就能发送330000个包,算下这个带宽已经可以到83Mbits,是不是很完美?只要增大窗口,理论上可以提高带宽利用率到100%,不幸的是窗口大小不受人为控制,它是发送和接收两端商量的结果。
五、java只能实现图片下载,不能实现图片预览
发现在HttpServletResponse返回的时候,设置了如下:
response.setContentType("image/jpeg");
response.setHeader("Content-Disposition", "attachment;filename=" + filename);
需要把attachment改为inline,如下:
response.setContentType("image/jpeg");
response.setHeader("Content-Disposition", "inline;filename=" + filename);
在浏览器中访问图片路径,就可以愉快的预览了。反过来一样,如果不想预览只想下载,那么就改为attachment。
六、zookeeper安装,报:xxx/zookeeper_server.pid: No such file or directory
我的解决:
1、在zookeeper的解压目录下,使用命令:bin/zkServer.sh start。或者去到bin目录下,执行:./zkServer.sh start
我之前报错执行的命令:sh bin/zkServer.sh start。如果有大神知道bin/zkServer.sh start 和 sh bin/zkServer.sh start,有啥不同,希望不吝赐教。本人对linux脚本不熟。
网上其他人的解决方案:
1、dataDir=/tmp/zookeeper,路径配置了空格。
2、还有说dataDir=/xxx/xxx,目录没有执行权限,需要赋予权限的。
3、dataDir=/xxx/xxx配置多个的,导致zk不知道用哪个。
等等,我没验证过,只是个搬运工。
七、mvn打包失败,报错:ArrayIndexOutOfBoundsException 9370 数组越界异常。
背景:我们应用没有做任何升级操作,公司打包平台也没有任何升级操作。但是平台突然就mvn打包失败,并且只有我们应用有问题,其他应用打包不受影响。我们应用打包总是报数组越界异常,异常如下:
诡异的是,本地打包成功。最开始怀疑,打包平台的mvn版本和我本地版本不一致。上去一看,确实不一致。平台3.3.9,我本地3.5.4。为了在本地复现,我把本地mvn版本降低到3.3.9,果然复现了问题。
为了找到根源问题,我们对应用的pom所有依赖,通过暴力法一个一个移除尝试,发现有个依赖去掉就打包成功了。我们的依赖如下:
<dependency>
<groupId>io.github.classgraph</groupId>
<artifactId>classgraph</artifactId>
<version>LATEST</version>
</dependency>
发现坑的位置了<version>LATEST</version>,表示使用最新版本。然后去看了下classgraph包最近更新的时间,果然是最近刚更新的和我们打包失败的时间吻合。然后,修改LATEST为上一个稳定版本,重新在平台打包,顺利打包成功。所以,LATEST(4.8.66)版本可能和mvn3.3.9有冲突,触发了bug,降低版本到4.8.65解决问题。
解决方案:
1、升级打包平台的mvn版本。但是这个升级影响很大,有风险。
2、固定pom版本依赖,不要有这种LATEST写法。这样的话,对第三方依赖风险增大。
八、MultipartFile的transferTo保存文件时,文件内容为空,并且也没报错
解决方案:把文件相对路径改为绝对路径
代码示例:把
String currentFileName = System.currentTimeMillis() + ".tmp";
currentUploadFile = new File(currentFileName);
file.transferTo(currentUploadFile);
修改为:
String currentFileName = System.currentTimeMillis() + ".tmp";
currentUploadFile = new File("/Users/xxx/Documents/" + currentFileName);
file.transferTo(currentUploadFile);
思考:为啥会这样呢?StandardMultipartHttpServletRequest的transferTo如下:
@Override
public void transferTo(File dest) throws IOException, IllegalStateException {
this.part.write(dest.getPath());
if (dest.isAbsolute() && !dest.exists()) {
// Servlet 3.0 Part.write is not guaranteed to support absolute file paths:
// may translate the given path to a relative location within a temp dir
// (e.g. on Jetty whereas Tomcat and Undertow detect absolute paths).
// At least we offloaded the file from memory storage; it'll get deleted
// from the temp dir eventually in any case. And for our user's purposes,
// we can manually copy it to the requested location as a fallback.
FileCopyUtils.copy(this.part.getInputStream(), new FileOutputStream(dest));
}
}
可以发现,不管dest是不是绝对路径,dest.exists()必是true,里面的方法一定执行不到。那么绝对路径与否,竟然可以决定能不能写入文件内容,着实奇怪。向上看,可以看下方法 this.part.write(dest.getPath()):
@Override
public void write(String fileName) throws IOException {
File file = new File(fileName);
if (!file.isAbsolute()) {
file = new File(location, fileName);
}
try {
fileItem.write(file);
} catch (Exception e) {
throw new IOException(e);
}
}
问题找到了,如果不是绝对路径,那么会new File(location, fileName),注意这个location是web容器的path。数据内容被写在这个文件了。这样看来,transferTo那里完全不用传File了啊,只需要传fileName不就行了嘛、反正write这里还是会new File的,一定也不是你传进来的那个file实例了。
至于为啥transferTo的参数要用File,可能是为了兼容if (dest.isAbsolute() && !dest.exists()) 这个判断逻辑吧。这个特殊处理逻辑里面,确实会用到我们传进去的file实例。
第一次使用,真的是被坑死了!!!竟然不会用我们传递进去的File实例!
九、@ResponseBody和response.getWriter().write()的区别?
网上搜到的基本都是说他们两没啥区别。其实有一个重要区别是,@ResponseBody返回的是json格式的字符串,write就是原始字符串。比如:我们测试一个echoController,发现输出的字符串,在@ResponseBody下全部都默认添加了双引号。write直接是输入的原始字符串,没有经过任何改造。
原文地址:@ResponseBody作用在返回类型为String的方法时的坑
解决方案:
StringHttpMessageConverter一定要放前面,让String类型优先匹配。