Manjaro日常开发配置

本人做开发以来一直喜欢尝试在不同的OS下进行开发作业,从最早的win7,win10到MacOS,再到ubuntu18.04,直到用过Manjaro之后,就再没想尝试其他发行版了,软件安装方便和硬件驱动支持良好是原因之一,还有就是pacman命令效率极高,相比ubuntu来说,manjaro在使用过程中的坑要少很多 pacman国内镜像初始化: sudo pacman-mirrors -i -c China -m rank sudo pacman -Syyu 下面从开发环境到常用软件一一介绍: 开发环境 平常工作主要是做app接口开发,网站开发,服务器运维等工作,主要语言是php,因此需要一个lnmp环境 为了后期方便环境的迁移,就把这个lnmp环境做成了docker-compose脚手架,又额外添加了一些常用工具(如:elk日志系统),然后发布至Github,项目是:allindocker 常用软件 ide phpstorm goland 文本编辑器 vscode vim,推荐使用vimrc进行扩展 终端相关 tmux,一个终端分屏利器,用过后就丢不下了,推荐一篇关于tmux的文章Tmux使用手册,一个主题 oh-my-zsh proxychains,终端代理必备!! 代理 ss 虚拟机 virtual box 容器化工具 docker 通讯工具 telegram 网页微信 输入法 RIME api调试 postman 远程传输 filezilla rsync 文件同步 dropbox 版本控制 git svn 浏览器 chrome firefox 其他 redshift 之后就可以愉快的开发了 人生苦短,我用Manjaro!

May 12, 2019 · 1 min · 56 words

在合适的场景使用延时队列代替定时任务

需求场景 当前有这样一个模块,用户A(被服务者)发布一个服务到平台,服务包含服务内容以及服务的开始和结束时间,用户B(服务者)可以选择预约用户A发布的服务 服务在被预约后会生成一个订单,用户B需要在服务开始时间到达时开始对用户A提供服务,并上传服务过程(手机拍照) 用户B在服务时间结束前完成全部服务过程的上传,用户A,用户B进行订单互评 流程结束 其中有4个时间节点需要系统自动处理: 距离服务开始前x(系统配置)分钟时,系统需要主动向用户B推送服务即将开始的通知 服务开始时间到达时,系统需要自动开始服务(更新订单状态为:服务中) 服务结束时间到达时,系统需要根据当前服务流程上传情况自动更新当前服务订单状态为:已完成/超时取消 对于已完成未评价的服务订单,系统需要在到达x(系统配置)小时后自动评价订单 解决方案 系统定时任务 最初使用了laravel自带的Task Scheduling处理以上流程,但是问题也不少: 由于需要批量查询,批量更新,后期数据量到达一定量级的时候mysql性能必然会受到较大影响 项目中对列表数据,详情数据几乎都使用了缓存,而缓存更新机制也是写在了laravel框架model层的events事件中,但是模型事件无法通过批量操作时触发(官网文档), 因此只能手动更新缓存 When issuing a mass update via Eloquent, the saved and updated model events will not be fired for the updated models. This is because the models are never actually retrieved when issuing a mass update. 时间粒度只能精确到分钟 延时队列 针对上述问题,我决定把这几个系统自动执行流程通过基于queues#delayed-dispatching重写(底层通过zset实现) 基本流程: 用户预约服务时将服务订单分发到两个队列(延时时间根据订单开始时间距离当前时间的差值决定[单位:s]):服务即将开始的通知队列,服务自动开始队列 服务开始时将订单分发到超时自动结束队列(延时时间根据订单结束时间距离当前时间的差值决定[单位:s]) 服务完成时将订单分发到超时未评价自动评价队列(延时时间根据系统配置订单完成后允许最长等待评价时间决定[单位:s]) 至此,通过延时队列解决了定时任务带来的问题

April 10, 2019 · 1 min · 60 words

如何坚持写博客

看到不少人说写博客很难坚持下去,在这总结下本人坚持写博客的动力 工作记录 做技术很多时候需要记录下开发过程中一些比较有意义的经历,比如解决了一个棘手的BUG,完成了一个对自己当前水平很有挑战的功能等等 这些记录都可能在日后遇到类似问题的时候不再踩坑,也可能帮助到他人 写博客的过程本身也是对所记录内容的一次情景重现,需要严格检查所记录内容是否正确,以免误导,自己再一次加深了对所记录内容的印象 技术总结 同上一个原因类似,我通常会在完成对一个或多个技术点的学习之后记录下学习过程,包括学习的动机,技术的应用场景,实现的过程等 折腾博客系统 从基于ThinkPHP3.2自己写的动态博客到hexo再到现在的jekyll,换过两次博客系统,周期性的替换博客系统也是玩独立博客的乐趣之一 博客主题也是换过多次 生活记录 除了技术相关的内容,博客用来记录生活的点滴也是不错的 保持学习 只有坚持不断的学习,才会有更多写博客的欲望,才会有更多需要记录的东西,因此这点可以从根本上解决不能坚持写博客的问题~ 以上都是本人坚持写博客的动力

April 9, 2019 · 1 min · 15 words

redis在目前项目的部分应用场景

场景一:设备在线状态保持 需求 有若干台设备,设备具备定时向server发送heartbeat的功能,后台需要在设备列表实时监控设备的在线情况(允许有不大于5分钟的时间延迟) 实现 在openresty配置中加入用于处理心跳请求的location块,如下 location /device/heartbeat { default_type text/html; lua_need_request_body on; content_by_lua_file src/heartbeat_detector.lua; } lua脚本 -- 获取请求方式,只允许POST请求 local request_method = ngx.var.request_method -- ngx.log(ngx.ERR, "headers:"..ngx.var.http_user_agent) if request_method ~= "POST" then ngx.exit(ngx.HTTP_NOT_ALLOWED) end local function close_redis(red) if not red then return end --释放连接(连接池实现) local pool_max_idle_time = 10000 --毫秒 local pool_size = 100 --连接池大小 local ok, err = red:set_keepalive(pool_max_idle_time, pool_size) if not ok then ngx.log(ngx.ERR, "set redis keepalive error : ", err) end end -- 引入json处理库 local cjson = require "cjson" -- 临时文件读取函数 function getFile(file_name) local f = assert(io.open(file_name, 'r')) local string = f:read("*all") f:close() return string end -- 获取请求体 ngx.req.read_body() -- 获取请求body local data = ngx.req.get_body_data() -- 如果请求body为空,则从临时文件获取 if nil == data then local file_name = ngx.req.get_body_file() if file_name then data = getFile(file_name) end end -- 将data转换为object local obj = cjson.decode(data) -- 如果当前请求为心跳维持请求 if obj.Name == "KeepAlive" then --[[ 初始化redis ]] local redis = require "resty.redis" local red = redis:new() red:set_timeout(1000) local host = 'ip' local port = port local ok, err = red:connect(host,port) if not ok then return close_redis(red) end -- 请注意这里 auth 的调用过程 local count ount, err = red:get_reused_times() if 0 == count then ok, err = red:auth("password") if not ok then ngx.say("failed to auth: ", err) return end elseif err then ngx.say("failed to get reused times: ", err) return end -- redis前缀 local prefix = 'device_heartbeat:' -- 缓存心跳 res, err = red:set(prefix..obj.DeviceId, 1, 'EX', 300) end 需要保证在项目的已有路由中没有/device/heartbeat,此时/device/heartbeat的请求会交给lua脚本处理,相对于php性能消耗更少,php后台获取到数据后可直接在redis中查找该设备对应的心跳key是否存在来确认设备是否在线 ...

April 3, 2019 · 3 min · 613 words

laravel基于redis的分布式秒杀系统

场景 本文暂不讨论前端页面,cdn在秒杀上的性能优化,只关注从用户请求到达web服务器开始直至秒杀完成在redis中生成订单结束这个阶段的实现,后续还需要使用redis队列异步生成mysql订单实现数据的持久化 实现 为了方便测试结果,当前本地的测试环境如下: web服务器 使用了openresty监听本地的80端口,并代理到3台负载均衡服务器,由负载均衡服务器调用php-fpm实际处理所有请求的业务 nginx.conf中加入 upstream test { server localhost:16888; server localhost:16889; server localhost:16890; } conf.d/default.conf中加入 server { listen 80; server_name localhost; location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://test; } } server { listen 16888; server_name localhost; access_log /var/log/nginx/balancer-1.access.log main; error_log /var/log/nginx/balancer-1.error.log warn; root /data/www/community/public; location / { access_by_lua_block{ -- request header方便后台分辨请求来源服务器 ngx.req.set_header('balancer', 'balancer-1') -- response header方便客户端查看当前请求由哪个服务器处理(仅测试用) ngx.header['balancer'] = 'balancer-1' } try_files $uri $uri/ /index.php?$query_string; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; index index.html index.htm index.php; } location ~ \.php$ { fastcgi_pass php72:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } server { listen 16889; server_name localhost; access_log /var/log/nginx/balancer-2.access.log main; error_log /var/log/nginx/balancer-2.error.log warn; root /data/www/community/public; location / { access_by_lua_block{ ngx.req.set_header('balancer', 'balancer-2') ngx.header['balancer'] = 'balancer-2' } try_files $uri $uri/ /index.php?$query_string; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; index index.html index.htm index.php; } location ~ \.php$ { fastcgi_pass php72:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } server { listen 16890; server_name localhost; access_log /var/log/nginx/balancer-3.access.log main; error_log /var/log/nginx/balancer-3.error.log warn; root /data/www/community/public; location / { access_by_lua_block{ ngx.req.set_header('balancer', 'balancer-3') ngx.header['balancer'] = 'balancer-3' } try_files $uri $uri/ /index.php?$query_string; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; index index.html index.htm index.php; } location ~ \.php$ { fastcgi_pass php72:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } 同时开放本地的16888,16889,16890接口 ...

March 8, 2019 · 2 min · 415 words

Openresty实现访问限流

基本概念 Nginx:高性能、高并发的Web服务器,拥有丰富的第三方模块。 Lua:一种轻量级、可嵌入式的脚本语言。 Ngx_lua:Nginx的一个模块,将Lua嵌入到Nginx中,这样就可以使用Lua编写应用脚本,部署到Nginx中运行,即Nginx变成了一个Web容器,这样开发人员就可以使用Lua语言开发高性能Web应用了。 引用官网的一个描述: OpenResty® 的目标是让你的Web服务直接跑在 Nginx 服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都进行一致的高性能响应。 应用场景 在 Lua 中混合处理不同 Nginx 模块输出(proxy, drizzle, postgres, Redis, memcached 等)。 在请求真正到达上游服务之前,Lua 中处理复杂的准入控制和安全检查。 比较随意的控制应答头(通过 Lua)。 从外部存储中获取后端信息,并用这些信息来实时选择哪一个后端来完成业务访问。 在内容 handler 中随意编写复杂的 web 应用,同步编写异步访问后端数据库和其他存储。 在 rewrite 阶段,通过 Lua 完成非常复杂的处理。 在 Nginx 子查询、location 调用中,通过 Lua 实现高级缓存机制。 对外暴露强劲的 Lua 语言,允许使用各种 Nginx 模块,自由拼合没有任何限制。该模块的脚本有充分的灵活性,同时提供的性能水平与本地 C 语言程序无论是在 CPU 时间方面以及内存占用差距非常小。所有这些都要求 LuaJIT 2.x 是启用的。其他脚本语言实现通常很难满足这一性能水平。 LuaNginxModule的执行阶段 set_by_lua*: 流程分支处理判断变量初始化 rewrite_by_lua*: 转发、重定向、缓存等功能(例如特定请求代理到外网) access_by_lua*: IP 准入、接口权限等情况集中处理(例如配合 iptable 完成简单防火墙) content_by_lua*: 内容生成 header_filter_by_lua*: 响应头部过滤处理(例如添加头部信息) body_filter_by_lua*: 响应体过滤处理(例如完成应答内容统一成大写) log_by_lua*: 会话完成后本地异步完成日志记录(日志可以记录在本地,还可以同步到其他机器) 限流的实现 由于近期工作中所负责的项目是开发App和一个前后端分离的管理系统的数据接口(统一采用jwt作为身份认证方式),且第一期已经接近尾声,因此除了做一些php代码层面的缓存优化之外,想到了需要学习一下除了bloomfilter之外的防止缓存穿透的办法(直接在web服务器层面通过redis动态限制访问频率,优点,性能损耗小,全程没有php参与),碰巧网上看到了Openresty,又是基于nginx(熟悉的配方),又能解决当下遇到的问题(神奇的味道),于是经过了几天的学习,也参考了一些其他博客中类似的实现,现记录下本人目前动态限流的实现过程 ...

March 2, 2019 · 7 min · 1477 words

mysql实现主从复制

基本流程 docker-compose.yml文件配置 #数据库-主库 mysql57: image: ${MYSQL_IMAGE} environment: - MYSQL_ROOT_PASSWORD=${MYSQL_MASTER_ROOT_PASSWORD} #- MYSQL_USER=user #- MYSQL_PASSWORD=password volumes: #配置文件 - ${MYSQL_MASTER_CONF}:/etc/mysql/my.cnf:ro #数据目录 - ${MYSQL_MASTER_DATA}:/var/lib/mysql/:rw #查询日志文件 #- ./logs/mysql/query_mysql.log:/var/logs/mysql/query.mysql.log:rw #慢查询日志文件 #- ./logs/mysql/slow_mysql.log:/var/logs/mysql/slow.mysql.log:rw restart: always ports: - "${MYSQL_MASTER_PORT}:3306" container_name: mysql57 #从库01 mysql57-slave01: depends_on: - mysql57 image: ${MYSQL_IMAGE} environment: - MYSQL_ROOT_PASSWORD=${MYSQL_SLAVE_01_ROOT_PASSWORD} - MASTER_HOST=mysql57 #- MYSQL_USER=user #- MYSQL_PASSWORD=password volumes: #配置文件 - ${MYSQL_SLAVE_01_CONF}:/etc/mysql/my.cnf:ro #数据目录 - ${MYSQL_SLAVE_01_DATA}:/var/lib/mysql/:rw #查询日志文件 #- ./logs/mysql/query_mysql.log:/var/logs/mysql/query.mysql.log:rw #慢查询日志文件 #- ./logs/mysql/slow_mysql.log:/var/logs/mysql/slow.mysql.log:rw restart: always ports: - "${MYSQL_SLAVE_01_PORT}:3306" container_name: mysql57-slave01 #从库02 mysql57-slave02: depends_on: - mysql57 image: ${MYSQL_IMAGE} environment: - MYSQL_ROOT_PASSWORD=${MYSQL_SLAVE_02_ROOT_PASSWORD} - MASTER_HOST=mysql57 #- MYSQL_USER=user #- MYSQL_PASSWORD=password volumes: #配置文件 - ${MYSQL_SLAVE_02_CONF}:/etc/mysql/my.cnf:ro #数据目录 - ${MYSQL_SLAVE_02_DATA}:/var/lib/mysql/:rw #查询日志文件 #- ./logs/mysql/query_mysql.log:/var/logs/mysql/query.mysql.log:rw #慢查询日志文件 #- ./logs/mysql/slow_mysql.log:/var/logs/mysql/slow.mysql.log:rw restart: always ports: - "${MYSQL_SLAVE_02_PORT}:3306" container_name: mysql57-slave02 master配置 my.cnf文件加入: ...

February 19, 2019 · 4 min · 684 words

php开启opcache前后性能差异

本打算发帖到v2ex上求助,结果自己碰巧解决了,因此在博客上记录一下完整的从发现到解决的过程 环境 硬件配置:腾讯云的2核4G服务器 系统:ubuntu server 16.04 LTS lnmp:通过docker-compose做编排的php-fpm7.2(基于alpine)+nginx(官方镜像)+mysql5.7(官方镜像) 缓存:redis 框架:laravel5.5 路由大概 之前QPS 不改变入口文件,请求http://hostname/,QPS:19-21 不改变入口文件,请求http://hostname/任意路径,QPS:18-19 在入口文件第二行直接die();,请求http://hostname/,QPS:240-250 已做过的调试 开启了php-fpm的slowlog记录(并确保其正常工作:docker开启了cap_add: SYS_PTRACE),但通过压测工具并未发现slowlog有任何记录(代码里加sleep(2)会记录到slowlog里) 已经用过laravel自带的配置缓存,路由缓存以及optimize等命令 通过htop查看系统负载发现cpu是被php-fpm pool www这个command跑满的,因此可以排除其他原因 其他说明 服务器通过nginx监听80端口对来源请求进行反向代理至php所在容器进行处理,所有容器中只有nginx对外开放了80和443,其他都是容器内部通过container_name进行访问 问题 可以从哪些方面着手提高QPS? 问题解决-开启opcache opcaches是什么 以下是开启opcache和关闭后QPS的对比 #开启opcache(Dockerfile中使用docker-php-ext-install opcache) #php.ini配置文件中开启opcache相关配置 ➜ ~ http_load -p 80 -s 30 url 2201 fetches, 80 max parallel, 1.33667e+07 bytes, in 30 seconds 6073 mean bytes/connection 73.3667 fetches/sec, 445556 bytes/sec msecs/connect: 4.99642 mean, 32.34 max, 2.791 min msecs/first-response: 1066.44 mean, 2130.71 max, 52.395 min HTTP response codes: code 200 -- 2201 ➜ ~ http_load -p 80 -s 30 url 2389 fetches, 80 max parallel, 1.45084e+07 bytes, in 30 seconds 6073 mean bytes/connection 79.6333 fetches/sec, 483613 bytes/sec msecs/connect: 4.92044 mean, 41.46 max, 2.818 min msecs/first-response: 980.024 mean, 1819.01 max, 42.171 min HTTP response codes: code 200 -- 2389 #关闭opcache(未安装opcache) ➜ ~ http_load -p 80 -s 30 url 555 fetches, 80 max parallel, 3.37052e+06 bytes, in 30 seconds 6073 mean bytes/connection 18.5 fetches/sec, 112350 bytes/sec msecs/connect: 5.68439 mean, 31.76 max, 2.826 min msecs/first-response: 4035.69 mean, 5985 max, 120.81 min HTTP response codes: code 200 -- 555 ➜ ~ http_load -p 80 -s 30 url 559 fetches, 80 max parallel, 3.39481e+06 bytes, in 30 seconds 6073 mean bytes/connection 18.6333 fetches/sec, 113160 bytes/sec msecs/connect: 5.78894 mean, 18.31 max, 2.944 min msecs/first-response: 3970.26 mean, 5100.76 max, 163.014 min HTTP response codes: code 200 -- 559 然后通过缓存配置&&路由缓存&&优化io读写&&优化自动加载,将QPS提升到了90+ ...

January 17, 2019 · 2 min · 422 words

一个non-linux平台使用docker的问题

相关问题 最近换了工作,新公司准备开发一个社区项目,从零开始开发.新电脑的环境使用自己为方便开发写的基于docker-compose的环境,框架使用laravel5.5,php版本7.2,mysql版本5.7,其他使用nginx作为web服务器,redis处理缓存 刚开始就发现一个奇怪的问题:请求后台的每个页面响应时间都在1s以上(localhost),后来发现直接请求首页也是这样的高延迟,由于全局都没有类似google的静态文件引入,因此想到去网上找原因,在Extremely slow on Windows 10中,提问者提到已经尝试过多种能想到的办法去优化设置,升级,以及修改docker的各项配置,但最终依然无法解决该问题 我也尝试过在Mac和Ubuntu Server上使用docker,docker在Mac和Windows上的问题相似,加载速度也很慢,但在Linux上响应非常迅速,个人能想到的原因可能是在非Linux系统下的docker都是运行在虚拟机内,可能因为目录映射跨越宿主机和虚拟机导致了读写速度缓慢.. 另一个参考 不同平台上的docker性能讨论 个人结论 使用non linux平台的docker作为开发和测试环境都是可行且方便的,但一定不要作为生产环境!!!

December 5, 2018 · 1 min · 14 words

关于docker内nginx获取真实client-ip的问题

环境 系统:MacOS Mojave web环境:docker+nginx+php-fpm 问题 nginx始终无法获取到正确的客户端ip地址,获取到的是nginx所在docker容器的网关ip 原因 后来发现是MacOS下才有的问题,在linux下正常 方法 在nginx配置文件的server段加入以下 proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; 现存问题 当前配置可在linux下获取到正确的客户端ip,但macOS系统获取到的依然是gateway地址,目前多次google后仍然无果,以下为部分该问题相关的参考地址 Original ip is not passed to containers Docker Beta on Mac : Cannot use ip to access nginx container docker 如何让 Nginx 获取到访问者 IP? 后续需要继续关注该问题的解决方案

November 9, 2018 · 1 min · 49 words