项目—万宝商城

疑惑

  • springMVC返回给前端的数据到底是什么格式? text\html 与 application\json有什么本质的区别??

杂七杂八

  • 版本号规则

REST与RESTful

  • REST是什么
    Representational State Transfer(表述性状态转移)
    Web服务的一种架构风格
    轻量级(耦合性高的是重量级)、跨平台、跨语言

  • RESTful是什么
    遵循REST风格的Web服务
    REST式的Web服务是一种ROA(面向资源的架构)

  • ROA与SOA
    ROA:面向资源的架构
    SOA:面向服务的架构
    区别:[SOA]REST与SOA两种架构的异同比较

  • REST架构的主要原则
    网络上的所有事务都可被抽象为资源
    每个资源都有一个唯一的资源标志符(Resource Identifier)
    同一资源具有多种表现形式(json、xml等,根据请求头返回对应格式)
    所有操作都是无状态

  • URI 与URL
    1.URI是抽象的定义,不管用什么方法表示,只要能定位一个资源,就叫URI,本来设想的的使用两种方法定位:1,URL,用地址定位;2,URN 用名称定位。
    2.举个例子:去村子找个具体的人(URI),如果用地址:某村多少号房子第几间房的主人 就是URL, 如果用身份证号+名字 去找就是URN了。
    3.结果就是目前WEB上就URL流行开了,平常见的URI 基本都是URL。=>URL就是URI、URI不一定是URL

  • 资源的操作
    1.GET:获取一个资源
    2.POST:创建一个新的资源
    3.PUT:修改一个资源的状态(body无法传递参数)
    4.DELETE:删除一个资源(body无法传递参数)
    (主要是这四种,对应CRUD)
    注意:默认情况下PUT、DELETE请求体中无法传递参数,因为tomcat对这两个请求不会解析表单 => 需在web.xml中配置过滤器
    RESTful风格的资源操作
    在这里插入图片描述

  • REST接口设计原则

  • REST响应设计原则

  • http响应状态码
    在这里插入图片描述
    重点关注:200、400、500; 以及201、204、404

SVN

  • 原理

    SVN是集中式; Git是分布式!!
    分布式版本管理仅仅是增加了本地库这个概念,其余的概念与集中管理并无区别。 即SVN只能直接提交到中央仓库;而Git可以提交到本地仓库,本地仓库可以再与其他仓库合并

  • SVN协议
    http => 客户端浏览器都可访问
    https =>客户端浏览器都可访问,更安全
    svn => svn自带协议,仅客户端可访问

  • SVN资源仓库
    三个目录:trunk(主干)、branches(分支)、tag(标签)
    最佳使用方法=>
    在这里插入图片描述

  • 冲突解决
    解决冲突的核心思想:为了避免冲突,要在最新的版本之上修改(也就是说修改之前先更新),再提交。
    如果没有更新就已经修改,然后发现冲突 =>应该放弃自己的修改,把本地文件更新到最新版本,在最新版本基础之上修改,并且提交。

开发流程与架构

  • 电商行业技术特点
  • 电商基础概念
  • 架构

    分布式架构存在的问题 => 系统间的调用变得复杂 => 服务注册中心解决

Maven

  • maven导入依赖的原则
    在这里插入图片描述

Nginx

  • 开发阶段的环境
    开发环境 => 开发人员的电脑
    测试环境 => 测试人员使用的环境
    生产环境 => 发布上线的环境
    预发布环境 => (部分企业有)介于测试环境于生产环境之间,数据与生产环境一致
  • 两类服务器
    web服务器:Apache、Nginx、IIS
    web应用服务器:tomcat、resin、jetty
    普遍采用:Nginx+tomcat
    区分:web服务器不能解析jsp等页面,只能处理js、css、html等静态资源。
    并发:web服务器的并发能力远高于web应用服务器。
  • nginx 特点与作用
    高性能的http服务器; 支持反向daili,可实现负载均衡
  • daili
    正向daili:用户 -> daili-> csdn=> 即为客户端daili(用户知道访问的结果来自哪里,比如这里的csdn)
    反向daili:用户 -> nginx ->tomcat => 即为服务端daili(用户不知道访问的结果来自哪里,因为nginx背后有一堆tomcat服务器)
  • server_name的匹配规则
    先遍历所有配置的server_name,如果找到了(与请求中的域名相同),则执行对应的server,如果没有找到,则默认执行第一个server

Redis

  • 缓存需求
    经常访问的数据缓存到内部才能数据库中,查询时加快速度
    缓存添加在哪里,前台系统? 还是 后台系统? — 都加。
    每个团队都应该为自己的系统功能负责任,保证其性能。
    (redis服务通常位于service层)
  • 常用缓存技术
    redis、memcached
    memcached:缓存命中率稍高;功能比较少;多线程实现
    redis:缓存命中率稍低(不过差距不大);功能强大;单线程实现
  • redis的多数据库
    redis默认有16个数据库,对外以从0递增的数字命名;
    数据库名不能修改;
    默认选择0号数据库;
    不支持为每个数据库设置访问密码(官方认为数据安全应由系统环境保证)
    多个数据库间不是完全隔离的 => flushall清空所有数据库中数据(flushdb单个)
  • redis常用命令
    keys:获取键名列表
    exists:判断一个键是否存在
    del:删除一个键值对
    type:获得键值的数据类型
    help:help+命令 查询该命令使用方法
  • redis字符串数据类型
    可以存储任何形式的字符串,包括二进制数据 ;
    一个字符串类型最多512M(如果需要存储的数据大于512M,说明架构不对)
    常用命令
    set key value
    get key
    incr key:自增数据 => decr
    incrby key increment:增加指定数据 => decrby
    append key value:向末尾追加
    strlen key:获取字符串长度
    mset key value [key value …]:一次设置多条数据
    mget key1 [key2 …]:一个查询多条数据
  • redis生存时间
    生存时间到期后缓存的数据会被销毁
    expire key seconds:设置数据的缓存时间
    ttl key:还差多长时间到期(-1:永久有效; -2:已经过期)
    persist key :清除生存时间,不会被删除(修改值也会清除过期时间)
  • redis分片式集群
    两种集群方式 => 分片式集群、官方提供的集群方式;

    分片式集群示意图如上(Jedis根据key的hash值决定存储到哪个节点),jedis支持分片式集群
  • 原则
    缓存逻辑不能影响原有业务逻辑的执行

Solr

  • 概述
    本项目使用solr本质上就是将mysql中经常被查询的数据导入solr,由solr完成查询功能并返回结果数据。solr其实就是一个nosql数据库,以RESTful API的方式提供搜索服务。虽然mysql也能提供搜索与查询,但是全部直接使用mysql会加重数据库负载,而且也不如solr高效,因为选用了solr单独提供搜索服务!!
  • 更多参考
    什么是Solr,它能为我们解决什么问题,怎么用?

消息队列(RabbitMQ)

  • MQ
    消息队列是应用程序和应用程序之间的通信方法(基于应用层协议AMQP)
  • RabbitMQ的队列

    hello模式:一个生产者对应一个队列和一个消费者
    work模式:一个生产者对应一个队列和多个消费者(一条消息只能发送给一个消费者)
    订阅模式:生产者将消息发送到交换机,每个消费者有一个与交换机绑定的队列,从交换机获取数据(一条消息能发送给所有消费者)。消息发送到没有队列绑定的交换机时,消息将丢失
    路由模式:在订阅模式的基础上,消息队列绑定到交换机中特定类型的消息(根据key绑定),只获取需要的消息而不是所有消息
    通配符模式:在路由模式的基础上,消息队列绑定交换机时key可以使用通配符
  • 消息的确认方式
    自动确认 => 只要消息从队列中获取,无论消费者获取到消息后是否成功消息,都认为是消息已经成功消费。
    手动确认 => 消费者从队列中获取消息后,服务器会将该消息标记为不可用状态,等待消费者的反馈,如果消费者一直没有反馈,那么该消息将一直处于不可用状态。
  • 持久化交换机和队列
    持久化:将交换机或队列的数据保存到磁盘,服务器宕机或重启之后依然存在。
    非持久化:将交换机或队列的数据保存到内存,服务器宕机或重启之后将不存在。
    非持久化的性能高于持久化。
    如何选择持久化?非持久化? – 看需求。
  • 队列和交换机的绑定
    1.在配置文件中将队列和交换机完成绑定
        => 绑定关系如果发生变化,需要修改配置文件,并且服务需要重启
    2.可以在管理界面中完成绑定
         =>管理更灵活,更容易对绑定关系的权限管理,流程管理

Dubbo

  • 系统间服务调用的方式
    1.浏览器直接访问:浏览器发起请求,通过ajax或者jsonp方式访问
    缺点:只能访问对外网公开的服务

    2.httpclient:系统与系统之间通过Httpclient发起http请求来请求数据
    优点:浏览器可通过中间业务系统间接访问内网中的服务
    缺点:http是短连接

    3.RPC
    优点:长连接!!
  • 背景(后端架构的演进)
  • 服务治理
  • dubbo的系统架构

    调用关系:
    1.服务容器负责启动,加载,运行服务提供者。
    2.服务提供者在启动时,向注册中心注册自己提供的服务。
    3.服务消费者在启动时,向注册中心订阅自己所需的服务。
    4.注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
    5.服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
    6.服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

MySQL相关

  • 商品数据库表
    a.价格要以最小单位分存储 => 为了避免小数计算带来的问题
    b.将商品描述和商品的基本数据分离?
       1商品描述的数据量大,会导致数据文件变大,影响查询速度。
       2后期会对商品描述数据的存储做改造,所以需要将描述数据分离
       3.其实,经常修改和经常不修改的数据需要做分离,不应该存储在同一个表
  • 富文本编辑器中的内容如何保存
    富文本编辑器中的内容其实是html,数据库中保存这个html即可
  • 设置主键id为null
    数据存入数据库时,为了防止恶意提交的带有id的数据 =>出于安全考虑,Controller中强制设置id为null,通过数据库自增获得Id
  • 事务
    必须同时保存的数据写在同一个事务中(同一个service或者嵌套的service)
  • 如何保存图片
    通常图片不是保存在数据库中,而是保存在文件中,数据库中只是保存图片的路径!!
  • 如何保存产品规格参数
    使用模板的思路=> 需要有2张表:
    1.模板表,需要和商品类目关联
    2.规格参数数据表,需要和商品关联
    模板结构如下:

    最终规格参数数据如下:

    将上面所示的json结构以字符串的形式存储在目标表和规格参数表中!
  • 订单-商品关联表中对商品数据冗余存储的原因(易错)

    => 此处并不是为了减少表间关联,加快查询; 而是为了保存这个交易快照,防止完成交易后商家修改商品信息,用户之后查询已购买商品的时显示的信息与实际交易的信息不符(如购买商品时商家承诺有优惠,购买之后商家删除了优惠信息而不给与优惠,从未顾客无法维权。通过数据冗余即可查询交易时的真实情况)
  • 多字段的联合索引
    注意索引字段的顺序,查询语句中只有使用了联合索引的第一个字段时,索引才会有效,否则查询不会使用索引。
  • 读写分离
    我们一般应用对数据库而言都是“读多写少”,也就说对数据库读取数据的压力比较大,有一个思路就是说采用数据库集群的方案:
        其中一个是主库,负责写入数据,我们称之为:写库;
        其它都是从库,负责读取数据,我们称之为:读库;
    那么,对我们的要求是:
        读库和写库的数据一致;
        写数据必须写到写库;
        读数据必须到读库;
  • mysql主从复制

    存在的问题:从库拷贝主库的日志并执行,这个过程会有一定时延 => 如何解决?不能从从根本上解决,只有在架构设计的时候考虑这个问题,只要它不影响业务、数据就可以接受
    注:上面图示只有一个主库一个从库,实际上更多的是一主(写)多从(读)

前端相关

  • 提交数据的序列化
    对提交数据进行序列化 => 防止轻易被看出来提交的数据是什么(经常看见地址栏中的乱码就是序列化的结果)
  • .html结尾的伪静态页面
    服务端做特殊过滤,匹配以*.html结尾的请求 => 伪静态页面,有利于SEO(搜索引擎对静态页面打分较高)
  • jsonp解决跨域问题
    发生跨域的情况 => 协议、域名、端口只要有一个不匹配就是跨域!
    script标签的src可以跨域请求资源,但是ajax请求不可以跨域请求=>能否借助script标签的src进行加载数据? – 可以的。
    jsonp解决跨域请求原理
       1.jsonp通过script标签的src可以跨域请求的特性,加载资源(会被当做js解析)
       2.后端把json资源包裹在一个回调函数的参数中(返回整个字符串)
          
       3.前端定义回调函数,解析返回的数据时会调用这个回调函数获取json数据
          
       优化 => 将回调函数名传递到服务端,根据前端的回调函数构造返回的字符串
    jquery的jsonp就是jquery使用上述原理,进行了一层封装 => 请求时juqery自动加上回调函数的名(后台因此需要提取出回调函数名这个参数,并在返回数据时加上回调函数名)
  • 商品类目侧边栏的实现方法
    从后端以json数据格式读取类目树结构(后端构造类目树结构比较麻烦,代码见ItemCatService)
  • js代码压缩
    经常看到整个js文件是一行,这是经过压缩后的代码; 压缩的目的一是减小文件大小,一是防止代码被轻易看懂

后端相关

  • 上传文件/图片校验
    对上传的文件通常要做校验,主要包括以下方面:
    1.类型,通过文件的后缀名
    2.大小
    3.上传文件的内容做校验 =>通过获取文件的宽和高来判断是否是图片
    注1:此项目使用了上传文件的依赖 commons-fileupload;另外使用了文件上传解析器CommonsMultipartResolver,它是spring的类
    注2:上传图片使用了flash,部分浏览器可能已经不支持,这部分目前只能使用sougou、360浏览器

  • 访问上传后的图片
    之前的上传后,通过tomcat访问图片。
    没有真实的项目是通过tomcat访问静态资源。 为什么?
    Tomcat是应用服务器,作用:处理动态请求。
    Nginx、Apache是web服务器,作用:处理静态资源、反向daili功能。
    Web服务器的并发能力远高于应用服务器。
    =>解决方法:图上上传到服务器的文件后,返回图片对应的静态资源链接,然后在前端根据这个返回的图片链接回显图片

  • spring父子容器
    (这部分内容很重要,回看day03视频15-16)
    Spring容器 – 父容器
    SpringMVC容器 – 子容器
    父子容器的关系:
    1.子容器能够访问父容器的资源(bean)=> 示例:Controller(springMVC容器中)可以注入Service(spring容器中)
    2.父容器不能访问子容器的资源(bean)
    @Value注入值:仅在当前的所在容器中获取值,然后注入
    如何在子容器中获取父容器中注入的值?=> 见PicUploadController中获取REPOSITORY_PATH的方法!

  • 日志的书写
    1.方法的入参处需要将参数打印出
    2.业务执行的状态发生变化时,需要打印(执行成功/失败)
    3.异常处需要打印

  • 如何获取商品数据
    如果不使用Mybatis,商品的数据从何而来? – 来源于Mysql数据库
    获取数据的途径:
    1.从JDBC获取
    a) 优点
       i. 直接,获取的途径较短,简单
    b) 缺点
       i. 对后台系统团队而言,数据不安全(只要开放的账户是只读的账户即可)
       ii. 前端系统团队需要有学习的成本,才能使用数据库
       iii. 依赖、耦合度太高,后端团队将数据库结构修改,那么其他团队必须跟着修改逻辑,才能使用
       iv. 直接走数据库查询,无法添加缓存逻辑
    2.通过后台系统接口获取=>面向服务
    前台系统不是使用Mybatis或者JDBC直接从数据库查询数据,而是调用后台其他系统的服务提供的数据
    a) 优点
       i. 耦合度降低,后端团队只要保证接口的返回数据格式不变化,其他团队就无需升级
       ii. 数据安全
       iii. 前端团队无需了解学习后端团队的底层数据库结构
       iv. 后端团队可以在接口处添加缓存逻辑
    b) 缺点
       i. 获取的路径较长(不是真正的缺点)

  • 中文乱码问题
    SpringMVC中产生的响应有2类ModelAndView返回数据响应
    返回的数据响应本来是一个对象,但是经过springMVC处理后变成了字符串 => 这一任务由springMVC的消息转化器完成
    乱码的原因:默认的消息转换器使用的编码不支持中文 => springMVC配置文件中解决!! (其实也可以在@RequestMapping中通过produces设置!)

  • 首页广告的实现 => 内容管理
                                                          方案一
    1、 在后台系统中创建一张表,存储大广告位的广告数据
    2、 在后台系统中对该表进行CRUD
    3、 后台系统对外提供接口服务
    4、 前台系统调用后台系统的提供的接口服务,即可获取到数据
    5、 前台系统获取到数据后,封装成前端所需要的数据结构,功能即可实现
                                                          方案二
    1、 将首页显示的广告都抽象的看作是内容
    2、 在后台系统中创建一张内容表(描述每一条广告的具体信息)
    3、 创建一个内容分类表用于区分内容的分类
    4、 后台系统对内容表以及分类表进行CRUD
    5、 对外提供接口服务
    6、 前端系统通过接口获取数据,进行封装,即可实现

    对于方案一,如果广告非常多,只能每类广告分别创建一张表,非常麻烦,应该对首页的所有广告统一管理 => 采用方案二,即内容管理系统!

  • 创建索引的常用规则
    1.经常在查询的where字句中出现的字段
    2.需要排序的字段

  • 前端传递json对象如何接收
    方法1.后端使用一个pojo对象接收所有数据
    方法2.后端将json对象中的各字段分开接收 => 更安全,防止json对象被修改,导致后端修改了本来不应该修改的字段

  • 访问后端提供的接口服务的方式
                                方式1.js访问
         a) 有跨域 – jsonp解决
         b) 无跨域 – ajax解决
                                方式2.Java代码访问
        a) Httpclient

  • 单例对象中如何使用多例对象
    不能通过注入获取(这样只能是单例) => 单例类应该实现BeanFactoryAware接口,需要使用多例对象时通过beanFactory从spring容器中获取新创建的对象

  • jsp文件中java代码、jsp代码、js代码的执行顺序
    java —> jsp —>js 前两个在后端执行,渲染出html页面然后返回给前端,之后才是js在浏览器端解析

  • 关于字符串拼接的效率
    A.“abc”+“cba”
    B.StringBuffer
    C.StringBuilder
    jdk1.5以下 => C>B>A
    jdk1.5以上 => C=A>B(A在低层也是按照C处理)
    StringBuffer只在有线程安全问题的前提下才会使用

  • 前后台系统数据同步
    问题:后台系统中将商品修改,前台系统没有进行数据的同步,导致前端系统不能够实时显示最新的数据。
    解决:在前台系统中开发一个接口 => 后台系统更新数据时调用前台系统的接口,删除前台系统的缓存

    上述方法存在的问题 => 要更新前台系统缓存必须修改后台代码,系统间耦合严重 => 应该使用消息队列(MQ)

  • sevice中的异常应该捕获还是抛出?
    事务的回滚是根据是否抛出异常来进行的,如果捕获了异常(则无法检测抛出的异常),那么出现异常时将不能对事务进行回滚 => 通常有事务的service中都是抛出异常而非捕获异常

  • 单点登录系统
    什么是单点登录(sso)?
    在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统(一个网站可能包含多个子系统,这些子系统部署在不同的tomcat中,但是只需登录一次即可访问所有子系统,无需访问每个子系统时分别进行登录)
    为什么需要单点登录系统
    之前实现的登录和注册是在同一个tomcat内部完成,我们现在的系统架构是每一个系统都是由一个团队进行维护,每个系统都是单独部署运行一个单独的tomcat,所以,不能将用户的登录信息保存到session中(多个tomcat的session是不能共享的=> 其实可以共享,不过是通过session复制到所有tomcat中,效率很低),所以我们需要一个单独的系统来维护用户的登录信息。
    补充:sssion是由tomcat创建并保存的,无法禁用;对于分布式部署的多个子系统,通常不再使用session
    传统登录流程

  • 单点登录流程

    与传统的登陆方式相比本质上没有变化,标志信息都需要保存到cookie中,只是前者在浏览器端保存sessionId后者保存token;单点登录使用redis代替了tomcat保存用户信息

  • 静态资源的处理方式
    方案1:每个子系统的webapp下分别存放该系统需要使用的静态资源(js、css、iamage等) => 简单,但是对于多个系统共享的静态资源会重复加载;而且这样是通过tomcat访问的静态资源,而tomcat不善于处理静态资源
    方案2:将共享的静态资源统一放到一个专门的域名指向的地方,由nginx处理静态资源,所以子系统访问同一个地方的共静态资源 => 避免重复加载;避免携带一些无用的cookie;提高静态资源处理能力

  • SpringMVC的规定:在SpringMVC中如果请求以html结尾,那么就不会返回JSON数据,而是直接返回406状态(springMVC默认的是text格式)
    => 解决办法:多条路进入SpringMVC(比如url-pattern同时匹配:*.html和/service/* )

  • 表单数据的校验
    前端js代码对表单数据进行的校验比较初级,如果用户直接修改提交的请求,则前端校验规则完成没有用上 => 应该在服务端再次进行数据校验(在springMVC中校验数据,校验通过才进行数据库操作)

  • 私密字段的处理
    返回浏览器端用户信息的时候,password等私密字段最好不要返回,可以在pojo中给相应字段加上@JsonIgnore注解,对象序列化成json字符串时便会忽略该字段

  • cookie、session、token
    cookie:cookie是浏览器端存储的一组数据,不同的网站对应的cookie分开存放(因而cookie不能跨域),访问某个网站时,浏览器会将该网站对应的cookie写入请求头的cookie字段(包括sessionID以及cookie中的其他k-v信息)
    session:session是服务器端存储的数据,常用于存储用户信息(不管用户是否登录),一个session由一个sessionID标志它。用户首次访问网站(尚未登录)时,tomcat会生成一个session并将sessionID写入浏览器的cookie中,用户后续登录时可以将登录用户的信息写入session方便后续使用。
    cookie+session:由上可知,cookie+session可用于跟踪会话,关键点就是sessionID。tomcat将sessionID写入浏览器端cookie中,服务端根据请求中的sessionID识别用户。由于tomcat中的session不能多个服务端共享,给单点登录造成麻烦 => 改用token
    token:为了方便多个服务端共享用户信息,通常使用redis缓存登录用户的信息(而不再是tomcat生成session并存储在单个服务端),redis中一个用户的信息由一个token标志。由此可见token类似于sessionID,都是用于识别用户
    token与sessionID的区别个人见解
        1.sessionID由tomcat生成;token由后端程序员生成
        2.sessionID由tomcat写入浏览器的cookie中;token可以由后端程序员写入浏览器cookie中,也可以直接返回给前端,由前端程序员选择保存策略(如存在localStorage中等)
        3.即使没有登录的客户端也会生成并写入sessionID;token只针对登录用户
        4.只要没有禁用cookie,每次请求都会通过cookie字段携带sessionID;如果token保存在cookie中,自然会出现在请求头的cookie字段。如果token不是保存在cookie中,用户的身份验证则需要通过将token写入请求url或者参数中

  • 如何生成订单编号
    时间戳+自增id(用redis维护)
    用户id+时间戳
    用户id+店铺id+时间戳

  • 登录拦截器

  • 区分响应状态码与业务状态码
    响应状态码是在报文头中,后端程序员不手动设置也会有默认的响应状态码
    业务状态码是在报文体中,由前后端程序员约定,后端程序员手动设置在返回的信息中

  • ThreadLocal
    可通过ThreadLocal将对象存储在当前线程,需要的时候再取出

  • 购物车的业务流程

  • 如何实现读写分离
                      应用层解决

                      中间件解决

    目前基本都是采用应用层解决方案

项目发布

  • 流程
    SVN打tag => 各项目打包(只需打包war项目,jar会自动包含在其中) => 数据库脚本及初始数据 =>编写发布文档 => 实施发布
  • 部署架构
    在这里插入图片描述
  • 配置tomcat集群
    上图中前台系统共三个tomcat,需要使用nginx进行负载均衡,由nginx决定访问交给哪个tomcat处理(tomcat负载均衡使用轮询算法)
  • 一台机器上运行多个tomcat
    需要修改tomcat的配置文件中的部分端口,避免冲突 =>具体百度
  • 双机主备
    keepalived+nginx实现双机主备

    1.客户端通过虚拟IP访问(与域名绑定),主nginx机器正常时,虚拟IP绑定在主nginx对应的机器上;
    2.主nginx异常时,虚拟IP绑定到nginx备份机器上;
    3.nginx备份机器通过keepalived的心跳检测感知主nginx机器是否异常
  • 双主热备
    keepalived+nginx实现

    1.图示中两个nginx同时使用,不区分主机和备份机;
    2.每台机器各一个虚拟IP(即一台机器两个IP)
    3.将一个域名同时绑定到两个虚拟IP
    4.客户端通过域名访问时,由DNS系统通过轮询决定走哪个虚拟IP,从而决定了使用哪个nginx
    5.如果一个nginx宕机,它的虚拟IP绑定到另一个nignx即可
  • 负载均衡
    使用lvs代替nginx的负载均衡功能(性能更好)
  • 压力测试
    原理 => 多线程模拟并发
    工具:Jmeter

实战笔记—功能完善

  • 如何处理高并发问题
    如何解决高并发问题
    1、HTML静态化
    2、图片服务器分离
    3、数据库集群和库表散列
    4、缓存
    5、镜像
    6、负载均衡(终极方法)
  • GET请求的URL中有时候加上随机数的作用
    中url后面接了个随机数,是为了欺骗浏览器或daili服务器用的;某些daili服务器会无视 no-cache 之类的标识,对响应结果进行强行缓存;而当url请求不改变的时候,有时候会导致浏览器不向服务器发送请求,而直接取调用缓存中的数据。加上随机数就是欺骗浏览器url改变了,要每次向服务器发送请求而不去调用缓存中的数据;
  • 热加载与热部署(注意二者区别)
    参考:Eclipse实现热部署和热启动
  • ajax,前端收到的json是对象还是字符串
    1.前后端数据使用http协议,传递的报文都是字符串,因此本质上说是字符串
    2.对于解决跨域的jsonp,由于收到字符串数据后底层会直接使用回调函数进行解析,因此返回给程序员的数据是json对象而不是字符串
    3.前端收到json字符串通常需要JSON.parse(data)解析成json对象; 如果不想手动解析,指定dataType字段为json即可自动解析为json对象
  • 什么时候才有响应状态码

实际开发中的一些tip

  • 商品价格在数据库中最好使用分为单位
  • 对于图片,不是直接将图片存储在数据库,而是仅仅将图片的路径存储在数据库
  • 为什么要将商品描述和商品的基本数据分离?
    1.商品描述的数据量大,会导致数据文件变大,影响查询速度。
    2.后期会对商品描述数据的存储做改造,所以需要将描述数据分离
    3.注:对表进行优化时,可以将经常修改的数据和不修改的数据分离(拆为不同的表)
  • 插入数据时,后端代码将自增的字段设置为null
    强制设置id为null,通过数据库自增获得 => 从而避免前端提交的请求中包含自增字段值时导致错误(此时插入的是提交的值而不是自增后的值)
  • 使用.html结尾的伪静态页面
    服务端做特殊过滤,匹配以*.html结尾的请求 => 伪静态页面,有利于SEO(搜索引擎对静态页面打分比较高)

    参考:伪静态

项目中较难的点

面试时可以从中挑选作答

  • 跨域
  • 内容管理
    将整个界面看到的所有信息抽象成内容,统一放到一张表中(不易想到) <=> 而不是界面中不同板块的东西分别建立其特定的表格
    具体如下
    1.将首页显示的广告(应该是所有东西,不仅是大广告)都抽象的看作是内容
    2.在后台系统中创建一张内容表
    3.创建一个内容分类表用于区分内容的分类
    4.后台系统对内容表以及分类表进行CRUD
    5.对外提供接口服务
    6.前端系统通过接口获取数据,进行封装,即可实现
  • PUT、DELETE无法在请求体中传递参数
    解决方案:在web.xml中配置过滤器
    详见:解决Ajax中Restful风格PUT和DELETE请求传递参数无效
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值