IPV4中TCP内核参数

      参照debian系统,查看的tcp相关配置 # 全连接队列满了,新来的连接发送rst, 1表示开启 net.ipv4.tcp_abort_on_overflow = 0 # 接受缓冲区1/2^n用来接受缓冲,换句话来说,接收窗口不表示接受buffer的大小 net.ipv4.tcp_adv_win_scale = 1 # 拥塞算法 net.ipv4.tcp_allowed_congestion_control = reno cubic net.ipv4.tcp_app_win = 31 # 自动开启crok选项 net.ipv4.tcp_autocorking = 1 net.ipv4.tcp_available_congestion_control = reno cubic net.ipv4.tcp_available_ulp = net.ipv4.tcp_base_mss = 1024 net.ipv4.tcp_challenge_ack_limit = 1000 net.ipv4.tcp_comp_sack_delay_ns = 1000000 net.ipv4.tcp_comp_sack_nr = 44 net.ipv4.tcp_congestion_control = cubic net.ipv4.tcp_dsack = 1 net.ipv4.tcp_early_demux =… Continue reading IPV4中TCP内核参数

Published
Categorized as 网络 Tagged

Cookie、Session、Token、JWT、OAuth2区别

什么是认证(Authentication) 通俗地讲就是验证当前用户的身份,证明“你是你自己”(比如:你每天上下班打卡,都需要通过指纹打卡,当你的指纹和系统里录入的指纹相匹配时,就打卡成功) 互联网中的认证: 用户名密码登录 邮箱发送登录链接 手机号接收验证码 只要你能收到邮箱/验证码,就默认你是账号的主人 什么是授权(Authorization) 用户授予第三方应用访问该用户某些资源的权限 你在安装手机应用的时候,APP 会询问是否允许授予权限(访问相册、地理位置等权限) 你在访问微信小程序时,当登录时,小程序会询问是否允许授予权限(获取昵称、头像、地区、性别等个人信息) 实现授权的方式有:cookie、session、token、OAuth 什么是凭证(Credentials) 实现认证和授权的前提是需要一种媒介(证书) 来标记访问者的身份 在战国时期,商鞅变法,发明了照身帖。照身帖由官府发放,是一块打磨光滑细密的竹板,上面刻有持有人的头像和籍贯信息。国人必须持有,如若没有就被认为是黑户,或者间谍之类的。 在现实生活中,每个人都会有一张专属的居民身份证,是用于证明持有人身份的一种法定证件。通过身份证,我们可以办理手机卡/银行卡/个人贷款/交通出行等等,这就是认证的凭证。 在互联网应用中,一般网站(如掘金)会有两种模式,游客模式和登录模式。游客模式下,可以正常浏览网站上面的文章,一旦想要点赞/收藏/分享文章,就需要登录或者注册账号。当用户登录成功后,服务器会给该用户使用的浏览器颁发一个令牌(token),这个令牌用来表明你的身份,每次浏览器发送请求时会带上这个令牌,就可以使用游客模式下无法使用的功能。 什么是 Cookie HTTP 是无状态的协议(对于事务处理没有记忆能力,每次客户端和服务端会话完成时,服务端不会保存任何会话信息):每个请求都是完全独立的,服务端无法确认当前访问者的身份信息,无法分辨上一次的请求发送者和这一次的发送者是不是同一个人。所以服务器与浏览器为了进行会话跟踪(知道是谁在访问我),就必须主动的去维护一个状态,这个状态用于告知服务端前后两个请求是否来自同一浏览器。而这个状态需要通过 cookie 或者 session 去实现。 cookie 存储在客户端: cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。 cookie 是不可跨域的: 每个 cookie 都会绑定单一的域名,无法在别的域名下获取使用,一级域名和二级域名之间是允许共享使用的(靠的是 domain)。 cookie 重要的属性 属性 说明 name=value 键值对,设置 Cookie 的名称及相对应的值,都必须是字符串类型 – 如果值为 Unicode 字符,需要为字符编码。 – 如果值为二进制数据,则需要使用 BASE64 编码。 domain 指定… Continue reading Cookie、Session、Token、JWT、OAuth2区别

高并发下秒杀商品

前言 高并发下如何设计秒杀系统?这是一个高频面试题。这个问题看似简单,但是里面的水很深,它考查的是高并发场景下,从前端到后端多方面的知识。 秒杀一般出现在商城的促销活动中,指定了一定数量(比如:10个)的商品(比如:手机),以极低的价格(比如:0.1元),让大量用户参与活动,但只有极少数用户能够购买成功。这类活动商家绝大部分是不赚钱的,说白了是找个噱头宣传自己。 虽说秒杀只是一个促销活动,但对技术要求不低。下面给大家总结一下设计秒杀系统需要注意的9个细节。 1 瞬时高并发 一般在秒杀时间点(比如:12点)前几分钟,用户并发量才真正突增,达到秒杀时间点时,并发量会达到顶峰。 但由于这类活动是大量用户抢少量商品的场景,必定会出现狼多肉少的情况,所以其实绝大部分用户秒杀会失败,只有极少部分用户能够成功。 正常情况下,大部分用户会收到商品已经抢完的提醒,收到该提醒后,他们大概率不会在那个活动页面停留了,如此一来,用户并发量又会急剧下降。所以这个峰值持续的时间其实是非常短的,这样就会出现瞬时高并发的情况,下面用一张图直观的感受一下流量的变化: 像这种瞬时高并发的场景,传统的系统很难应对,我们需要设计一套全新的系统。可以从以下几个方面入手: 2. 页面静态化 活动页面是用户流量的第一入口,所以是并发量最大的地方。 如果这些流量都能直接访问服务端,恐怕服务端会因为承受不住这么大的压力,而直接挂掉。 活动页面绝大多数内容是固定的,比如:商品名称、商品描述、图片等。为了减少不必要的服务端请求,通常情况下,会对活动页面做静态化处理。用户浏览商品等常规操作,并不会请求到服务端。只有到了秒杀时间点,并且用户主动点了秒杀按钮才允许访问服务端。 这样能过滤大部分无效请求。 但只做页面静态化还不够,因为用户分布在全国各地,有些人在北京,有些人在成都,有些人在深圳,地域相差很远,网速各不相同。 如何才能让用户最快访问到活动页面呢? 这就需要使用CDN,它的全称是Content Delivery Network,即内容分发网络。 使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。 3 秒杀按钮 大部分用户怕错过秒杀时间点,一般会提前进入活动页面。此时看到的秒杀按钮是置灰,不可点击的。只有到了秒杀时间点那一时刻,秒杀按钮才会自动点亮,变成可点击的。 但此时很多用户已经迫不及待了,通过不停刷新页面,争取在第一时间看到秒杀按钮的点亮。 从前面得知,该活动页面是静态的。那么我们在静态页面中如何控制秒杀按钮,只在秒杀时间点时才点亮呢? 没错,使用js文件控制。 为了性能考虑,一般会将css、js和图片等静态资源文件提前缓存到CDN上,让用户能够就近访问秒杀页面。 看到这里,有些聪明的小伙伴,可能会问:CDN上的js文件是如何更新的? 秒杀开始之前,js标志为false,还有另外一个随机参数。当秒杀开始的时候系统会生成一个新的js文件,此时标志为true,并且随机参数生成一个新值,然后同步给CDN。由于有了这个随机参数,CDN不会缓存数据,每次都能从CDN中获取最新的js代码。此外,前端还可以加一个定时器,控制比如:10秒之内,只允许发起一次请求。如果用户点击了一次秒杀按钮,则在10秒之内置灰,不允许再次点击,等到过了时间限制,又允许重新点击该按钮。 4 读多写少 在秒杀的过程中,系统一般会先查一下库存是否足够,如果足够才允许下单,写数据库。如果不够,则直接返回该商品已经抢完。 由于大量用户抢少量商品,只有极少部分用户能够抢成功,所以绝大部分用户在秒杀时,库存其实是不足的,系统会直接返回该商品已经抢完。 这是非常典型的:读多写少 的场景。 如果有数十万的请求过来,同时通过数据库查缓存是否足够,此时数据库可能会挂掉。因为数据库的连接资源非常有限,比如:mysql,无法同时支持这么多的连接。 而应该改用缓存,比如:redis。 即便用了redis,也需要部署多个节点。 5 缓存问题 通常情况下,我们需要在redis中保存商品信息,里面包含:商品id、商品名称、规格属性、库存等信息,同时数据库中也要有相关信息,毕竟缓存并不完全可靠。 用户在点击秒杀按钮,请求秒杀接口的过程中,需要传入的商品id参数,然后服务端需要校验该商品是否合法。 大致流程如下图所示: 根据商品id,先从缓存中查询商品,如果商品存在,则参与秒杀。如果不存在,则需要从数据库中查询商品,如果存在,则将商品信息放入缓存,然后参与秒杀。如果商品不存在,则直接提示失败。 这个过程表面上看起来是OK的,但是如果深入分析一下会发现一些问题。 5.1 缓存击穿 比如商品A第一次秒杀时,缓存中是没有数据的,但数据库中有。虽说上面有如果从数据库中查到数据,则放入缓存的逻辑。 然而,在高并发下,同一时刻会有大量的请求,都在秒杀同一件商品,这些请求同时去查缓存中没有数据,然后又同时访问数据库。结果悲剧了,数据库可能扛不住压力,直接挂掉。 如何解决这个问题呢? 这就需要加锁,最好使用分布式锁。 当然,针对这种情况,最好在项目启动之前,先把缓存进行预热。即事先把所有的商品,同步到缓存中,这样商品基本都能直接从缓存中获取到,就不会出现缓存击穿的问题了。 是不是上面加锁这一步可以不需要了?… Continue reading 高并发下秒杀商品

OAuth2 四种授权

1 OAuth 2.0 定义了四种授权方式 密码模式(resource owner password credentials) 授权码模式(authorization code) 简化模式(implicit) 客户端模式(client credentials) 1.1 密码模式 这种模式是最不推荐的,因为 client 可能存了用户密码 这种模式主要用来做遗留项目升级为 oauth2 的适配方案 当然如果 client 是自家的应用,也是可以 支持 refresh token 一般在内部系统中使用,调用者是以用户为单位 用户向客户端提供自己的用户名和密码,向 “服务商提供商” 换取 access_token 。 1.2 授权码模式 这种模式算是正宗的 oauth2 的授权模式 设计了 auth code,通过这个 code 再获取 token 支持 refresh token 功能最完整、流程最严密的授权模式,通常使用在公网的开放平台中 适用于有自己的服务器的应用,它是一个一次性的临时凭证,用来换取 access_token 和 refresh_token。 一旦换取成功,code 立即作废,不能再使用第二次。 用户请求网站,如:www.baidu.com… Continue reading OAuth2 四种授权

Linux 高性能 获取时间

基础 常用时间函数 从The Linux Programming Interface 上看,获取时间最常用的函数是 gettimeofday,常见的中间件也是用该函数么? 1 2 3 #include <sys/time.h> int gettimeofday(struct timeval *tv, struct timezone *tz); Returns 0 on success, or –1 on error Redis 扫了下redis的命令,发现redis有个time command. 调用该command能够返回当前服务器的时间戳,从redis源码 )上看,redis也是调用了gettimeofday获取当前的时间 1 2 3 4 5 6 7 8 9 10 void timeCommand(client *c) { struct timeval tv; gettimeofday(&tv,NULL); addReplyArrayLen(c,2); addReplyBulkLongLong(c,tv.tv_sec); addReplyBulkLongLong(c,tv.tv_usec); }… Continue reading Linux 高性能 获取时间

MySQL Nested Loop Join

Nested Loop Join分为 Index Nested Loop JOIN 和 Block Nested Loop Join两种 INJ全称Index Nested Loop JOIN   将 “驱动表/外部表” 的结果集作为循环基础数据,然后循环该结果集,每次获取一条数据作为下一个表的过滤条件查询数据,然后合并结果,获取结果集返回给客户端。Nested-Loop一次只将一行传入内层循环, 所以外层循环(的结果集)有多少行, 内层循环便要执行多少次,效率非常差。 一. 被驱动表有可用索引的情况: 如果内层循环(被驱动表)利用到了索引,可以视为一种新的算法Index Nested_Loop JOIN,简称为  INJ 。 示例(t1有100条记录,t2有1000条记录): 1. 执行select * from t1,查出表 t1 的所有数据,这里有 100 行; 2. 循环遍历这 100 行数据: 2.1 从每一行 R 取出字段 a 的值 $R.a; 2.2 执行select * from t2 where a=$R.a;需要检查t2中利用到了索引 2.3 把返回的结果和… Continue reading MySQL Nested Loop Join

认认真真地聊聊中断

本来想写内核如何接收一个网络包这个过程,但发现把整个过程捋顺了,还是很难的。 推导整个过程的起点是中断,包括硬中断和软中断。   而这个过程要是讲清楚吧,感觉在整个网络包接收原理的大流程中有点喧宾夺主。但要是一笔带过吧,那对于这块有困惑的人就很难受,一切的起点没整明白在心里总是个疙瘩。   所以,单拎出来一个主题中断,给大家把这个问题搞明白了,之后讲内核收包时直接引过来就好了,不想看的直接过,想看的就可以有篇前置文章详细了解,美滋滋。   另外,整个操作系统就是一个中断驱动的死循环,操作系统原理如果用一行代码解释,下面这样再合适不过了。 while(true) { doNothing();} 其他所有事情都是由操作系统提前注册的中断机制和其对应的中断处理函数完成,我们点击一下鼠标,敲击一下键盘,执行一个程序,都是用中断的方式来通知操作系统帮我们处理这些事件,当没有任何需要操作系统处理的事件时,它就乖乖停在死循环里不出来。   所以,中断非常重要,它也是理解整个操作系统的根基。掌握它,不亏!   那我们开始吧。 1. 五花八门的中断分类 关于中断的分类,教科书上和网上有很多”标准”答案了,如果你用搜索引擎去寻找答案,可能会找出很多不一样的分类结果。   所以我打算直接在 Intel 手册上找个最官方的标准答案。   在 Intel 手册 “Volume 1 Chapter 6.4 Interrupts and Exception” 给出。 翻译过来就是,中断可以分为中断和异常,异常又可以分为故障、陷阱、中止。   第一句话有点奇怪,啥叫中断分为中断和异常呢?   你看好多文章的时候也是这么写的,不知道你有没有曾疑惑过。但其实原文的意思准确说是,CPU 提供了两种中断程序执行的机制,中断和异常。第一个中断是个动词,第二个中断才是真正的机制种类。   好吧,我感觉原文也挺奇怪的,但人家就这么叫,没辙。接下来我只需要翻译一下就好了,再夹杂点自己的解读。   An interrupt is an asynchronous event that is typically triggered by an… Continue reading 认认真真地聊聊中断

MySQL MMR

MMR全程Multi-Range Read,5.6新特性 当表很大的时候,使用二级索引进行范围的读取行回表导致磁盘的随机访问。 原理: 先查询满足条件的索引元组,然后按照数据行ID进行排序,对排序后的元组回表检索数据行 使用场景: 可以基于InnoDB和MyISAM引擎进行优化 可以基于集群多范围索引扫描表 使用MRR的时候,Extra 显示Using MRR   select * from user where uid > 100  在没有MMR的情况下 先获取数据集,然后根据集合回表,返回满足的数据 使用MMR情况下 先获取数据集,然后对数据集排序(主键排序),最后回表查询完整行  

深入理解零拷贝技术

hi,大家好,内存拷贝是比较耗时操作,零拷贝是常用优化手段,今天分享的文章就是Linux系统零拷贝技术,Kafka和MySQL开源组件都用到这个核心技术,希望大家可以掌握。 DMA 与零拷贝技术 注意事项:除了 Direct I/O,与磁盘相关的文件读写操作都有使用到 page cache 技术。 作者:Spongecaptain 原文:https://spongecaptain.cool/SimpleClearFileIO/ 1. 数据的四次拷贝与四次上下文切换 很多应用程序在面临客户端请求时,可以等价为进行如下的系统调用: File.read(file, buf, len); Socket.send(socket, buf, len); 例如消息中间件 Kafka 就是这个应用场景,从磁盘中读取一批消息后原封不动地写入网卡(NIC,Network interface controller)进行发送。 在没有任何优化技术使用的背景下,操作系统为此会进行 4 次数据拷贝,以及 4 次上下文切换,如下图所示: 如果没有优化,读取磁盘数据,再通过网卡传输的场景性能比较差: 4 次 copy: CPU 负责将数据从磁盘搬运到内核空间的 Page Cache 中; CPU 负责将数据从内核空间的 Socket 缓冲区搬运到的网络中; CPU 负责将数据从内核空间的 Page Cache 搬运到用户空间的缓冲区; CPU 负责将数据从用户空间的缓冲区搬运到内核空间的 Socket 缓冲区中; 4 次上下文切换: read… Continue reading 深入理解零拷贝技术

MySQL降序索引

什么是降序索引 大家可能对索引比较熟悉,而对降序索引比较陌生,事实上降序索引是索引的子集。 我们通常使用下面的语句来创建一个索引: create index idx_t1_bcd on t1(b,c,d); 上面sql的意思是在t1表中,针对b,c,d三个字段创建一个联合索引。 但是大家不知道的是,上面这个sql实际上和下面的这个sql是等价的: create index idx_t1_bcd on t1(b asc,c asc,d asc); asc表示的是升序,使用这种语法创建出来的索引叫做升序索引。也就是我们平时在创建索引的时候,创建的都是升序索引。 可能你会想到,在创建的索引的时候,可以针对字段设置asc,那是不是也可以设置desc呢? 当然是可以的,比如下面三个语句: create index idx_t1_bcd on t1(b desc,c desc,d desc); create index idx_t1_bcd on t1(b asc,c desc,d desc); create index idx_t1_bcd on t1(b asc,c asc,d desc); 这种语法在mysql中也是支持的,使用这种语法创建出来的索引就叫降序索引,关键问题是:在Mysql8.0之前仅仅只是语法层面的支持,底层并没有真正支持。 我们分别使用Mysql7、Mysql8两个版本来举例子说明一下: 在Mysql7、Mysql8中分别创建一个表,有a,b,c,d,e五个字段: create table t1 ( a int primary… Continue reading MySQL降序索引