浅析代理 Nginx功能 正向代理:客户端不知道服务端,也就是说客户端需要配置代理服务器来,代理服务器再去访问真正的服务端。挂梯子就是正向代理的应用。 反向代理:服务端不知道客户端,客户端不需要进行任何配置,用户只请求反向代理地址,反向代理服务器选择目标服务器,获取数据返回客户端。 负载均衡:在反向代理中,我们可以使用负载均衡去将请求分配到不同的服务器上。 动静分离:Nginx将接到的请求分为动态请求和静态请求,这在实际的应用中对应了前后端。 Nginx原理 Master - Worker 模式 在启动Nginx后,我们通过ps -ef可以发现有关nginx的进程有一个master process和n个worker process,并且我们查看nginx监听的端口,可以看到监听了80端口。
Master process: master进程的作用主要是读取并且验证nginx.conf, 并且管理worker进程,给worker进程传递消息。
Worker process: 每一个Worker进程都维护了一个线程去处理连接和请求(避免一个线程造成的线程切换问题),一般cpu几核就有几个worker进程。
所有的worker进程都是从master进程fork()过来的,worker进程提供好listenfd的接口, 为了保证只有一个进程处理连接,所有的Worker进程在注册listenfd接口读取事件前抢互斥锁accept_mutex,抢到互斥锁的那个进程注册listenfd读事件,在读事件里面调用accept接受连接,开始处理请求。 Nginx采取上面的这种进程模型的好处: 独立进程不需要加锁,省去锁的开销 独立进程互不影响,服务不会中断 独立进程异常退出,只影响该进程的请求 Cache Manager process: 除了上面两个进程外,我们还可以看到Cache Manager process, 与之对应的还有Cache Loader process(在nginx服务启动的时候由主进程生成,缓存数据加载完成后退出), Cache Manager process负责缓存索引的还礼,通过缓存机制,可以提高对请求的响应效率。 模块化 Nginx从功能上可以分为:
Handlers: 处理请求,进行输出内容和修改headers等,一般只有一个 Filters: 接收请求进行链式修改 Proxies: Nginx的Htpp Upstream等模块,主要和后端进行交互,实现服务代理和负载均衡等 Nginx(内核)本身做的工作实际很少,当它接到一个 HTTP 请求时,它仅仅是通过查找配置文件将此次请求映射到一个 location block,而此 location 中所配置的各个指令则会启动不同的模块去完成工作,因此模块可以看做 Nginx 真正的劳动工作者。通常一个 location 中的指令会涉及一个 Handler 模块和多个 Filter 模块(当然,多个location可以复用同一个模块)。Handler模块负责处理请求,完成响应内容的生成,而 Filter 模块对响应内容进行处理。
...
log4j线上不打印日志 问题描述 使用log4j的项目(包名com.abc)在服务器上未打印日志,本地控制台打印正常,文件中未输出。
日志文件能够正常生成,并且也有日志打印,但是业务日志没有打印。
只打印了com.xxx包下的日志。
问题分析 出现日志无法打印的问题大概率就在logback.xml的配置上,具体logback的配置参数的具体解释网上有很多,具体可以看一下
https://juejin.cn/post/7200549600590282789
在logback.xml中可以发现一个配置项:
1 2 3 4 5 6 7 <!-- 本地测试时,可以修改level 以便打印debug日志 --> <!--定义com.xxx包下的类日志向哪个appender写入日志--> <logger name="com.xxx" level="info" additivity="false"> <appender-ref ref="FILE-debug" /> <appender-ref ref="FILE-error" /> <appender-ref ref="STDOUT" /> </logger> logger标签可以指定特定包的输出,additivity字段含义如下
如果logger里面配置了additivity=“false”,就会覆盖root的,只打印一遍;但是additivity=“true”,就会向上层再次传递,不会覆盖,而是打印两遍!
通过查看logback.xml文件我们可以发现,整个文件中只使用了一个logger打印com.xxx包下的日志,而我们的项目的package为com.abc。
问题解决 至此问题已经排查完毕,那问题的解决也很简单,新增加一个com.abc的logger即可
1 2 3 4 5 6 7 <!-- 本地测试时,可以修改level 以便打印debug日志 --> <!--定义com.xxx 包下的类日志向哪个appender写入日志--> <logger name="com.abc" level="info" additivity="false"> <appender-ref ref="FILE-debug" /> <appender-ref ref="FILE-error" /> <appender-ref ref="STDOUT" /> </logger>
Java 常用工具 redis redis可视化工具: https://goanother.com/cn/ MQ kafkatool: https://www.kafkatool.com/
2023一组技术提升计划 2023年整体技术方面聚焦在代码规范和代码质量上面,希望能够通过推动代码规范的执行和代码质量的审核来提升软件品质。
规范 代码规范:统一代码规范,使用阿里巴巴代码规范,IDEA安装阿里巴巴规范插件。
代码规范中强制要求的必须执行,其它项按自己的风格使用。 旧代码不做要求,新代码强制执行。 二季度结束后和年度结束后,随机抽查新代码,形成考核结果。 文档规范:中大型项目需要有开发文档,就写在README中,讲述开发逻辑和开发中不为人知的秘密
文档书写使用Markdown语法,每个项目的README中都有语法链接 文档中包含但不限于需求描述,实现方案,升级记录,注意事项等。 旧代码不做要求,新代码强制执行。 二季度结束后和年度结束后,随机抽查新代码,形成考核结果。 开发文档模板会在年前提供出来。 为什么要进行代码规范和文档规范 目前代码中,因个人风格的不通,代码风格差异也比较大,在维护代码的时候要去不停的适应不同人的代码风格,因此规范代码风格,减少维护适应代码时间。 目前代码中,因为没有好的规范,所以部分地方还是存在风险,通过实行好的代码规范来避免风险产生问题。 目前代码中,因为没有文档,所以每次看代码遇到不懂的地方需要去猜,可能存在误差。 质量 代码审核:周六分享会开发人员把自己上周的开发工作说一遍,视开发内容决定是否需要代码审核 如果需要代码审核,必须要有开发文档,让组员能够理解在干什么 使用代码IDEA插件搭配Upsource快速审核,https://www.jianshu.com/p/fab6539a6749 写代码的人讲解自己的代码,阐述清楚为什么这么写 鼓励自己提交代码审核,量化代码审核次数 内容输出 完善一组wiki,问题和开发技术输出, 周六分享会后技术分享同样提交wiki 周六分享会后技术分享完毕后如果有想分享的东西同样可以分享
Java启动脚本详解 在工作的过程中,不免要遇到与服务启动相关的问题,很多问题很好解决,但是有些问题可能需要请教总部的大佬才能解决。由于最近遇到了一次nohup启动两个服务进程的问题,其中一个进程因为端口占用一直在不断重启,故深入研究一下运管的启动和启动脚本的启动。
__service脚本 __service脚本有很多种,其实作用都一样,但是因为写法不同,所以在看的过程中会感觉很痛苦,每次都会遇到新的语法。这里以Jsvc启动和nohup启动两种方式进行详细解读。
__service脚本 - Jsvc启动 什么是Jsvc jsvc可以理解为类unix系统下的启动并守护java进程的可执行程序,属于Apache Commons Daemon项目。
简单理解,就是启动java服务,并且维护java服务的运行。
Jsvc的优缺点 一个java服务可能存在多个进程,通过jsvc控制不同进程 java进程启动、停止或者退出时,执行init stop destroy等方法,java应用能通过这些方法。执行一下必要的操作 Jsvc的原理 公司使用jsvc的框架都需要引入一个laucher的依赖,这个launcher里面就是具体的启动的代码,可以看到其实是在mainClass外包装了一层,可以执行start,init,stop等操作来管理Java服务。
Jsvc __service脚本详解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 #!/bin/bash _ServerName=placeholder JAVA_HOME=${JDK_PATH} CLASSPATH=.:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar _Xms=1024M _Xmx=2048M _Xmn=512M _MetaspaceSize=512M _MaxMetaspaceSize=1024M _DIR="$( cd "$(dirname "$0")" && pwd )" _HOME_DIR=$(dirname "$_DIR") _JSVC=${_HOME_DIR}/bin/linux/Jsvc _Classpath=${CLASSPATH}:"${_HOME_DIR}/config":"${_HOME_DIR}/lib/*":"${_HOME_DIR}/../../conf" _MainClass=com.xx.AlarmBootstrap _StartCLASS=com.xxx.JsvcLauncher _Pid=${_HOME_DIR}/temp/${_ServerName}.pid #_LogOut=${_HOME_DIR}/logs/${_ServerName}.log _LogOut=/dev/null _LogErr=${_HOME_DIR}/logs/Jsvc.log echo "service name: $_ServerName" do_exec() { $_JSVC -D${_ServerName} -home $JAVA_HOME -cwd ${_HOME_DIR}/config -Djava.net.preferIPv4Stack=true -Dcom.sun.jndi.ldap.connect.pool.protocol="plain ssl" -XX:MetaspaceSize=${_MetaspaceSize} -XX:MaxMetaspaceSize=${_MaxMetaspaceSize} -Xms${_Xms} -Xmx${_Xmx} -Xmn${_Xmn} -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError -XX:+DisableExplicitGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xloggc:${_HOME_DIR}/logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=8M -Djava.io.tmpdir=${_HOME_DIR}/temp -Dloader.main=${_MainClass} -wait 60 -pidfile $_Pid -outfile ${_LogOut} -errfile ${_LogErr} -cp ${_Classpath} $1 ${_StartCLASS} } case "$1" in start) do_exec echo "${_ServerName} started" chmod -R 777 ${_HOME_DIR} chmod -R 777 ${_HOME_DIR}/../../logs ;; stop) if [ -f "$_Pid" ]; then SERVICE_PID=`cat ${_Pid}` kill -15 ${SERVICE_PID} fi ;; restart) if [ -f "$_Pid" ]; then do_exec "-stop" do_exec echo "${_ServerName} restarted" else echo "service not running, will do nothing" exit 1 fi ;; status) ps -ef | grep ${_ServerName} ;; *) echo "usage: service ${_ServerName} {start|stop|restart|status}" >&2 exit 3 ;; esac _ServiceName: ServiceName就是段标识的名称,也可以看到后面的Jsvc启动使用了这个ServiceName,$_JSVC -D${_ServerName},这里的-D是指 -D<name>=<value> set a Java system property
...