项目中遇到的问题
1.在使用es的时候,对存储在对象数组里面的对象进行检索时出现了数据不匹配的问题?
原因:es使用扁平化存储,相同的字段存储在一起,导致查询的时候无关的值进行了匹配
解决:在建立mapping的时候将对象数组的类型转换为netsted,这个类型是一种特殊的对象object数据类型(specialised version of the object datatype ),允许对象数组彼此独立地进行索引和查询。
2.跨域问题
原因:跨域问题是由于ajax对浏览器同源策略的一种限制,通常出现在前后端分离的项目中,主要导致的原因有前后端请求url的
①协议不一致
②域名或ip不一致
③端口不一致
解决办法:
①httpclirnt
②@cronsoct注解
③gateway网关配置解决
④nginx解决
location / { add_header Access-Control-Allow-Origin *;add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';if ($request_method = 'OPTIONS') {return 204;
}
proxy_pass http://192.168.12.1:8081;
}
参数说明
Access-Control-Allow-Origin
服务器默认是不被允许跨域的。给Nginx服务器配置Access-Control-Allow-Origin *
后,表示服务器可以接受所有的请求源(Origin),即接受所有跨域的请求。
Access-Control-Allow-Headers
是为了防止出现以下错误:
Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.
这个错误表示当前请求Content-Type的值不被支持。其实是我们发起了"application/json"的类型请求导致的。这里涉及到一个概念:预检请求(preflight request),请看下面"预检请求"的介绍。
Access-Control-Allow-Methods
是为了防止出现以下错误:
Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.
给OPTIONS 添加 204的返回
是为了处理在发送POST请求时Nginx依然拒绝访问的错误,发送"预检请求"时,需要用到方法 OPTIONS ,所以服务器需要允许该方法。
⑤jsonp
3.缓存问题
在处理缓存问题时,由于好多接口查询出来的数据需要用到缓存,不能每个接口都添加与业务无关非核心的代码,于是使用注解+aop实现了分布式缓存和分布式锁.解决了以下问题:
①减缓了数据库的压力
②高并发请求下,对一个热点数据进行查询,可能会导致热点数据,顿时失效,使所有的请求达到数据库,造成数据库宕机,采用了redission实现分布式锁解决也就是最经典的那个缓存击穿的问题
③避免了缓存穿透,在数据库以及缓存都没有的时候,通过反射创建对象,往redis里面缓存一个空对象,并设置时间
④为了防止缓存雪崩,一方面使用了分布式锁,另一方面在添加缓存的时候給缓存设置了随机时间
具体步骤:
①模仿@translation创建一个注解,并在里面添加属性
②创建一个切面,并交由ioc容器管理
③定制环绕通知,以加了注解的方法为连接点
④方法体里面,通过joinpoint获取方法,并获取方法上注解以及注解里面的参数
⑤准备key从缓存里面查询看是否查询到,使用反射动态的创建对象返回
⑥查询到:直接返回,查询不到,准备key,通过redission上锁,尝试获取锁,如果获取不到锁则等待并自旋,如果
获取到锁则从数据库查询
⑦数据库存在:添加到redis,并设置随机过期时间防止雪崩,数据库不存在,通过反射动态的创建对象,储存空对象
并设置过期时间在5s之内
⑧解锁
4.并发注册的问题
在高并发测试的时候发现,同一时刻采用相同的手机号进行注册,会导致相同的手机号会在数据库出现好几个
解决办法:
在注册发送短信之前先从reids里面获取手机号是否存在,如果存在则禁止注册,如果不存在则存往redis一份再走注册流程
5.在网关中将用户信息保存到了header当中传递給下一个微服务导致下一个微服务用不了header里面的用户信息
如上图:因为微服务之间并没有传递头文件,所以我们可以定义一个拦截器,每次微服务调用之前都先检查下头文件,将请求的头文件中的用户信息再放入到header中,再调用其他微服务即可。
解决:
package com.atguigu.gmall.common.interceptor;import javax.servlet.http.HttpServletRequest;@Component
public class FeignInterceptor implements RequestInterceptor {public void apply(RequestTemplate requestTemplate){ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();requestTemplate.header("userTempId", request.getHeader("userTempId"));requestTemplate.header("userId", request.getHeader("userId"));}
}