lua与redis结合应用于nginx的动态upstream

技术要求很简明: nginx分发请求的时候,upstream是由lua从redis中读取配置动态生成的,这样便于用程序动态修改。 装好nginx+lua,过程不表。 把lua redis的模块配到路径中 wget https://raw.github.com/nrk/redis-lua/version-2.0/src/redis.lua nginx配置如下: server { listen 80; server_name _; server_name_in_redirect off; port_in_redirect off; root /root/html; location / { set $upstream ""; rewrite_by_lua ' -- load global route cache into current request scope -- by default vars are not shared between requests local routes = _G.routes -- setup routes cache if empty if routes == nil then routes = {} ngx.log(ngx.ALERT, "Route cache is empty.") end -- try cached route first local route = routes[ngx.var.http_host] if route == nil then local redis = require "redis" local client = redis.connect("localhost", 6379) route = client:get(ngx.var.http_host) end -- fallback to redis for lookups if route ~= nil then ngx.var.upstream = route routes[ngx.var.http_host] = route _G.routes = routes else ngx.exit(ngx.HTTP_NOT_FOUND) end '; proxy_buffering off; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_redirect off; proxy_connect_timeout 10; proxy_send_timeout 30; proxy_read_timeout 30; proxy_pass http://$upstream; } } 送进redis一些数据 ...

2024年1月23日

kvm的虚机中如何在线挂接一块新网卡

比较古怪的需求,公司拉了根专线到机房。 而使用专线的机器是一台kvm虚机,实体机有自己的路由,实体机的前两个网卡做了双网卡bonding。 那虚机就只能使用实机的第三块网卡连出去了,而且必须制定host的路由,这里给的子网掩码是255.255.255.252,只有2个ip可以用,所以只能虚机有ip,实机根本不能配ip地址!!! 首先把实机dell r720的第三块网卡em3改一下,连接到网桥br1 cat /etc/sysconfig/network-scripts/ifcfg-em3 DEVICE=em3 HWADDR=XX:XX:XX:XX:XX:XX TYPE=Ethernet UUID=6b68220d-d5ed-496f-b8d1-4c6d9cbb1234 ONBOOT=yes NM_CONTROLLED=no BRIDGE=br1 再做个网桥br1 cat /etc/sysconfig/network-scripts/ifcfg-br1 DEVICE=br1 BOOTPROTO=none ONBOOT=yes TYPE=Bridge 注意,这个物理机网卡和网桥都没有IP地址,实在是可怜,ip不够用 然后启动他们: ifup em3 ifup br1 虚机挂接新设备: virsh attach-interface --domain vis-16-13-28 \ --type bridge \ --source br1 --model virtio \ --mac f0:00:ac:30:2d:1d --config 然后ssh登录虚机,配置好虚机中eth1的ip/mask,不要配gateway啊 最后直接加主机路由: route add -host 172.17.11.182 dev eth1 ping一下对端172.17.11.182,通就搞定了。

2024年1月23日

mvn build的时候控制日志输出

最近在弄jenkins的自动打包部署 出现个问题,项目是用的mvn,打包的时候,如果是在控制台下还好。 如果是在jenkins下,看console output,往中心仓库artifactory提交包的时候,会显示下面一堆: Uploaded: http://xxx:8081/artifactory/libs-release-local/abc/maven-metadata.xml (315 B at 17.1 KB/sec) Uploading: http://xxx:8081/artifactory/libs-release-local/abc/d/admin-9.1.war 20000/21969 KB 20002/21969 KB 20004/21969 KB 20006/21969 KB 20008/21969 KB 20010/21969 KB 20012/21969 KB 20014/21969 KB 20016/21969 KB 20018/21969 KB 20020/21969 KB 20022/21969 KB 20024/21969 KB 20026/21969 KB 20028/21969 KB 20030/21969 KB 20032/21969 KB 20034/21969 KB 20036/21969 KB 20038/21969 KB 20040/21969 KB 20042/21969 KB 20044/21969 KB ...... 长度无比长,垃圾东西。如何将之屏蔽呢? 首先去修改mvn的日志级别,缺省是INFO,提高到WARN: MAVEN_OPTS=-Dorg.slf4j.simpleLogger.defaultLogLevel=warn mvn -ff clean install 我去,INFO是都没了,但是这个居然还在!!!! 查了下java的日志优先级: ALL < DEBUG < INFO < WARN < ERROR < FATAL < OFF 上面只有FATAL和OFF了,说明这个是个副产品,不是mvn控制的,而是上传的时候产生的。 ...

2024年1月23日

syslog级别详解

首先是: [facility].[priority] facility表示设备、设施,特别装置: auth # 认证相关的 authpriv # 权限,授权相关的 cron # 任务计划相关的 daemon # 守护进程相关的 kern # 内核相关的 lpr # 打印相关的 mail # 邮件相关的 mark # 标记相关的 news # 新闻相关的 security # 安全相关的,与auth 类似 syslog # syslog自己的 user # 用户相关的 uucp # unix to unix cp 相关的 local0 到 local7 # 用户自定义使用 * # *表示所有的facility 一定要注意上面的,local0 到 local7 # 用户自定义使用 priority表示优先权,日志优先权(log level),一般有以下几种优先权(从低到高): debug # 程序或系统的调试信息 info # 一般信息, notice # 不影响正常功能,需要注意的消息 warning/warn # 可能影响系统功能,需要提醒用户的重要事件 err/error # 错误信息 crit # 比较严重的 alert # 必须马上处理的 emerg/oanic # 会导致系统不可用的 * # 表示所有的日志级别 none # 跟* 相反,表示啥也没有 syslog的日志优先权默认是info,这时候用syslog为debug(最低日志优先权)来写日志,syslog服务是不会写入日志的。

2024年1月23日

Xpath金手指

最近在搞puppeteer的自动化,有很多地方需要用到CSS Selector,但是某些地方又是用Xpath方便,金手指放一下,备查: Test queries in the Xpath test bed: Xpath test bed (whitebeam.org) Browser console $x("//div") Works in Firefox and Chrome. #Selectors Descendant selectors h1 //h1 div p `//div//p ul > li `//ul/li ul > li > a //ul/li/a div > * //div/* :root `/ :root > body /body Attribute selectors #id //*[@id="id"] .class //*[@class="class"] …kinda input[type="submit"] //input[@type="submit"] a#abc[for="xyz"] `//a[@id=“abc”][@for=“xyz”] a[rel] //a[@rel] a[href^='/'] `//a[starts-with(@href, ‘/’)] a[href$='pdf'] //a[ends-with(@href, '.pdf')] a[href*='://'] //a[contains(@href, '://')] a[rel~='help'] //a[contains(@rel, 'help')] …kinda Order selectors ul > li:first-of-type `//ul/li[1] ul > li:nth-of-type(2) //ul/li[2] ul > li:last-of-type //ul/li[last()] li#id:first-of-type `//li[1][@id=“id”] a:first-child //*[1][name()="a"] a:last-child //*[last()][name()="a"] Siblings h1 ~ ul `//h1/following-sibling::ul h1 + ul //h1/following-sibling::ul[1] h1 ~ #id //h1/following-sibling::[@id="id"] jQuery $('ul > li').parent() `//ul/li/.. $('li').closest('section') //li/ancestor-or-self::section $('a').attr('href') `//a/@href $('span').text() //span/text() Other things h1:not([id]) `//h1[not(@id)] Text match `//button[text()=“Submit”] Text match (substring) //button[contains(text(),"Go")] Arithmetic //product[@price > 2.50] Has children //ul[*] Has children (specific) //ul[li] Or logic `//a[@name or @href] Union (joins results) `//a | //div Class check //div[contains(concat(' ',normalize-space(@class),' '),' foobar ')] Xpath doesn’t have the “check if part of space-separated list” operator, so this is the workaround (source). ...

2024年1月22日

禁掉Rsyslog的dns解析

网管检查流量图的时候发现,udp的流量很多 看了看日志: Jun 28 00:39:28 172.16.0.1 %ASA-6-305011: Built dynamic UDP translation from inside:172.16.36.2/2160 to outside:124.243.230.6/2160 Jun 28 00:39:28 172.16.0.1 %ASA-6-302015: Built outbound UDP connection 1369422617 for outside:223.5.5.5/53 (223.5.5.5/53) to inside:172.1... 发现一大堆是查询dns 53的 杀了无关进程,继续,还有是那么多的udp 53 dns查询 查了半天才发现,是rsyslog记录日志的时候反查ip的域名导致的,由于是内网域名都不对,所以ip查不到,就不停的往公网dns发查询,导致udp流量激增。 知道原因就知道如何解决了 Centos下,rsyslog增加-x -Q禁止解析的参数: vi /etc/sysconfig/rsyslog # Options for rsyslogd # Syslogd options are deprecated since rsyslog v3. # If you want to use them, switch to compatibility mode 2 by "-c 2" # See rsyslogd(8) for more details SYSLOGD_OPTIONS="-c 5 -x -Q" Ubuntu下,方法一样,文件不一样 ...

2024年1月21日

Java业务上kubernetes的注意点

java业务上k8s的话,看到一篇比较好的文章,要注意的地方: apiVersion: apps/v1 kind: Deployment metadata: name: java-web namespace: ops labels: app: java-web spec: selector: matchLabels: app: java-web replicas: 2 strategy: type: RollingUpdate template: metadata: name: java-web annotations: # 第一点:新增注解 loki.io/scrape: 'true' # 抓取直接输出的日志到loki里 prometheus.io/path: /metrics #采集的监控地址 prometheus.io/port: '2112' #采集暴露的监控端口 prometheus.io/scrape: 'true' #打开采集开关 labels: app: java-web spec: imagePullSecrets: # 第二点:添加权限 - name: my-docker #只有该用户才有pull镜像的权限 containers: - name: java-web image: hb.ops.top/ops/java-web:5917f92c imagePullPolicy: IfNotPresent readinessProbe: # 第三点:新增存活检测,当前是针对监控端口进行存活检测,也就是说只有当监控端口起来了,程序才算完全启动 httpGet: port: 2112 path: /metrics/prometheus initialDelaySeconds: 60 successThreshold: 1 failureThreshold: 3 timeoutSeconds: 5 startupProbe: httpGet: port: 2112 path: /metrics/prometheus initialDelaySeconds: 60 successThreshold: 1 failureThreshold: 3 timeoutSeconds: 5 livenessProbe: httpGet: port: 2112 path: /metrics/prometheus initialDelaySeconds: 60 successThreshold: 1 failureThreshold: 3 timeoutSeconds: 5 resources: # 第四点:设置资源限制,如果是java程序,建议limit比request大,这样可以合理分配堆内存和非堆内存 requests: memory: 1024Mi limits: memory: 2048Mi ports: - name: web-port containerPort: 8889 env: # 第五点:设置环境变量,可以设置时区,指定EVN环境,添加JAVA参数等 - name: JVM_OPTS value: -javaagent:/opt/skywalking/skywalking-agent.jar -Xmx1G -Xms1G - name: TZ value: Asia/Shanghai - name: APOLLO_LABEL value: gray - name: SW_AGENT_NAME value: 'k8s-java-web' - name: SW_AGENT_COLLECTOR_BACKEND_SERVICES value: '10.0.0.123:11800' - name: ENV value: prod --- apiVersion: v1 kind: Service metadata: labels: app: java-web name: java-web namespace: ops spec: ports: - name: java-web-port port: 8889 protocol: TCP targetPort: 8889 nodePort: 30009 selector: app: java-web sessionAffinity: None type: NodePort status: loadBalancer: {} 上面忽略了启动命令,其实容器内的启动命令也是很有学问的。 ...

2024年1月19日

kubernetes中Pod资源清单和解释

Pod的yaml文件的资源清单和解释,备查 apiVersion: v1 #必选,版本号,例如v1 kind: Pod #必选,资源类型,例如 Pod metadata: #必选,元数据 name: string #必选,Pod名称 namespace: string #Pod所属的命名空间,默认为"default" labels: #自定义标签列表 - name: string spec: #必选,Pod中容器的详细定义 containers: #必选,Pod中容器列表 - name: string #必选,容器名称 image: string #必选,容器的镜像名称 imagePullPolicy: [ Always|Never|IfNotPresent ] #获取镜像的策略 command: [string] #容器的启动命令列表,如不指定,使用打包时使用的启动命令 args: [string] #容器的启动命令参数列表 workingDir: string #容器的工作目录 volumeMounts: #挂载到容器内部的存储卷配置 - name: string #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名 mountPath: string #存储卷在容器内mount的绝对路径,应少于512字符 readOnly: boolean #是否为只读模式 ports: #需要暴露的端口库号列表 - name: string #端口的名称 containerPort: int #容器需要监听的端口号 hostPort: int #容器所在主机需要监听的端口号,默认与Container相同 protocol: string #端口协议,支持TCP和UDP,默认TCP env: #容器运行前需设置的环境变量列表 - name: string #环境变量名称 value: string #环境变量的值 resources: #资源限制和请求的设置 limits: #资源限制的设置 cpu: string #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数 memory: string #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数 requests: #资源请求的设置 cpu: string #Cpu请求,容器启动的初始可用数量 memory: string #内存请求,容器启动的初始可用数量 lifecycle: #生命周期钩子 postStart: #容器启动后立即执行此钩子,如果执行失败,会根据重启策略进行重启 preStop: #容器终止前执行此钩子,无论结果如何,容器都会终止 livenessProbe: #对Pod内各容器健康检查的设置,当探测无响应几次后将自动重启该容器 exec: #对Pod容器内检查方式设置为exec方式 command: [string] #exec方式需要制定的命令或脚本 httpGet: #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port path: string port: number host: string scheme: string HttpHeaders: - name: string value: string tcpSocket: #对Pod内个容器健康检查方式设置为tcpSocket方式 port: number initialDelaySeconds: 0 #容器启动完成后首次探测的时间,单位为秒 timeoutSeconds: 0 #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒 periodSeconds: 0 #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次 successThreshold: 0 failureThreshold: 0 securityContext: privileged: false restartPolicy: [Always | Never | OnFailure] #Pod的重启策略 nodeName: <string> #设置NodeName表示将该Pod调度到指定到名称的node节点上 nodeSelector: obeject #设置NodeSelector表示将该Pod调度到包含这个label的node上 imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定 - name: string hostNetwork: false #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络 volumes: #在该pod上定义共享存储卷列表 - name: string #共享存储卷名称 (volumes类型有很多种) emptyDir: {} #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值 hostPath: string #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录 path: string #Pod所在宿主机的目录,将被用于同期中mount的目录 secret: #类型为secret的存储卷,挂载集群与定义的secret对象到容器内部 scretname: string items: - key: string path: string configMap: #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部 name: string items: - key: string path: string 在kubernetes中基本所有资源的一级属性都是一样的,主要包含5部分: ...

2024年1月19日

url中的字符转义

遇到个怪问题,设置http_proxy的时候有用户密码,命令如下: export http_proxy=http://user\2016:PmnQ 2016@192.168.0.1:3128 结果不生效,仔细观察上面的命令: 用户名其实是:“user\2016”,里面有个反斜杠\ 而密码是:“PmnQ 2016”,里面有个空格 这下麻烦了,命令过不去啊。 反复搜索找到了字符转义表,第一个图是可以安全转义的: 下面这张是不安全的: 转一下吧: \ 的16进制HEX是%5C,空格的16进制HEX是%20 最后的语法: export http_proxy=http://user%5C2016:PmnQ%202016@192.168.0.1:3128 搞定收工。

2024年1月19日

如何通过extundelete恢复删除文件

考古篇,记录下来,现在都是xfs了,但是方法不能忘啊! 恢复过程如下: 1、安装extundelete yum -y install e2fsprogs e2fsprogs-libs e2fsprogs-devel wget http://jaist.dl.sourceforge.net/project/extundelete/extundelete/0.2.4/extundelete-0.2.4.tar.bz2 tar -jxvf extundelete-0.2.4.tar.bz2 cd extundelete-0.2.4 ./configure make make install 2、卸载要恢复的分区 如果你误删除的分区是/dev/sda2,那么首先需要umount 这个分区的挂载点 3、开始恢复 首先df -lh查看分区的使用情况,选择一个剩余空间足够容纳要恢复的文件大小的分区,例如你的/home分区剩余100G,你需要恢复的文件小于100G,那么你可以cd /home 然后进行恢复操作 cd /home 恢复单个文件或文件夹 extundelete /dev/mapper/vg_localhost-lv_home –restore-files 文件名 我是直接恢复整个分区 extundelete /dev/mapper/vg_localhost-lv_home –restore-all 然后会在当前目录生成一个恢复文件夹,进去找你要的文件就可以了

2024年1月19日