面试有两点:1、技术过硬。2、能说会道。
如果自己的技术还过的去,但是表述的不尽人意,其实是吃了很大亏的,下面我来介绍一个大神的面试过程:
面试官:请介绍一下你的电商项目。
大神:该商城是一个综合性的B2C电商平台,类似于京东商城,主要针对广大消费者。
在整个项目中,我们采用的是nginx+tomcat
来部署的(面试官可能会问nginx是谁来部署的?如何部署的?nginx的执行流程、优点),nginx一方面做加载静态资源的服务器
,另一方面来做反向代理
和负载均衡
。因为该项目需要在多个环境中运行,我们利用了nginx的反向代理解决了不同环境同系统访问地址不统一带来的问题。
因为整个项目实现的功能较多,所以采用分布式的架构设计
,整个项目包括后台管理系统
、商城首页系统
、搜索系统
、商品详情页系统
、登录系统
、购物车系统
、订单系统
等,这样做的好处是使每个功能模块独立出来
,降低
了各系统之间的耦合度
,增删一个功能不会影响其他功能模块。
如何解决了浏览器访问当前页面去加载后台系统数据出现的跨域问题
答:因为项目是采用分布式架构设计的,各模块之间是相互独立的,而各模块的访问路径又是不同的,所以当跨域请求
数据的时候会遇到跨域受限的问题。比如当用户首次访问该网站首页
时,首页页面会异步请求后台管理系统
加载商品的类目,这是就会出现跨域受限
的问题,以前开发时,如果在本模块内,我们是通过ajax异步请求数据
的,但ajax不支持跨域
,所以用ajax无法解决跨域请求数据的问题。
最后我们使用的是jsonp
来解决这个问题的。jsonp通过script标签的src可以跨域请求的特性
,加载资源,将加载的资源(通过一个方法名将数据进行包裹)当做是js脚本
解析,定义一个回调函数
(是怎么实现的?),获取传入的数据。我们使用jsonp是因为jsonp的兼容性比较好
,并且在请求完毕后可以通过callback的方式回传结果
。但jsonp有一个缺点是只支持get请求
而不支持post等其他类型的http请求。
其他系统该如何调用后台系统的数据?
答:我们可以发送http请求
来访问后台数据,我们想到的是使用HttpClient(Dubbo)
来解决此问题,因为HttpClient可以使用java代码模拟浏览器发送Http请求
。
向外抛出一个接口,执行过程是:
1、创建HttpClient对象;
2、构建请求对象post、get请求;
3、如果有参数,就去构造请求参数,get使用URIBuilder去构造请求参数,post构建表单实体,把表单实体放入到post请求对象中。
4、执行请求,并且接受响应;
5、处理响应结果;
6、释放连接。无论执行方法是否成功,都必须释放连接。
为什么HttpClient实现认为是线程安全
的?
每次连接发起Http请求的时候都会重新建立连接(经历3次握手),用完就会关闭连接(4次挥手),这样会消耗很多时间,所有我们采用了连接池
。如果不采用连接池,每次连接都会打开一个端口
,在大并发的情况下系统的端口资源很快就会被用完,导致无法建立新的连接。
get方法如何传递参数?
答:定义URIBuilder对象,在URIBuilder里设置参数,以key和value,都是string类型的,然后将URIBuilder放到URI中,然后将URI传给Httpget请求。
Post方法如果传输数据?
答:模拟表单提交,将数据封装到list集合中,然后将集合数据放入构造的表单实体中,在将表单实体请求放到httppost对象中。
问题背景:
像项目中首页的大广告和商品类目这些不需要经常修改
的数据,如果用户每次刷新页面的时候都要去数据库中查询,这样会浪费资
源和增加数据库的压力
。
解决思路:
所以我们想当把这些数据添加到一个缓存
中,用户去访问的时候,先去缓存中命中
,如果命中失败,再去数据库中查询,然后把查询到的数据添加到缓存中。
具体方案:
目前比较主流的缓存技术有Redis
和Memcached
,单纯从缓存命中的角度来说,Memcached要高一些,可Redis和Memcache的差距其实并不大,但Redis提供的功能更加强大一些,读写速度也很快
。所以我们选用了Redis来缓存数据。
redis把数据以key—value的形式缓存到内存中,并提供了多种数据存储类型(String、Hash、list、Set、SortedSet),还自身提供了持久化功能(2种:RDB、AOF)
,还可以把数据备份到磁盘中(redis的SAVE命令用于创建当前 redis数据库的备份),防止redis宕机时的数据丢失。(会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步
)。我们使用的是spring与redis的java的客户端jedis进行整合,可以利用jedis做分片式集群
,解决了redis内存受限
的问题。
单点登录系统
之前实现的登录和注册是在同一个tomcat内部完成,而现在系统架构是每一个系统都是由一个团队进行维护,每个系统都是单独部署运行一个单独的tomcat,所以,不能将用户的登录信息保存到session中(多个tomcat的session是不能共享的,即session共享问题),所以我们需要一个单独的系统来维护用户的登录信息。我们是这样做的,用户去登录页面登录,发送含有用户信息的请求且会携带cookie去服务端数据库查询是否有该用户,如果没有提示用户,如果有就把用户信息保存到redis中,并生成一个token保存到cookie中。
后台管理系统
在后台管理系统中采用了Maven的多模块化
的管理,其中采用了水平切分
的方式(垂直与水平划分的区别:垂直:功能模块明确,层次不够清晰,代码重用性差。水平:层次清晰,代码重用性高,易于独立维护。),将各层分层开发,这样做的好处是代码重用性高
,层次清晰
,易于独立维护
。系统内部接口调用采用Httpclient(Dubbo)
,接口提供端采用RESTful风格
的接口定义(一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件);系统之间的通知机制采用MQ
的方式,使用ActiveMQ
的实现,使用了ActiveMQ的消息订阅模式
的消息机;部署方面,采用了nginx+tomcat的模式,其中nginx的作用一方面是做反向代理、负载均衡、另一方面是做图片等静态资源的服务器。
我负责的模块
在此项目中我主要负责后台管理模块,主要实现商品管理和商品规格参数管理,对商品和商品规格进行CRUD操作。在实现前台调用后台数据时,为了实现系统间的调用,便使用了HttpClient技术来实现此功能,在后台提供了需要调用的接口。(HttpClient介绍、工作原理、优缺点)。如果在后台对商品进行操作,为了使前台数据与后台数据实现同步,我们使用了ActiveMQ消息队列机制实现商品同步功能(ActiveMQ介绍、工作原理、优缺点)。
在此项目中,我还参与了购物车模块的开发。在开发这个模块时候,我们考虑了会员在未登录和登录两种情况下把商品加入购物车,后台如何该保存商品信息。
在用户商品详情页点击加入购物车的时候,我们用了登录拦截器
来判断用户是否登录。如果没有登录,将商品信息保存到cookie
中,当用户登录后,再把商品持久到数据库中;但是考虑到cookie储存大小(4k)
的问题,还有当cookie储存的数据越多就会影响响应速度,我们决定使用redis来缓存
用户在未登录状态下的商品信息(redis介绍、原理、优缺点),在redis中设置缓存生存时间(如何做到的?),如果用户在规定时间内没有登录,数据便会自动删除。如果用户在规定时间内登录了,便会通过ActiveMQ消息队列
机制将数据同步到数据库中。
不管你的简历和工作经验是真是假,至少要做到能自圆其说就行。
参考链接:https://blog.csdn.net/qq_38584262/article/details/80707593