第一天
上午九点到下午三点左右,入职活动结束,被带到工位。
-
安装环境,
- jdk 1.8 64位
- maven这边工程通过maven构建,推荐使用maven3以上版本
- IDEA 下载。idea自带maven插件,但需要在默认的settings.XML文件中添加内部的maven远程仓库地址
- git下载安装,代码寄存在gitlab。
- 所有安装环境部署完毕之后,了解工具的使用
-
熟悉团队的各位成员,相互认识和学习
- 注意事项:
- 每周三晚上八点之前提交周报:写这一周的学习内容,遇到的问题,解决的方法,什么收获
- 每天的学习中遇到的问题记下来,晚上找时间向师傅请教。做到当天的问题当天解决。
第二天
- 学习阿里的代码编程规范
- 根据规范中总结的经验,结合自己之前编码中的个人习惯进行反思,发现自己存在之前存在很多编码不规范的地方,对这些地方进行重点总结(规范内容较多,后续还会继续看)
- 了解spring boot。由于内网资料看不到,自己在外网搜一下相关教程,并使用spring boot搭建一个hello world程序。
第三天
熟悉信用证基本概念,了解国内跟单流程
-
java基础复习:
-
jvm类加载机制
- 类加载器
类加载器类型 名称 负责加载 加载的类 Bootstrap ClassLoader 引导类加载器 核心java class 所有java.开头的类 Extension ClassLoader 扩展类加载器 扩展的java class javax.开头的、放在ext目录下面的 System ClassLoader 系统类加载器 用户程序自身的class 系统中配置的环境变量classpath路径下面的类 - 类加载机制
- 全盘负责:当一个classLoader加载一个类的时候,该class所依赖的所有class 也由这个classloader负责载入。除非是显示的使用另一个classLoader载入。
- 双亲委托:先让父类的加载器加载,如果父类加载器无法加载的话,再该类的加载器进行加载。
垃圾回收
内存模型
基础集合类
jdk 8 新特性
-
servlet
- 生命周期:
- 初始化:servlet容器会在启动时初始化一些servlet,如果在web.xml中的servlet标签之间加入load-startup 1
- 生命周期:
-
-
maven工具学习,重点关注如下问题
-
如何解决jar冲突
在项目中的pom文件中将冲突依赖排除,具体写法:比如我们要讲一个依赖中的相应jar包排除
<dependency> <groupId>com.xxx.xx</groupId> <artifactId>xxx</artifactId> <version>x</version> <exclusions> <exclusion> <artifactId>com.springsource.slf4j.org.apache.commons.logging</artifactId> <groupId>org.slf4j</groupId> </exclusion> </exclusions> </dependency>
-
第四天
-
START
- 之前有过java web开发经验,对于servlet的生命周期以及基本开发过程有了解,但对于filter和listener了解不是很深。对这些盲点进行逐一攻破
- 对web.xml的所有常用的配置深入掌握(规范、原理),对不常用的标签要有所了解
- 能够准确描述出servlet、filter、listener各自发挥的作用、生命周期、加载顺序等
- 使用filter、servlet、listener编写一个动态网页小demo
- filter servlet listener:
- 初始化顺序:listener -》filter -》servlet
- 销毁顺序:servlet- 》filter-》listener(和初始化顺序相反)
-
web.xml
-
filter
- 定义:过滤器,对web服务器所管理的web资源:例如jsp、servlet、静态文件等进行拦截。例如实现URL级别的权限访问、过滤敏感词汇
- 主要用于对
httpServletRequest
进行预处理,也可以对httpServletResponse
进行后处理。 - 完整流程:FIlter对用户请求预处理--》servlet对请求进行做出相应--》FIlter在对相应进行后处理
filter链:在一个web应用中,可能会有多个filter,这些filter 组合起来称作filter链。filter的执行顺序根据filter在web.xml中定义的顺序一致
filer 生命周期:和servlet一样,filter的创建和销毁由web容器负责,当web容器启动时,将创建filter实例对象,调用init方法。filer对象只会创建一次,故filer是单例的。在多线程情况下会存在线程安全性问题,故不要在file类中定义属性变量,最好是无状态的,如果非要使用,一定要使用线程安全的类。比如并发包中的类。
filer的四种拦截方式:REQUEST 、FORWORD、 INCLUDE、ERROE
REQUEST:直接访问目标资源
FORWORD:转发
INCLUDE:例如:<jsp:include>
-
ERROR:web.xml中配置error-page时
可以在
filter-mapping
中添加多个dispatch子元素 filer用在哪:权限检查、编码过滤
如何使用filer:实现javax.servlet.Filer接口,并覆盖doFilter方法
public class MyFilfer implements Filer{ @Override public void doFilter(ServletRequest srep, ServletResponse sresp, FilterChain fc) { //TODO } }
在web.xml中添加filter
<filter> <filter-name>myFilter</filter-name> <filer-class>MyFilfer</filer-class> </filter> <filter-mapping> <filter-name>myFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
-
servlet
- 生命周期:servlet实例的创建有两个时机:
- 客户端第一次请求某个servlet时,系统创建servlet的实例
- web应用启动时立刻创建servlet 实例,需要在web.xml中配置
<load-on-startup>1(或大于1)</load-on-startup>
- 容器中只存在一个servlet实例。单例多线程的。故也是线程不安全
-
Demo :使用servlet 和 filter 实现登录小程序
- filter 对用户请求进行拦截,验证是否登录。如果session有用户信息,则放过。否则redirect到登录页面
- servlet 对登录请求进行处理,将用户信息保存到session中
git分支地址:http://gitlab.alibaba-inc.com/shixu.sx/user_login/tree/master
-
问题解决
JVM性能调优监控常用命令
-
jps :列出jvm中正在运行的进程信息
-q 不输出类名、Jar名和传入main方法的参数 -m 输出传入main方法的参数 -l 输出main类或Jar的全限名 -v 输出传入JVM的参数 shixu.sx@$ jps -l 9520 sun.tools.jps.Jps 17924 org.apache.catalina.startup.Bootstrap 9812 org.jetbrains.jps.cmdline.Launcher 14184 14440 org.jetbrains.idea.maven.server.RemoteMavenServer
-
jstack: 主要用来查看某个java线程堆栈信息
场景:找出某个java 进程中最耗费cpu的java线程,并定位堆栈信息
方案:
-
首先找出该java进程的进程id,比如要找bootstrap进程,
- 在windows环境下,命令行输入:
jps | findstr "bootstrap"
- linux环境下,输入:
jps | grep "bootstrap"
- 在windows环境下,命令行输入:
-
根据进程id,找出该进程内最耗费资源的线程信息
命令行输入:
top -Hp 进程id
, 然后根据列出的线程信息找到time最长的线程id-
将线程id转化为十六进制,然后在命令行输入
jstack 进程id | grep 线程id对应的十六进制数
,根据打印出来的堆栈信息可以知道是哪个线程的问题
-
-
-
jmap: 用来查看堆内存使用情况
使用
jmap -heap pid
查看进程堆内存使用情况。 -
jstat:jvm统计监测工具
S0C、S1C、S0U、S1U:Survivor 0/1区容量(Capacity)和使用量(Used) EC、EU:Eden区容量和使用量 OC、OU:年老代容量和使用量 PC、PU:永久代容量和使用量 YGC、YGT:年轻代GC次数和GC耗时 FGC、FGCT:Full GC次数和Full GC耗时 GCT:GC总耗时 堆内存 = 年轻代 + 年老代 + 永久代 年轻代 = Eden区 + 两个Survivor区(From和To)
查看网络端口命令:
-
windows:
- 查看所有端口占用:
netstat -ano
- 查看指定端口占用:
netstat -ano | findstr "端口号"
- 查看所有端口占用:
-
linux:
- 查看所有端口占用:
netstat -anp
- 查看指定端口占用:
netstat -anp | grep "端口号"
- 查看所有端口占用:
第五天
-
9点半到10点半,学习代码规约
-
问题:
-
规约中一条:避免在有锁的代码块中调用RPC方法,为什么?
A:一般情况下,锁的粒度要越小越好,调用RPC本身就是一种粗粒度的处理,所以不建议放在同步代码块中。其次,RPC远程调用不确定性太多,比如运行时间长、超时、事务回滚等,如果RPC方法需要运行很长时间,那么该锁会一直被占用,导致其他线程等待时间过长。
-
-
-
jvm
- jvm内存区域
- pc寄存器:程序计数器,线程私有,保存当前线程执行的字节码地址,唯一一个没有规定任何OOM的区域
- 虚拟机栈:线程私有,每个线程被创建时都会同时创建一个对应的虚拟机栈,栈中存放着栈帧,每一个栈帧对应一个方法调用。栈帧中保存局部变量表、操作数栈、动态链接等
- 方法区:线程共享,大小可以动态调整,主要存放:类信息(名称、方法、字段等元信息)、静态变量。(注:jdk 8 之后方法区已经不存在,取而代之的是metaspace,一块本地内存,由于类的元数据分配在本地内存中,元空间的最大可分配空间就是系统可用内存空间。)
- java堆:对象和数组都在这里分配空间。线程共享。垃圾回收的主要区域
- 垃圾回收算法回顾
- 遇到的问题
- 在JVM规范中规定,如果线程执行的是非native方法,则程序计数器中保存的是当前需要执行的指令的地址;如果线程执行的是native方法,则程序计数器中的值是undefined。为什么是undefined?如果是undefined的话,那么当cpu再次切换执行到该本地方法是,怎么找到要代码行的地址?
-
-
maven 定义和相关命令回顾
项目管理和构建自动化工具
maven仓库:
本地仓库:第一次运行maven构建,会自动下载所有依赖的jar文件到本地仓库中。它避免了每次构建都引用远程仓库的依赖文件
中央仓库:maven社区提供,不需要配置。
远程仓库:如果maven在中央仓库也找不到依赖的文件,会从用户提供的远成仓库中查找
maven依赖搜索顺序:1. 本地仓库 2. 中央仓库 3. 远程仓库 4. 都找不到,报错编译失败
创建工程:
命令:
mvn archetype:generate -DgroupId=com.companyname.helloworld -DartifactId=helloworld Dpackage=com.company.helloworld -Dversion=1.0-SNAPSHOT
- 构建程序:
命令:
mvn package
- 安装工程:
命令:
mvn install
(安装到本地后,在本地仓库会有该工程,其他的项目可以依赖该工程)
- 生成文档
命令:
mvn site
-
spring
控制翻转和依赖注入:
bean作用域
bean生命周期
依赖注入方式
基于set方法
-
基于构造方法
(二者优劣)
AOP原理,代理模式(动态代理cglib和jdk代理区别)
事务管理(编程式事务和声明式事务)
demo小程序
-
总结:
- 今天主要是对spring的基础知识和核心概念,以及常用的配置等进行了复习。回顾过程中发现,很多知识点停留在会用的水平,对底层实现不了解。比如注解这一块,jvm在加载类的时候遇到注解该怎么处理、注解是如何引入相应的功能的,对这些问题了解以后,还要思考如何自己定义一个注解。周末要对这一点进行深入剖析。同时对于spring boot进行系统学习。
第六天
-
上午和师傅以及徐潇师兄一起探讨了在浏览器输入
www.alibaba.com
,之后发生的一切,结合自己对这个问题的认识,发现自己对阿里整个网络体系以及服务架构了解很不够。- 域名解析:浏览器dns缓存、本地dns缓存、本地host文件、请求根dns服务器解析(查询dns根域,自顶向下进行查询)
- http连接:TCP三次握手,建立连接,客户端与服务器
- 到达阿里负载均衡层(F5或者LVS,F5是硬件实现负载均衡,LVS针对传输层TCP\IP)
- VIPserver\vip
- 统一接入(HTTPS解密成HTTP,这是一个CPU密集型任务,在这里进行处理可以降低下游服务器压力)
- Tengin\apach\NGINX(负载均衡,应用层负载均衡)
- 感想:对阿里的整体网络架构了解还很不够,比如VIP和VIPserver在其中的具体作用,CDN等如何实现加速,怎么更快解析DNS,如果找到一条更短的路由,等等,这些点以后要一一弄明白。
-
spring boot start
今天学习了spring boot,看了springboot的一些视频,对spring boot有了一定的初步的认识,初步了解了spring boot的一些基本理念,如可以替换之前给予xml的配置,可以选用@configuration 和application.properties和application.yml来进行配置spring bean。了解到了spring starters ,通过这个可以减少maven依赖中的版本不匹配问题。
spring boot的学习中,通过运行demo,加深了对spring boot的理解,demo中集成了JPA。接下来会将springboot中加入其它start比如:mybatis、tddl等,进行学习。
感想:基于之前学习spring的基础,spring boot的学习整体顺利。但目前对spring boot的理解更多的是在spring boot的使用上,并理解相关的看到的一些注解,对spring boot的一些原理的还需要后面继续深入。
- 三种启动方式:
- main方法中启动
- mvn:spring-boot:run
- mvn install 然后:java -jar 。。
- controller的使用
- @Controller:处理http请求
- @RestController = @Controller + @ResponseBody:Spring4之后新加的注解,原来返回json需要@ResponseBody配合@Controller
- @RequestMapping:配置url映射
- 获取参数
- @PathVariable:获取URL中的数据
- @RequestParam:获取请求参数中的值
- @GetMapping@PostMapping:组合注解
- 三种启动方式:
第七天
- 今天主要对HSF进行了学习。
在系统越来越复杂的情况下,传统的架构会存在如下的问题:
- 各个模块耦合度过高,导致升级更新困难,一处变处处变
- 扩展性差
- 团队开发困难
- 分布式部署非常困难
而HSF是一个远程RPC调用框架。面向服务,降低耦合性
- HSF:
通过配置provider和consumer的bean就ok。
provider暴露自己提供服务的接口,consumer根据接口进行调用。
返回的对象序列化后,通过网络传输。
感想:关于hsf,今天学习的内容主要是对基本原理和基本概念进行学习,然后运行了一个小demo,对服务的发布和服务的消费进行了简单的实现。接下来还会更深入的学习。
- OCR识别的结果乱码问题:
针对ocr识别的结果中文乱码的问题,我进行了单元测试,最后通过将乱码内容用
iso-8859-1
编码方式转化为字节,然后再用utf-8
解码,解决了这个问题。iso-8859-1
编码方式是不支持中文的,所以当对含有中文的内容使用这种编码方式进行编码的时候,再次解码肯定会出现乱码。
因为java本身是跨平台的语言, 乱码问题在java开发中非常常见,比如java的IO操作、数据库、内存、jav web等多种场景,而最终的问题就是出现在字节和字符的转换上面。
- swift 报文格式
- AutoConfig
- SchedulerX
第八天
- 继续学习HSF框架
通过看文档,理解关于服务提供和服务的消费过程:
- 服务提供者将提供的服务和自己的IP注册至注册中心ConfigServer
- ConfigServer会将服务提供者的IP列表推送至服务消费者
- 服务消费者发起调用时,直接从ConfigServer推送过来的服务提供者的IP列表中选择一个IP发起远程调用
标准的service方式RPC:
- service 定义:基于OSGI的service定义方式
- 底层通信方式:万变不离tcp\ip ,io方面使用异步NIO,并使用长连接
Provider和Consumer的启动和处理过程
- 初识TDDL
问题:单一数据库无法满足性能要求
- 数据切分
- 读写分离
- 系统容灾和主备切换以及运维等问题
TDDL提供用户访问和数据库之前的隔离,实现透明操作
1.直接提供分库分表,读写分离、主从备份等解决数据库扩展问题的功能.
2.基于配置模型构建的包括数据库在线扩容、准实时数据同步服务、运维平台等支撑系统。
核心设计:
- SQL解释器 :语法树、查询匹配规则、分库分表
- 查询优化器
- 执行器
HSF原理
HSF架构
HSF服务架构主要几块组成:
- ConfigServer: 用于服务的注册与发现,server通过向ConfigServer注册自己的服务,会在ConfigServer注册自己的服务信息,如服务地址,发布的接口,服务版本等内容。client端可以从ConfigServer订阅自己想要的服务,之后ConfigServer就会把订阅的服务的信息发送给client,之后client和server就可以建立连接,进行RPC调用了。
- Diamond: 主要用于一些动态的配置内容,例如ConfigServer的地址,路由匹配,动态负载等配置。这些配置内容,可以通过在HSF服务治理网站上进行配置。
- Redis:负责存储HSF的元数据,consumer和provider隔一段时间会将调用信息进行上报,同时存储了应用名和服务映射等信息。
服务注册发现流程
- Provider从Diamond中获取Configserver的地址、类型等信息。
- Provider在Configserver上注册自己的IP地址、端口号、服务名、版本号、Group号信息。
- Provider定期将元数据(调用次数、服务状态等等)上报给Redis,用于服务治理。
- Consumer从Diamond中获取Configserver的地址、类型等信息。
- Consumer根据服务名、版本号、Group号信息向Configserver订阅Provider服务。
- Consumer定期将元数据(调用次数、服务状态等等)上报给Redis,用于服务治理。
- Configserver推送Provider的IP地址列表给Consumer。
- Consumer选择一个IP地址,与该Provider建立长连接、通过RpcRequest和RpcResponse进行调用。