深入理解Nginx读书笔记

Keywords: #Nginx #Linux
nginx能帮我们做什么?? 一般情况下,一万个非活跃的HTTP Keep-Alive连接在Nginx中仅消耗2.5MB内存,这是Nginx支持高并发连接的基础。 单机支持10w以上的并发连接。理论上,Nginx支持的并发连接上限取决于内存。 master和work进程分离设计,使得Nginx能够提供热部署功能。 Nginx先天的事件驱动型设计、全异步的网络IO处理机制、极少的进程间切换以及许多优化设计,都使得Nginx天生善于处理高并发压力下的互联网请求。 必备软件: GCC编译器,可用来编译C语言程序。 PCRE库,用来支持正则表达式。 zlib库,用于对HTTP包的内容做gzip格式的压缩。 OpenSSL开发库,用于支持SSL协议上传输HTTP,想使用MD5,SHA1等也需要使用它。 内核参数的优化。打开/etc/sysctl.conf。修改后需要sysctl -p来生效。 file-max,表示进程(如一个work进程)可以同时打开的最大句柄数。这个参数直接限制最大并发连接数。tcp_tw.reuse,这个参数设置为1,表示允许将time-wait状态的socket重新用于新的TCP连接。 tcp_keepalive_time,这个参数表示当keepalive启用时,TCP发送keepalive消息的频度。默认为两小时,改小点能更快清理无效连接。 其他的若干参数也应该看看。 编译安装Nginx。 configure检测操作系统内核及安装软件,参数解析,中间目录生成以及根据参数生成c源码、Makefile文件等。 make命令根据上面的Makefile编译Nginx工程并生成目标文件、最终二进制文件。 make install命令根据configure执行时的参数将Nginx部署到指定目录。 configure命令的参数。 –prefix,Nginx安装部署后的根目录,默认/usr/local/nginx。 —sbin-path,—conf-path,—error-log-path,—pid-path,—lock-path,可执行文件、配置文件、错误日志、pid文件(存放master进程id)存放目录和lock文件的放置目录。默认放在下的位置。 —with-cc,C编译器的路径。 –with-cpp,C预编译器的路径。 –with-ld-opt,用于加入链接时的参数。 –with-cpu-opt,指定CPU处理器架构。 另外还包括事件模块、默认编译、默认不编译、邮件代理相关、其他模块。 —user,指定worker进程运行时所属用户,不要用root,其出问题时master要有权限停止worker进程。 nginx -V 可以查看编译阶段的详细信息。 -s stop 可以强制停止Nginx服务。-s参数其实是告诉Nginx程序向正在运行的Nginx服务发送信号量。 -s quit 可以优雅停止服务。先处理完当前请求再停止。 -s reload 重新加载nginx.conf文件。其会先检测文件格式,并以优雅方式关闭并重启服务。 -s reopen,重新打开日志文件,避免日志文件过大。 平滑升级Nginx。 需要替换二进制文件的Nginx。它支持不重启来完成新版本平滑升级。 首先通知正在运行的Nginx准备升级,发送USR2信号。这时运行中的Nginx会将pid文件重命名为pid.oldbin。这样新的Nginx才可能启动成功。 启动新版本Nginx。 给旧的master进程发送SIGQUIT信号以优雅关闭。 随后只有新版本Nginx服务运行。 Nginx的配置 一般使用一个master进程管理多个worker进程。一般worker进程数量和CPU核心数相等。 worker进程很忙,而master进程很闲,他们只负责管理worker进程。当一个worker进程coredump时,master进程会立刻启动新的worker进程继续服务。 为何worker进程要和CPU数量一致?因为Apache上一个进程同一时刻只处理一个请求,所以就需要开多个进程或线程,大量进程间切换将带来系统资源消耗。 Nginx一个worker进程可以同时处理只受限于内存大小的请求数。而且不同worker进程之间处理并发请求几乎没有同步锁,worker进程通常不会进入睡眠状态。所以当其进程数和CPU核心数相等时(最好每个进程和特定CPU绑定),进程间切换代价最小。 每个worker进程都是单线程的进程。他们会调用各个模块来实现功能。如果这些模块确认不会出现阻塞式调用,进程数和CPU数量应该一致。反之则需要配多一些的worker进程。 在gdb调试时关闭以守护进程方式运行Nginx。daemon off。这样可以看到终端上的执行信息。 同上,当关闭以master/worker方式工作,就不会fork出worker进程,而是用master进程来处理请求。master_process off。 error_log logs/error.log error 这儿的error也可以是其他级别,包括debug,info,notice,warn,error,crit,alert,emerg,从左到右依次增大。 如果设定为debug,则编译时需要加入—with-debug参数。 debug_points 是否处理几个特殊的调试点。 debug_connection IP/CIDR,可以对某些特定客户端输出debug级别日志。 Linux系统中,当进程发生错误或收到信号终止时,系统会将进程执行的内存内容(核心映像)写入一个文件(core文件),以作为调试之用,这就是所谓的核心转储(coredumps)。 通过work_rlimit_core size来限制core文件大小。 working_directory path,coredump文件放置目录。 worker_rlimit_nofile limit,设置一个worker进程可以打开的最大文件句柄数。 可以绑定worker进程到指定CPU内核,worker_cpu_affinity cpumask。 SSL硬件加速,使用openssl engine -t来查看是否有SSL硬件加速设备。ssl_engin device。 系统调用gettimeofday的频率,timer_resolution t。 每次内核事件调用如epoll、select、poll、kqueue等返回,都会执行一次gettimeofday,实现用内核的时钟来更新Nginx中的缓存时钟。早期Linux内核中这个代价不小,因为有一次内核态到用户态的内存复制。但是目前一般不必配置。 是否打开accept锁,accept_mutex on。它是Nginx的负载均衡锁,它可以让多个worker进程轮流的、序列化地与新客户端建立tcp连接。当某个worker进程建立的连接数量达到worker_connections配置的7/8时,会大大减小该worker进程试图建立新tcp的机会。 sendfile,当启用时减少了内核态与用户态之间的两次内存复制,这样就会从磁盘中读取文件后直接在内核态发送到网卡设备,提高了发送文件的效率。 ngx_http_core_module模块提供的变量。$uri,$host等等。 Nginx做反向代理服务器,会先把用户发来的请求完整得缓存到Nginx代理服务器,然后才向后端转发,与squid不同。这样能降低后端服务器的负载。 比如用户上传一个1G的文件,squid马上向上游服务器转发,在接受整个文件过程中,后端始终要维持这个链接,对上游服务器的并发能力提出了挑战。 而Nginx在完整接收文件后才与上游服务器建立连接转发请求,由于是内网速度很快。 如何编写HTTP模块 worker进程会在一个for循环语句中反复调用事件模块检测网络事件。当事件模块检测到某个客户端发起tcp请求时(收到SYN包),将会为他建立tcp连接。成功建立链接后根据nginx.

Go代码片段

Keywords: #Go #Linux #语言
打印 使用fmt打印结构体。 import ( "fmt" ) //打印结构体并输出字段名 fmt.Printf("%+v", bc) //{Id:1 BcId:3 Name:缓存集群 Type:1 Operator:袁青松 Status:1 Ctime:1571197361 Utime:2019-10-16 15:40:55} //单独使用这个方法会产生一个换行 fmt.Println() //打印结构体 fmt.Printf("%v", bc) //{1 3 缓存集群 1 袁青松 1 1571197361 2019-10-16 15:40:55} //打印结构体的响应go语法表示 fmt.Printf("%#v", bc) //model.BusinessClassification{Id:1, BcId:3, Name:"缓存集群", Type:1, Operator:"袁青松", Status:1, Ctime:1571197361, Utime:"2019-10-16 15:40:55"} //打印结构体的go类型 fmt.Printf("%T", bc) //model.BusinessClassification fmt.Print有几个变种: Print: 输出到控制台,不接受任何格式化操作 Println: 输出到控制台并换行 Printf : 只可以打印出格式化的字符串。只可以直接输出字符串类型的变量(不可以输出别的类型) Sprintf:格式化并返回一个字符串而不带任何输出 Fprintf:来格式化并输出到 io.Writers 而不是 os.Stdout 通用占位符: %v 值的默认格式。 %+v 类似%v,但输出结构体时会添加字段名 %#v 相应值的Go语法表示 %T 相应值的类型的Go语法表示 %% 百分号,字面上的%,非占位符含义 整数类型:

架构修炼之道读书笔记

Keywords: #网关开发 #Linux #架构
网关之道 网关和代理的区别,代理是纯粹的数据透传,协议不会发生变化。 一个API网关的基本功能包括统一接入、协议适配、流量管控与容错,以及安全防护。 从单体应用到微服务的演变,我们引入了API网关的概念。 API网关通过管道技术来实现逻辑的依次处理。用管道比用if else在结构上会更清晰。 管道的思想和责任链模式是类似的。平常使用的过滤器或拦截器也属于管道技术思维的应用。 同步网关指接收请求到调用API接口提供方的过程都是同步调用。 半同步则是将IO请求线程和业务处理线程分开,但业务线程内部还是同步调用API接口。 全异步指整个链路都是异步请求。 CPU利用率显示的是程序在运行期间实时占用的CPU百分比。 CPU负载显示的是一段时间内正在使用和等待使用CPU的平均任务数。 单核CPU的负载为1.0时,假设CPU每分钟能处理100个进程,而它正好处理100个。如果是2.0则表示这分钟他处理了100个,还有100个在等待处理。双核为2.0时也正好没需要等待的进程。类比。 有的进程CPU利用率高,有的利用率低(等待IO操作)。利用率低但负载高可能是IO高。 磁盘主要通过iostat查看磁盘使用率和磁盘负载百分比。 我们关注磁盘负载百分比这个参数,%util,代表一秒中有多少时间用于IO操作,如果接近100%代表IO请求太多,IO系统已经满负载,该磁盘可能存在瓶颈。 在全异步网关中,RPC客户端内部有一个回调线程池处理异步调用。 一种使用缓存的方式是将缓存持久化,要解决数据更新问题,一般利用时间戳,每次都对比一下时间戳是否过期,过期则去库里面取最新的更新。 凡是不需要重启应用服务器就能够让程序对象的属性值改变的行为都属于热更新。 常见的热更新的方法有MQ、RPC、ZOOKEEPER。 网关有七种武器,分别为降级、限流、熔断、线程池隔离、管道技术、配置热更新和异步。用来保证网关系统的健壮性。 开放之道 分布式之道 CAP理论,C一致性,A可用性,P分区容错性(从分区和容错的角度来理解,当各个节点不能进行通信时,就会形成很多孤立的节点。容错是指在网络异常后整个分布式还是可用的。一般会把数据复制到所有节点上,当分区出现后每个节点都能访问到数据)。CAP不能同时都满足。 BASE理论,BA基本可用,S软状态(如页面显示支付中,允许中间状态的存在),E(eventual consistency)最终一致性。从CAP的基础上演化成了BASE理论。 老的分布式事务通过二阶段提交来实现,分为准备阶段和提交阶段。一般我们都不用二阶段提交,而采用BASE理论实现分布式事务。 分布式锁的实现,redis和zookeeper。redis使用redission。 QPS指服务器每秒能响应的查询次数。TPS指服务器每秒内处理的事务个数,这个事务包括请求服务器,处理,返回三个过程。一般用来评估数据库、交易系统的基准性能。 RT指响应时间,包括请求发出时间、网络传输时间和服务器处理时间三部分组成。 评估系统扩容需要增加多少机器。 总PV0.8/每天秒数0.2 = 峰值时间内每秒请求数(QPS) 峰值时间内每秒请求数(QPS)/单机QPS = 需要的机器 MQ之道 JMS消息类型: 点对点使用队列,生产者将消息放到队列,消费者把消息取出并删除,不会有重复消费的问题,而且只有一个消费者能消费该消息。 发布订阅,引入主题概念,发布者发布一个主题,并向主题发送消息,订阅者订阅自己感兴趣的主题,订阅该主题的消费者都能消费该主题消息,发布者和订阅者之间也不需要关心对方的存在。 生产者-消费者模式 生产者消费者之间增加了一个缓冲区,他们不需要知道对方的存在,相互不依赖,实现了空间解耦。 生产者不关心消费者什么时间去消费数据,消费者可以按照自己的逻辑来控制,实现了时间解耦。 空间解耦和时间解耦 时间耦合 时间解耦 空间耦合 与一个或一些给定的接收者直接通信。发送者接受者必须同时存在,比如PRC调用。 与一个或一些给定的接收者直接通信。他们都可以有自己的生命周期。比如苹果推送等。 空间解耦 发送者不需要知道接收者的身份,但是他们必须同时存在。比如代理、网关。 发送者不需要知道接收者的身份。他们都可以有自己的生命周期。如发布订阅系统,消息队列等。 观察者模式与发布订阅 发布订阅是观察者模式的一种变化。 他们的不同在于,首先观察者模式中,观察者需要提前注册到主题上,所以他在空间和时间上是耦合的。 而发布订阅模式中,发布者将内容发布到MQ队列中,所以发布和订阅是完全解耦的。 消费幂等 一般使用唯一的消息key来进行幂等处理。 MQ的各种功能场景 解耦 削峰填谷 最终一致性,利用MQ的幂等、重试等机制来保证业务的最终一致性 广播消费 使用集群消费模拟广播 重试之坑,由于网络原因,已经消费了被认为没消费导致重复发送,这种要保证重试时发送的流水号相同。 数据异构,对数据按需进行异地构建。 常见数据异构的方式:完整克隆、标记同步(标记时间戳,故障从时间点开始重新同步)、binlog方式、MQ方式。 binlog方式进行异构,使用开源订阅binlog日志组件canal。 消息推送之道 消息推送主要有两种方式,自建或利用第三方平台。 自建一般通过HTTP和TCP协议,HTTP的话一般通过1.

docker开发kong

Keywords: #docker #Linux #kong
安装docker 如果是centos,最好用最新的7.6版本。 安装docker依赖。 yum install -y yum-utils device-mapper-persistent-data lvm2 设置yum源。 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 安装docker。 yum install docker 启动并加入开机启动。 systemctl start docker systemctl enable docker 验证安装。 docker version 安装kong 使用docker-compose部署kong,也可以按照官方步骤来,但是这样需要每次手动执行或者使用shell脚本。使用docker-compose可以在单机上启动一组相关容器。 安装docker-compose。 yum -y install epel-release yum -y install python-pip pip install docker-compose 在指定当前目录添加一个docker-compose.yml文件。 version: '2.1' services: kong-migrations: image: "kong:latest" command: kong migrations bootstrap depends_on: db: condition: service_healthy environment: KONG_DATABASE: postgres KONG_PG_DATABASE: kong KONG_PG_HOST: db KONG_PG_PASSWORD: kong KONG_PG_USER: kong links: - db:db kong: image: "kong:latest" depends_on: db: condition: service_healthy environment: KONG_ADMIN_ACCESS_LOG: /dev/stdout KONG_ADMIN_ERROR_LOG: /dev/stderr KONG_ADMIN_LISTEN: '0.

算法大全

递归、常见 求斐波那契数列的第n项。 第一种,用递归。因为存在重复计算,效率很低。 第二种,非递归,考虑从小往大来算。 one=0 two=1 N=0 for(i=2;i<n;i++){ N=one+two two=N one=two } 快排。 第一种,双指针法。 #include <stdio.h> void qsort(int *ary, int min, int max) { int p1 = min; int p2 = max; int key=(min+max)>>1; while(p1<p2) { while(ary[p2]>ary[key]) { p2--; } while(ary[p1]<ary[key]) { p1++; } if(p1<=p2) { int tmp=ary[p1]; ary[p1]=ary[p2]; ary[p2]=tmp; p1++; p2--; } } if(min<p2) qsort(ary, min, p2); if(p1<max) qsort(ary, p1, max); } int main() { int a[] = {4,6,1,6,9,3,2}; qsort(a, 0, 6); for(int i=0;i<=6;i++) printf("%d ",a[i]); return 0; } 二分法查找 递归实现

我从WordPress改成hugo生成静态网站

我的阿里云快到期了,WordPress也没有什么不好,只是这次到期我不在想续费了,所以想迁移到github.io上。 还有这次我续费了三年腾讯云,1核2G的机器,可惜是成都机房,在我家晚间高峰期访问能卡死,所以我推测这绝逼不是电信机房。 本次的方案如下: 全部改成markdown语法,从WordPress转过来,使用了一个WordPress插件:wordpress-to-hugo-exporter,可以把所有文章和附件打包下载。 不过事实上这个插件很弱,我几乎是全部手工转的。借用了一个chrome插件:拷贝为markdown。 在bitbucket建立一个私有仓库来保存这些md文件,这样我可以在任何地方写博客了。 客户端我使用了Typora,一个非常好用的跨平台markdown编辑器。 在腾讯云安装了hugo,用来生成静态博客。hugo速度飞快不愧是go写的,还不用安装啥乱七八糟的软件。 生成网站后推送到github.io,域名也使用dulcim.com,这样啥都不用改。连地址都不变。 高亮使用软件highlight.js,这儿涉及到代码不会自动换行的问题,在css中加入: code { white-space: pre-wrap; /* CSS 3 */ white-space: -moz-pre-wrap; /* Mozilla */ white-space: -pre-wrap; /* Opera 4-6 */ white-space: -o-pre-wrap; /* Opera 7 */ word-wrap: break-word; /* IE 5.5+ */ } 其实这样后的换行还是挺丑的,不是在一行顶格后才换行,而是按内容来。这个还待再解决。 toc问题,在主题里找到layouts/_default/single.html,把{{ .TableOfContents }}加到适当位置即可。 不错的博客主题:hugo-lithium-theme,elephants 在使用lithium主题时,加了标签内容,但是生成发现原风格并没有标签页,因为生成标签页时按照默认标签页/layouts/_default/list.html去读取,但是却没有这个页面,所以复制了其他的风格页面过来,需要的middle页面也复制了过来。看这个博客有说明。还有个问题,生成标签链接时是有大写的,但是hugo生成标签却是全小写,所以标签链接要改成小写,看这个。 建立了tags页面。 创建一个about页面,hugo new about.md会在content下生成。

视频转码相关

Keywords: #ffmpeg #Linux #mencoder
linux下视频转码主要有两种方案,mencoder和FFmpeg。我使用jwplayer播放器,发现不少格式不兼容,即使对于mp4格式的,如果不是x264编码也会出问题——有声音但是黑屏。 mencoder 因为我用的是ct板子,安装了mencoder,先试了试转一个75mb的视频,转成x264编码的。转换结果48mb,质量尚可,但是耗时太长了,一般两三秒对应视频中的一秒。 mencoder -ovc x264 -oac mp3lame -of lavf /mnt/Untitled-sda1/webdata/video/raw.mp4 -o /mnt/Untitled-sda1/webdata/video/dest.mp4 不过证明这种格式是可以播放的。 还有mp4不能播放的情况,转换后可正常播放,但是视频时间压缩了一倍,这类怀疑是音频缺失导致。 ffmpeg 在ct板子上安装了ffmpeg,然后测试了一下转换一个30mb的视频。 ffmpeg -i /mnt/Untitled-sda1/webdata/video/raw.mp4 -f mp4 -acodec copy -vcodec libx264 /mnt/Untitled-sda1/webdata/video/dest.mp4 太慢了,还是考虑把这块放到mac上来执行,安装ffmpeg。 brew install ffmpeg --with-chromaprint --with-fdk-aac --with-fontconfig --with-freetype --with-frei0r --with-libass --with-libbluray --with-libbs2b --with-libcaca --with-libgsm --with-libmodplug --with-libsoxr --with-libssh --with-libvidstab --with-libvorbis --with-libvpx --with-opencore-amr --with-openjpeg --with-openssl --with-opus --with-rtmpdump --with-rubberband --with-schroedinger --with-sdl2 --with-snappy --with-speex --with-tesseract --with-theora --with-tools --with-two-lame --with-wavpack --with-webp --with-x265 --with-xz --with-zeromq --with-zimg

关于

关于 这是个技术博客

寻求帮助

寻求帮助 Email: destroy@outlook.com Wechat: Maidotdot

隐私政策

隐私政策 “少年手册"尊重并保护所有使用服务用户的个人隐私权。为了给您提供更准确、更有个性化的服务,“少年手册"会按照本隐私权政策的规定使用和披露您的个人信息。但"少年手册"将以高度的勤勉、审慎义务对待这些信息。除本隐私权政策另有规定外,在未征得您事先许可的情况下,“少年手册"不会将这些信息对外披露或向第三方提供。“少年手册"会不时更新本隐私权政策。 您在同意"少年手册"服务使用协议之时,即视为您已经同意本隐私权政策全部内容。本隐私权政策属于"少年手册"服务使用协议不可分割的一部分。 适用范围 a) 在您注册"少年手册"帐号时,您根据"少年手册"要求提供的个人注册信息; b) 在您使用"少年手册"网络服务,或访问"少年手册"平台网页时,“少年手册"自动接收并记录的您的浏览器和计算机上的信息,包括但不限于您的IP地址、浏览器的类型、使用的语言、访问日期和时间、软硬件特征信息及您需求的网页记录等数据; c) “少年手册"通过合法途径从商业伙伴处取得的用户个人数据。 您了解并同意,以下信息不适用本隐私权政策: a) 您在使用"少年手册"平台提供的搜索服务时输入的关键字信息; b) “少年手册"收集到的您在"少年手册"发布的有关信息数据,包括但不限于参与活动、成交信息及评价详情; c) 违反法律规定或违反"少年手册"规则行为及"少年手册"已对您采取的措施。 信息使用 a) “少年手册"不会向任何无关第三方提供、出售、出租、分享或交易您的个人信息,除非事先得到您的许可,或该第三方和"少年手册”(含"少年手册"关联公司)单独或共同为您提供服务,且在该服务结束后,其将被禁止访问包括其以前能够访问的所有这些资料。 b) “少年手册"亦不允许任何第三方以任何手段收集、编辑、出售或者无偿传播您的个人信息。任何"少年手册"平台用户如从事上述活动,一经发现,“少年手册"有权立即终止与该用户的服务协议。 c) 为服务用户的目的,“少年手册"可能通过使用您的个人信息,向您提供您感兴趣的信息,包括但不限于向您发出产品和服务信息,或者与"少年手册"合作伙伴共享信息以便他们向您发送有关其产品和服务的信息(后者需要您的事先同意)。 信息披露 在如下情况下,“少年手册"将依据您的个人意愿或法律的规定全部或部分的披露您的个人信息: a) 经您事先同意,向第三方披露; b) 为提供您所要求的产品和服务,而必须和第三方分享您的个人信息; c) 根据法律的有关规定,或者行政或司法机构的要求,向第三方或者行政、司法机构披露; d) 如您出现违反中国有关法律、法规或者"少年手册"服务协议或相关规则的情况,需要向第三方披露; e) 如您是适格的知识产权投诉人并已提起投诉,应被投诉人要求,向被投诉人披露,以便双方处理可能的权利纠纷; f) 在"少年手册"平台上创建的某一交易中,如交易任何一方履行或部分履行了交易义务并提出信息披露请求的,“少年手册"有权决定向该用户提供其交易对方的联络方式等必要信息,以促成交易的完成或纠纷的解决。 g) 其它"少年手册"根据法律、法规或者网站政策认为合适的披露。 信息存储和交换 “少年手册"收集的有关您的信息和资料将保存在"少年手册"及(或)其关联公司的服务器上,这些信息和资料可能传送至您所在国家、地区或"少年手册"收集信息和资料所在地的境外并在境外被访问、存储和展示。 Cookie的使用 a) 在您未拒绝接受cookies的情况下,“少年手册"会在您的计算机上设定或取用cookies ,以便您能登录或使用依赖于cookies的"少年手册"平台服务或功能。“少年手册"使用cookies可为您提供更加周到的个性化服务,包括推广服务。 b) 您有权选择接受或拒绝接受cookies。您可以通过修改浏览器设置的方式拒绝接受cookies。但如果您选择拒绝接受cookies,则您可能无法登录或使用依赖于cookies的"少年手册"网络服务或功能。 c) 通过"少年手册"所设cookies所取得的有关信息,将适用本政策。 信息安全 a) “少年手册"帐号均有安全保护功能,请妥善保管您的用户名及密码信息。“少年手册"将通过对用户密码进行加密等安全措施确保您的信息不丢失,不被滥用和变造。尽管有前述安全措施,但同时也请您注意在信息网络上不存在“完善的安全措施”。 b) 在使用"少年手册"网络服务进行网上交易时,您不可避免的要向交易对方或潜在的交易对方披露自己的个人信息,如联络方式或者邮政地址。请您妥善保护自己的个人信息,仅在必要的情形下向他人提供。如您发现自己的个人信息泄密,尤其是"少年手册"用户名及密码发生泄露,请您立即联络"少年手册"客服,以便"少年手册"采取相应措施。