ClassLoader

深入理解ClassLoader 是什么? 相信大家在准备面试的时候都会背过Java的类加载机制,双亲委派模型。 就是当JVM收到一个类加载请求的时候,当前的类加载器首先会将类加载器传递给它的父类,父类尝试加载,如果失败继续向上传递,如果所有的父类都无法加载,则当前类加载器自己处理。 那这段话理解起来还是比较容易的,但是具体是如何做的呢?下面进行分析。 为什么? 那为什么要使用双亲委派模型吗?当前类加载器自己处理不行吗? 如果我们自己写了一个java.lang.Object类的话,那当前的类加载器直接选择加载的话,那加载的类中就会有两个一样的Object类。应用程序将会变的非常混乱。 怎么做? 下面从源码开始看Java是如何进行类加载的。 ClassLoader 介绍 先进入ClassLoader类中public abstract class ClassLoader, 可以先看一下doc,介绍了ClassLoader这个类, A class loader is an object that is responsible for loading classes. The class ClassLoader is an abstract class. Given the binary name of a class, a class loader should attempt to locate or generate data that constitutes a definition for the class. A typical strategy is to transform the name into a file name and then read a “class file” of that name from a file system. ...

<span title='2024-12-19 18:11:06 +0800 +0800'>December 19, 2024</span>&nbsp;·&nbsp;3 min&nbsp;·&nbsp;YuanPeng

一个基于Quic协议的Http转Udp代理工具

一个基于Quic协议的Http转Udp代理工具 背景 某地存在A和B两个网络,A中搭建了上级平台,用户平时正常办公使用该平台。B搭建了下级平台,接入设备。 两个网络的边界端口映射有一个唯一的限制:两个网络之间端口映射只能映射Udp的端口 现在B网中的设备想要接入A网,B网中的设备接入基本上都是http请求,所以整体的对接只需要对接http请求。 探索 针对该问题,进行相关的预研探索。目前已有的条件就是udp通道的边界,那么实现该目标的办法就是利用该udp通道去传输http请求,也就是说要开发http-udp,udp-http的代理工具。 TCP和UDP 处在TCP/IP模型的传输层中,传输控制协议TCP和用户数据报协议UDP TCP可靠,UDP不可靠 Http 处在TCP/IP模型的应用层中,基于tcp协议的应用 上述的概念比较清晰,其中也暴露了一个非常关键的点,TCP可靠,UDP不可靠。我们都知道tcp的三次握手和四次挥手,tcp是面向连接的协议,通过严格的确认连接来保证整个连接的正常通信。而udp面向非连接,不需要维护连接状态,只需要交付报文即可。 经过一些了解后,如果要开发一个http和udp互相转换的代理工具,主要需要解决以下的问题: Udp不可靠,存在丢包的情况 Udp有报文大小限制,1480bytes Udp不保证数据顺序 对于一个网络方面的小白来说,想要独自开发上述代理工具至少需要半年起步。 既然从0开发需要耗时太长,那么就需要找目前已经存在的代理工具,经过搜索发现相关内容少之又少。 在一次偶然的搜索中发现http3.0是基于Quic协议开发,而Quic协议又是基于udp的,那么似乎找到了一丝问题解决的可能性。 HTTP/3 & Quic HTTP/3 is the third major version of the Hypertext Transfer Protocol used to exchange information on the World Wide Web, complementing the widely-deployed HTTP/1.1 and HTTP/2. Unlike previous versions which relied on the well-established TCP (published in 1974),[2] HTTP/3 uses QUIC, a multiplexed transport protocol built on UDP.[3] On 6 June 2022, IETF published HTTP/3 as a Proposed Standard in RFC 9114.[4] ...

<span title='2023-11-25 11:39:30 +0800 +0800'>November 25, 2023</span>&nbsp;·&nbsp;4 min&nbsp;·&nbsp;yuanpeng11

Maven之Deploy使用

Maven之Deploy使用 背景 目前公司里的项目定制一般不需要用到Deploy(上传jar包到af仓库上),定制只是下载依赖然后使用。最近开发组件过程中,由于需要组件提供对外api给其它组件使用,在使用的过程中也不是特别顺利,所以记录一下Deploy的使用。 Deploy Deploy是Maven生命周期的最后一个环节,作用是上传最终的成果物到远程仓库中,共享给其它开发人员和工程。使用方法如下: Step 1:需要在settings.xml配置af仓库的用户名和密码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <!-- servers | This is a list of authentication profiles, keyed by the server-id used within the system. | Authentication profiles can be used whenever maven must make a connection to a remote server. |--> <servers> <!-- server | Specifies the authentication information to use when connecting to a particular server, identified by | a unique name within the system (referred to by the 'id' attribute below). | | NOTE: You should either specify username/password OR privateKey/passphrase, since these pairings are | used together. | --> <server> <id>xxx-release</id> <username>xxx</username> <password>xxx</password> </server> </servers> Step 2:要Deploy的module的pom文件中添加要上传的af仓库,id要和上面settings.xml中的id对应 ...

<span title='2023-06-21 18:40:34 +0800 +0800'>June 21, 2023</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;yuanpeng11

DEBUG

浅析几种不同的DEBUG方法,欢迎大家补充 远程DEBUG 当本地的代码因为各种原因无法正常启动的时候,可以选择使用远程DEBUG,这种方法要求和线上的代码一致,具体方法如下, Step1: 新建一个remote jvm debug,填入需要线上服务所在服务器ip,复制Command line arguments for remote JVM,选择需要debug的module。 Step2: 服务器中启动脚本修改添加Step1中复制的arguments 1 java -jar -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 remote-debug-1.0-SNAPSHOT.jar 公司的jsvc启动的话,要放在mainclass前面,注意JDK的版本,查看JAVA_HOME的版本,jdk8就配在jdk8的启动命令处,jdk11同理。配置好启动脚本后,重启服务。 1 $_JSVC -D${_ServerName} -home $JAVA_HOME -cwd ${_HOME_DIR}/config -umask 0011 -Djava.security.egd=file:/dev/./urandom -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 *-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005* -Dloader.main=${_MainClass} -wait 60 -pidfile $_Pid -outfile ${_LogOut} -errfile ${_LogErr} -cp ${_Classpath_jdk8} -procname ${_SystemctlName} $1 ${_StarCLASS} Step3: 重启好服务后,IDEA启动远程debug。显示连接正常即可,如果连接time out查询服务5005端口是否起来,如果没有起来则查看服务启动问题。 Step4: 打断点,线上服务页面操作即可进入断点。 Nginx代理DEBUG 在进行某次问题的排查的时候,需要debug单点登录(外部依赖)的流程,线上和线下的组件代码不一致,但是依赖的单点登录jar包一致,测试发现IDEA远程DEBUG并不能debug外部依赖的jar包。 由于线上服务使用的频率不高,所以直接启动本地的代码作为线上服务,使用nginx反向代理线上服务到本地,此时就可以愉快的进行外部jar包的debug,具体方法如下。 Step1: 启动本地服务 Step2: 找到集群代理组件所在的服务器,进入代理组件内部/opt/opsmgr/web/components/cluster.1/data/proxy_section,修改proxy_https.conf文件,找到需要反向代理的组件location,以iface为例,修改proxy_pass的参数为本地启动服务的地址。 1 2 3 4 5 6 7 8 9 10 location /iface-web/ { proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cookie_path /iface-web "/iface-web;httponly; secure"; #proxy_pass http://10.195.185.23:8037/iface-web/; proxy_pass http://10.195.169.165:8037/iface-web/; } Step3: 重启nginx ...

<span title='2023-05-08 18:52:46 +0800 +0800'>May 8, 2023</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;yuanpeng11

Nginx代理配置实战

浅析代理 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 模块对响应内容进行处理。 ...

<span title='2023-03-23 19:01:29 +0800 +0800'>March 23, 2023</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;yuanpeng11