WEB服务器的实现包含哪些内容

WEB服务器的实现包含哪些内容

本文根据自己的经验,整理实现一个WEB服务器可能包含的内容,每一项都点到为止,不做过多展开。以下顺序无重要程度区分,皆按实际场景考虑是否需要。

路由

WEB服务器的路由,本质上是根据HTTP请求携带信息,决定执行何种逻辑。

最简单的if-else语句,也是一种路由方式:

// 路由依据通常使用请求method和url
if (method === 'GET' && url === '/robots.txt') {
    // do something
}
else {
    // do other things
}

不同平台不同框架,路由定义的方式会有差异,但本质相同:通过HTTP请求所携带的信息,决定不同的执行逻辑。拿Node.js下Express举例:

const express = require('express');
const app = express();

// GET:/home will match funcA
app.get('/home', funcA);

// POST:/home will match funcB
app.post('/home', funcB);

// GET:/params/a or GET:/params/b will be match funcC
app.get('/params/:id', funcC); 

// GET:/regexp/list-1.html or GET:/regexp/list-2.html will be match funcD
app.get('/regexp/list-[0-9].html', funcD); 

以上代码就是Node.js + Express的一种简单路由定义方式,但在真实场景下不推荐这样一行一行添加路由的写法,尽量做到按类型、业务拆分定义,也可以抽成独立于语言框架的一种配置项。

日志

日志用来记录跟请求相关的信息,经常作为数据统计,问题定位等用途,可分为以下几种:

  • 访问日志

访问日志是最常见的基础日志,记录每一个request的部分请求信息和响应信息,通常会记录的信息有请求者IP、请求方式、请求URL、请求主体大小、请求Host、请求处理时长、响应状态码、响应主体大小等,这些日志信息可用做访问统计、问题定位等

  • 业务日志

业务日志的内容,根据业务需要输出,可用于业务统计、追踪、问题定位等

  • 错误日志

请求处理过程中发生错误、异常,只要能被捕捉,都应该输出到错误日志中,并且包含尽量多的上下文信息,方便开发人员定位BUG

会话保持

HTTP是一种无状态协议,但在某些业务场景下,需要保持会话信息,即请求需要跟踪并唯一标识请求者。

现代WEB服务器都能实现会话保持功能,实现原理并不难,保证每一个请求都包含本次处理所需要的所有信息上下文即可。实现原理:

  • 初次请求时,服务器为本次请求分配一个唯一ID(SessionId)以及与之对应的会话信息(Session),然后在响应中包含该ID
  • 客户端收到响应时,存储所获得的ID(Cookie),以后每一个请求都带上该ID
  • 后续请求时,服务器取出请求所携带的ID以及根据ID获取对应的会话信息,即完成了会话追踪

这个ID的承载体通常是一个HTTP头部,在浏览器中分别为Set-Cookie、Cookie,前者在响应时使用,后者在请求时使用。同时浏览器针对Set-Cookie还有很多其它特性,如:过期时间,作用范围(域名、路径),协议(HTTP、HTTPS)等

有一个常见的面试题:Cookie与Session的区别。以下是我的理解:

  • Cookie是网站在浏览器中存储数据的一种方式,服务器通过Set-Cookie头部在浏览器中存储信息,浏览器通过Cookie请求头部携带所存储的信息给服务器,被存储的这份信息称为Cookie
  • Session可以指一次请求所对应的会话,是一种抽象概念,也可以指会话所对应的信息上下文本身,存储在服务器端

Session通常是与SessionId一一对应,SessionId的传输依靠Set-Cookie/Cookie头部,SessionId对应的数据可以存放在内存或数据库中,前者难以跨进程共享故不推荐,后者因为读写高频经常选用Redis。

缓存

系统不同的部分或层级,获取数据的资源开销和速度经常会有显著差异,为追求更高的性能与更快的速度,于是就有了缓存这个概念,在很多应用场景下,使用缓存都可以显著提升系统整体性能。

跟HTTP相关的缓存,常出现的地方有:

  • 客户端

客户端,通常也就是浏览器,会根据一系列HTTP缓存规则去进行资源缓存,当资源命中缓存时,其获取速度是最快的,具体缓存策略参考HTTP缓存策略

  • 中间代理

请求在客户端没有命中缓存时,会向服务器发送请求,但有可能经过不同的HTTP代理,有些HTTP代理实现了缓存功能,甚至有些专门用作缓存的HTTP代理。缓存代理在缓存未过期的情况下,不会去真实请求服务器资源,而是使用本地命中的缓存响应客户端,用于提升资源获取速度,同时减少网络负载

  • 反向代理

反向代理,是现代WEB服务器架构中常见的一个名词,代理真实服务器与客户端进行通信。在反向代理服务器上通常会有缓存功能,减少真实服务器的负载,提供更高性能、更快速的资源访问能力

版本控制

版本控制,在这是指API的版本控制,一旦生产环境投入使用,在后续的版本迭代过程中,相同接口如果要修改,改变输入或输出。由于依赖服务器的客户端难以保持同步更新,新接口部署时还需同时保持旧接口可用,可以有两种方式:

  • 在同一接口中支持新、旧两种使用场景

如果接口的性质、输入、输出都没有变化,只是内部实现的更新,则此方式可取。但如果因输入、输出变化,也在原有的老接口中揉合进新接口的功能代码,会导致代码难以阅读和维护,不推荐

  • 重新定义一个接口,用以支持新场景

重新定义接口,支持新场景,原有接口不改变,此方式即接口的版本控制,在约束和规范下定义并实现新的接口,旧接口确认不再使用或不再兼容之后,从系统中移除。

接口的版本控制虽非必需,但不表示不重要的,能够在系统设计之初考虑进去最好不过,具体如何实现版本控制,即如何确定约束和规范则因人而异,没有必然正确的标准。

访问控制

如果某些敏感资源,只有特定的访问者可以访问,就需要做访问控制,比如:内部系统不允许外部调用,用户资源需要登陆后才可以获取,管理系统需要管理员登陆才可访问,屏蔽某些已知的恶意IP访问等

针对以上场景,可能采用的方式有:

  • 黑白名单

允许或屏蔽特定用户访问,该方式比较僵硬,但在某些情况下却非常高效和便捷

  • 验证码

有各种各样的验证码形式,但主要目的都是为了区别对待机器与人

  • 用户登陆

依靠用户登陆,识别用户身份,控制访问权限

单点调用频率限制

单点调用频率限制也是访问控制的一部分,有特殊性,也经常被忽视。单点调用频率限制,最终常会转变成识别机器与人,因为真人的正常操作往往难以达到调用频率限制门槛。

需要考虑单点调用频率限制的因素:

  • 资源成本较高

需要消耗过多计算机资源(CPU、IO、磁盘等)、过多带宽、额外成本(短信验证码,其它收费服务等)等,API如果具有以上特性,那么为避免因非法使用而导致系统成本浪费,在技术上就需要尽可能的去防范

  • 维持公平性

在某些特定业务场景下,如限量抢购、投票等场景,为了维持公平性,可能需要加以限制单点调用频率

统一响应格式

统一响应格式主要指业务API的返回值,HTTP的标准状态码是一种方式,但并不推荐在业务场景中直接使用。现代服务器API大多使用JSON作为数据交换格式,如果再套用HTTP标准状态码,会使得前端逻辑处理异常繁琐。

例如根据文章ID获取文章,当文章ID对应的文章不存在,如果采用HTTP标准状态码,此时响应码应为404, 原因短语为Not Found,因为接口本身设计成JSON的返回值,返回404状态码会导致前端无法进入正常处理逻辑,需要额外逻辑去理解响应,并友好提示用户。

统一API的响应格式,可使用以下简单结构:

response = {
    code: number, // 0 表示成功,其它表示失败
    msg: string,  // 描述信息,code非0时表示错误描述
    result: var    // 成功时的响应数据,用于业务处理
};

所有能捕捉的异常,都可以包装成上面的结构返回,Content-Type: application/json。

对等

服务器实例部署需要保持对等,便于水平扩展,可分为两种:单机多进程、多机多进程。单机多进程,解决对单机的依赖(本地文件、本机网络资源、本机独有服务等),就可以转为多机多进程部署。

负载均衡

如果服务器实例实现了对等部署,也就是同一个服务,有多个实例在运行,通常在前面会存在一个负载均衡服务器,它会考虑到多个不同服务实例的负载情况,给它们带去不同数量的请求。可把负载均衡理解成另一个层次的路由。

反向代理

反向代理服务器是隐藏真实服务器相关信息,代理真实服务器与客户端打交道,同时可以集成其它功能的角色。出色代表:Nginx,性能稳定可靠,包含大部分非业务相关特性,如缓存、访问日志、负载均衡、路由转发等。

总结

一个现代WEB服务器,不一定包含上述所有内容,同时也不限于上述内容。上述每一项,都是根据自己的理解,简单描述一遍,不涉及具体实现与技术细节,因为每一项内容展开,都有太多太多内容。后续针对其中某些内容,再单独写文章进行更详细和深入的介绍。

博客原文

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值