很多时候,创新就是相信一定可以实现才有的。很多时候,你觉得这个事情是做不成的,然后直接拒绝掉了,创新就没有了。
但如果相信这个事情一定是可以做成的,你就会想方设法去实现它,这个时候你想出来的东西就是有开创性的,就是创新。
链接
baidu
How to Build a Cybersecurity Career
Bash
YouZack
liaoxuefeng
haizi
achang
springboot的类加载过程
baidu
baidu
URL
https://youmeek.gitbooks.io/linux-tutorial/content/markdown-file/Zsh.html
https://github.com/judasn/Linux-Tutorial
http://www.youmeek.com/
https://nextcloud.longzhaow.com
https://www.longzhao.org
博客使用github page
http://monkeywie.cn/2020/08/20/fast-github-page-with-cloudflare/
书单
CSAPP
计算机网络
深入理解JAVA虚拟机
设计模式
现代操作系统
链接\装载与库
高性能Linux 服务器
数据结构与算法分析
算法导论
LeetCode
LC
- AC - Accepted 答案正确/通过
- WA - Wrong Answer 答案错误
- RE - Runtime Error 运行时错误
- CE - Complie Error 编译错误
- TLE - Time Limit Exceed 超出时间限制/超时
- MLE - Memory Limit Exceed 超出内存限制
- PE - Presentation Error 格式错误
- OLE - Output Limit Exceed 输出超出限制/输出超限
- UKE - Unknown Error 未知错误
函数名有意义,变量名有习惯,代码有缩进,重复代码尽量少,就足够优雅了
保证思路正确,不必过分追求内存占用
技术栈
理论: 计算机原理、计网、数据结构与算法、设计模式
基础: jdk源码、juc、jvm
微服务: spring、spring cloud
数据库: mysql 集中、mybatis
数据库连接池: druid、hakricp
数据库中间件: sharding-sphere、mycat、canal 会一种了解即可
缓存中间件: redis 死磕、memcached了解区别
消息中间件: rocketmq 死磕、kafka 细节, rabbitmq、activemq古董极mq没必要学了
搜索中间件: 有精力 es 死磕, 其他放弃
分布式理论: 分布式ID、分布式lock、分布式幂等、分布式会话
分布式注册中心: eureka、zookeeper、consul、nacos 要知道原理、euraka 可以跳过
分布式配置中心: apollo、disconf、switch、diamond 了解原理, 熟悉
分布式网关: zuul、nginx、kong、gateway 熟悉网关作用, 优缺点;
分布式事务: tcc、seata 熟悉解决什么样的问题
分布式链路跟踪: skywalking、zipkin、cat、pinpoint
任务调度: xxl job、dfs 注意和mq的区别
分布式服务调度: dubbo、grpc、motan、netty 熟悉细节、熟悉核心原理
分布式限流熔断: hystrix、sentinel 闭着眼说出项目设计限流细节和场景
大数据: hive、spark、flink 了解、某些项目需要做数据处理要用到离线批处理
源码
- 服务接入层:反向代理 Nginx;API 网关 Node.js
- 业务逻辑层:
- Web 容器 Tomcat、Jetty
- 应用层框架 Spring、Spring MVC 和 Spring Boot
- ORM 框架 MyBatis
- 数据缓存层:内存数据库 Redis;消息中间件 Kafka
- 数据存储层:关系型数据库 MySQL;非关系型数据库 MongoDB;文件存储 HDFS;搜索分析引擎 Elasticsearch
其中每层都支持水平扩展和高可用
业务层普遍采用微服务架构,微服务之间需要互相调用,于是出现了:
- RPC 框架:Spring Cloud 和 Dubbo。
还有两个非常重要的基础组件:
- Netty (网络通信)
- ZooKeeper (分布式协调, 网络通信模块通过 Netty 实现)
JDK 自带命令
# 1. 编译class
javac -encoding UTF-8 [-d .] Test1.java
# 2. 运行
java com.blog.Test1
# 3. 查看字节码
javap -verbose Test1.class
// -verbose 指定显示更进一步的详细信息
// -c 分解方法代码,即显示每个方法具体的字节码
# 查看堆内存占用情况
jmap -heap [pid]
# 图形界面多功能监测工具, 可以连续监测
jconsole
# 可视化工具(安装 Visual GC 插件)(堆Dump)
jvisualvm
# 查看运行的java进程及 pid
jps
# 查看当前的堆内存
jmap -dump:fromat=b,live,file=1.bin 21384
## b 二进制文件类型
## live 活着的, 会主动进行一次垃圾回收
## file 文件名
# 排查栈上问题
top # 记下 pid
ps H -eo pid,tid,%cpu |grep [pid] # H 打印进程树 -eo 感兴趣的内容 或 top Hp [pid]
jstack [pid]
# 然后将上面 ps 找到的 tid (thread id) 换算为16进制(原来为10进制), 在打印的信息中找到对应的 nid (Native Thread ID). 得到堆栈.
Spring URL 匹配执行方法 AbstractHandlerMethodMapping#lookupHandlerMethod
Spring 解析请求参数名称的过程,参考代码 AbstractNamedValueMethodArgumentResolver#updateNamedValueInfo
其中 NamedValueInfo 的 name 为 @RequestParam 指定的值。
对于一个 Header 的解析,标记 @RequestHeader 参数. 如果它的类型是 Map,则使用 RequestHeaderMapMethodArgumentResolver
,否则一般使用的是 RequestHeaderMethodArgumentResolver
. 它们都继承于 AbstractNamedValueMethodArgumentResolver
,但是应用的场景不同,可以对比下它们的 supportsParameter()
方法
当一个请求来临时,都会进入 DispatcherServlet#doDispatch()
,此方法会根据 Path、Method 等关键信息定位到负责处理的 Controller 方法,然后通过反射去执行,具体反射执行过程代码 InvocableHandlerMethod#invokeForRequest
在试图构建出一个方法参数时,会遍历所有支持的解析器(Resolver)以找出适合的解析器, 代码 HandlerMethodArgumentResolverComposite#getArgumentResolver
标记为 @RequestBody,当遍历到 RequestResponseBodyMethodProcessor
时就会匹配上, 代码 RequestResponseBodyMethodProcessor#supportsParameter
找到 Resolver 后,就会执行 HandlerMethodArgumentResolver#resolveArgument
方法, 会根据当前的请求(NativeWebRequest)组装出 Student 对象并对这个对象进行必要的校验,校验的执行代码: AbstractMessageConverterMethodArgumentResolver#validateIfApplicable
判断:
- 标记了 org.springframework.validation.annotation.Validated 注解;
- 标记了其他类型的注解,且注解名称以 Valid 关键字开头。
if (validatedAnn != null || ann.annotationType().getSimpleName().startsWith("Valid")) {
Object hints = (validatedAnn != null ? validatedAnn.value() : AnnotationUtils.getValue(ann));
Object[] validationHints = (hints instanceof Object[] ? (Object[]) hints : new Object[] {hints});
//执行校验
binder.validate(validationHints);
break;
}
Filter
标记 @ServletComponentScan 就会启用 @WebServlet @WebFilter @WebListener
而过滤器被 @WebFilter 修饰后,就只会被包装为 FilterRegistrationBean 作为一个 InnerBean 注册到 Spring 容器。是找不到该 bean 的.
在 Spring Boot 中会用 FilterRegistrationBean
(org.springframework.boot.web.servlet.FilterRegistrationBean) 来包装 @WebFilter
(javax.servlet.annotation.WebFilter 不属于 Spring) 标记的实例。
创建时使用, 断点在 WebFilterHandler#doHandle() 可以在堆栈上看出对 @WebFilter 的处理是的触发点是 ServletComponentRegisteringPostProcessor
这个类 (继承 BeanFactoryPostProcessor
接口)
最终可以看到,注册的 FilterRegistrationBean
,名称就是 WebFilter
的beanName
- Tomcat 等容器启动时,才会创建 FilterRegistrationBean;
- FilterRegistrationBean 在被创建时(createBean)会创建 TimeCostFilter 来装配自身,TimeCostFilter 是通过 ResolveInnerBean 来创建的;
- Filter 实例最终是一种 InnerBean,我们可以通过下面的调试视图看到它的一些关键信息
同步两个库的一样的表的数据
先使用 canal 这类来同步, 观察 canal 流量, 等降下来后, 加数据源双写.
下游
下游: 接收数据的一侧 (业务侧)
-
调用的时候, 是为了提供给对方数据. 所以对方是下游 (别人依赖你)
-
调用的时候, 是为了使用对方的数据. 所以对方是上游
-
多帮助平级同事
-
掌握工作汇报的方式
首先,不要把汇报当作负担当作浪费时间。汇报其实是双向的,你跟上级多沟通的话,他可以反馈给你更多的信息,这个信息可能是你工作的方向,也可能是给你的一些资源,还可能是告诉你上级想要什么。因为你和你的上级其实在一个信息层面上是不对等的,他能收到更上级的信息,比如公司策略方面的信息。
在一般的架构图中,都是"底层"为"上层"提供服务。数据从 “数据” 层流向 “model” 层,进而流向 “logic” 层,再流向 “控制器” 层,最后到服务调用的最前端。所以,数据库层就是应用层的上游。反之为下游。
前序(根左右),中序(左根右),后序(左右根)