序
又到了写年终总结的时候了。每当这个时候思绪总是翻江倒海,因为太久没有反思和总结的缘故,一年才总结一次,确实是有点久,欠的账的太多,梳理起来有点费劲。这里依旧还是写跟点跟工作/技术相关的总结。
盘点
2017这一年自己从前到后主导了个小项目,技术体系使用的openresty + spring boot/cloud + postgres + statsd + graphite + grafana + sentry + elasticsearch + kafka + docker + kubernetes。这一年依旧是延续上面的技术架构进行深入:
- docker & kubernetes(
使用级别
)
停留在使用阶段,考虑到云平台技术的成熟,假设自己出去创业,感觉也用不到自己去搭建kubernetes,直接用阿里云、腾讯云等的kubernetes的基础设置就可以了,于是就没有深入研究。
- spring cloud(
实践及扩展级别
)
这一年算是深入实践了一把spring cloud,不过生产还停留在Camden.SR6的版本,现在的GA版已经是Edgware,pre版本已经到了Finchley M4。而且从Camden版本到以上版本迁移的话,貌似有一些不兼容或变动,有点疲于跟进,另外主要是生产已经稳定运行了,就没有力气再去折腾升级了,维稳为主。等做下一个项目的时候再考虑直接用最新版吧。不过随着service mesh的成熟,分布式的这一套更进一步固化到基础设置里头,感觉spring cloud后续可能优势就不那么明显了。而且随着go语言流行,以及相关生态的丰富,渐渐的也有很多高并发服务采用go来替代java了,后续如果不是业务特性强的应用,可能用java的优势就不那么大了。就像Java未来也许不再是电商的首选开发语言这篇文章说的。
- spring security(
使用及扩展级别
)
这一年又去看看了spring security,还有spring security oauth2,感觉少点什么,缺乏将一整套技术实施去替代既有的权限控制体系,没有大规模去应用,总感觉没有深入理解。另外开始重视系统安全方面的知识,学习中。
- kafka(
使用及了解基本原理
)
kafka版本太杂,公司有的用0.8,有的用0.9,有的用0.10,17年推出了0.11,紧接着1.0版本也出来了,对于初学者来说,感觉有点措手不及,一入技术深似海,真的是学海无涯啊,于是就只能挑着点看了。主要是研究了0.8版本的一些使用和实现细节,另外研究了0.9版本与0.8版本的一些区别,还有就是今年主推的kafka stream,后续可能基于1.0版本再去深入了解。
- redis / postgres / mongo / elasticsearch(
使用级别
)
这些今年用的不多,也就用一用。
说说关系型数据库,一直对SQL不感兴趣,也没有深入研究,大底是面向对象看的太多了,另外看过了太多复杂业务需求写复杂SQL然后把系统搞挂的例子,总是觉得通过其他方式的实现是可以替代复杂SQL的,而且性能更优。NOSQL的出现,很多非事务性的查询,基本都可以通过将数据按查询需求结构化/冗余化同步到NOSQL里头来实现。
其他几个NOSQL,若要排行,估计redis得优先,毕竟使用太广了,明年估计得再深入学学redis;对mongo不是太有好感,像分片复制啥的,感觉都不如elasticsearch成熟,这里头要在排序,elasticsearch排在mongo前面;elasticsearch的话,以前有想过要深入学习的,不过版本变化太快了,以前还是1.x版本,如今都6.x版本了,欲哭无泪,特别是java api的使用,学的疲于奔命。还有就是mongo跟elasticsearch的查询语法学习成本太高了,elasticsearch还好一点,有ES SQL插件大部分场景可以用SQL来查询,还是比较爽歪歪的,mongo就没有SQL插件来查,于是就更不想学mongo了。
- rabbitmq(
基本使用
)
对于消息队列,传统的mq当中,就属rabbitmq最耀眼了,不过随着kafka、rocketmq的出现,有点被淹没了。不过还是值得一学的,有待深入实践。重点看open-messaging规范,从这个入手。
- openresty(
稍微上手
)
第一次写lua,感觉调试特别费劲,没有idea可以提示,总是不断来来回回重启,请求,看日志验证;后来写多了,稍微上手,感觉还可以,主要是nginx秒级重启,非常爽。有待深入研究。不过随着go的出现,后续go也有网关出来,比如janus,目测二者可以拼一拼。
- arch / system design(
入门级别
)
系统架构方面,感觉还出处于入门级别,后续有待深入学习和提高,不仅仅是技术架构,还有业务架构。
评价
收获
体验了一下从零到一的后端技术架构与实现,期望是初步具备了一个人出去创业拉起一整套后端技术架构与实现的能力不足
系统访问量太低,不容易暴露问题,部分技术实现在访问量在百万级、千万级、亿级是不同的,而且高并发场景会把一些技术实现的不是太好的问题给暴露出来,这点算是今年做的这个项目的硬伤的。
目标完成情况
- 继续每天sg博客,继续提升sg声望(
完成
)
这个算是完成了,16年突破1000声望,17年突破6000声望
- 多回答stackoverflow的问题(
不达标
)
这个完成的不大好,16年是255声望,17年是457声望,总体上升24052名,不过排行在98894
- 每周末技术复盘(
没完成
)
这个几乎是没完成,是最致命的,18年要严抓这个
- 夏天还是需要继续跑步,期望能学会游泳(
完成
)
游泳没学,但是跑步是有坚持的,除了下雨还有加班太累没有跑,其他基本是每周一跑,17年累计跑了80多公里,巅峰时期一次可以跑4km,但是持续不久,18年希望能多跑几次5km。
- 少加班、多提升时间以及项目管理能力(
不达标
)
习惯性加班,感觉身体要被加班逐渐加班坏了,时间规划不大好,好几次研究问题研究好几个小时到一两点才睡,对身体损伤太大。
展望
2018年学习计划:
- 重点学习
系统架构(
CASE MOCK
)、深入系统安全(OWASP
)、深入分布式缓存(redis
)、深入研究open-tracing(kafka
)、深入研究nginx/openresty
非技术类,目标是研究金融投资相关以及跟技术的结合。
- 前沿技术探索
service mesh,spring cloud可能风头正劲,但是也仅仅限于java领域,但是service mesh可是不限语言的,进一步将分布式架构固化在底层,目测又是一场技术变革。
AI这块,一直想学,但是没找到动力去开始,估计先从一些机器学习的理论开始,找实践点切入边学边实践。
具体指标
硬性指标
- 继续每天sg,sg声望突破10000
- stackoverflow声望突破1000
- 每周技术复盘/CASE STUDY(
完成let it crash系列
) - 每周完成至少一篇投资类文章(
逐步深入金融业务知识
) - 年度跑步公里数达到100+公里
软性目标
- 完成系统安全、分布式缓存、open-tracing、nginx/openresty的学习
- service mesh研究与实践
- 金融技术相关尝试
- 高并发多找机会实践
- 多研究优秀的开源项目架构/代码
- 多写开源项目
文章导航
docker / kubernetes
- docker的网络配置
- docker修改打开文件数
- docker-machine指定cpu个数
- dockerfile中apt-install处理continue
- docker运行prometheus
- docker运行jenkins
- docker运行oracle11g
- docker安装tesseract
- Dockerfile安装maven
- docker搭建mongo副本集
- docker运行consul cluster
- docker运行drill 1.10.0
- docker java8安装JCE
- ubuntu docker手工安装java8
- docker运行seyren
- docker-compose运行sentry
- docker运行mywebsql
- docker运行storm及wordcount实例
- docker运行kafka manager
- docker化360的pika
- ubuntu安装chrome及firefox
- kompose神器使用
- kubernetes的service的类型
- 使用kubernetes的deployment进行RollingUpdate
- 优雅地关闭kubernetes中的nginx
- mac安装kubernetes并运行echoserver
- kubernetes安装heapster、influxdb及grafana
- kubernetes部署rabbitmq集群
http / tcp / network / io
- 关于cookie的几个属性
- Cache-Control参数
- netstat及tcp状态
- 关于netstat的ListenOverflows等参数
- tcp的半连接与完全连接队列
- 关于netstat的ListenOverflows等参数
- 异步IO
- IO密集型的线程池大小设置
- netty的Sharable到底是干嘛用的
- webmagic小试牛刀
- httpclient参数配置
- apache的HttpClient的默认重试机制
- httpclient访问https
- restTemplate访问https
- RestTemplate的converters配置
- RestTemplate设置通用header
- RestTemplate获取文件的contentType
- springboot配置okhttp3
nginx / openresty
- 聊聊nginx的几个常见异常
- 聊聊nginx报错499问题
- 聊聊nginx与tomcat的5xx
- nginx lua重置请求参数及常量备忘
- nginx域名配置非80端口的301跳转
- nginx lua指令执行顺序
- 使用nginx capture的注意事项
- nginx的upstream异常
- openresty安装及使用LuaXml
- nginx的proxy_redirect
tomcat
- springboot的tomcat启动过程
- tomcat线程池策略
- tomcat的acceptCount与maxConnections
- tomcat的acceptCount、maxThreads、connectionTimeout参数调整
- springboot增加tomcat的metrics
- tomcat jdbc pool高级配置
- tomcat jdbc pool的borrow和return
- tomcat的jdbc连接池PoolExhaustedException
- tomcat jdbc连接池的suspect、abandon操作解析
- tomcat jdbc SlowQueryReport的实现解读
- 浅析tomcat jdbc的ResetAbandonedTimer
- springboot访问tomcat的SlowQueryReport
- tomcat如何关闭response的outputStream
java / jvm
- Java8的allMatch
- java9系列(一)安装及jshell使用
- java9系列(二)docker运行java9
- java重写equals及hashcode方法
- threeten-extra使用实例
- Java将枚举序列化为对象
- java计算集合交差并集
- java计算集合对称差
- java字符全角半角转换
- 使用prettyTime格式化时间
- java如何获取hdd序列号
- CompletableFuture的执行线程
- ForkJoinPool的commonPool相关参数配置
- java取消线程实例
- java8的CompletableFuture使用实例
- 线程池工作窃取实例
- fastjson获取unknown的字段
- rocksdb的jni加载
- 使用common-codec进行md5加密
- lombok的builder设置默认值的问题
- 聊聊lombok构造模式的参数校验
- 聊聊querydsl的生成类
- 记一个toJSONString异常
- 解决SAXNotRecognizedException
- java计算object大小
- 使用SXSSFWorkbook来导出excel
- TransferQueue实例
- Deque的使用实例
- SynchronousQueue使用实例
- java降低竞争锁的一些方法
- ArrayBlockingQueue与LinkedBlockingQueue
- ConcurrentLinkedQueue使用实例
- futureTask的超时原理解析
- JIT编译器版本
- jvm参数查看
- GC日志参数
- jvm的gc线程数计算公式
- jvm堆大小配置建议
- CMS收集器
- jvm分层编译级别
- jvm代码缓存
- 解决jd-gui在Sierra下闪退问题
- 聊聊jvm的PermGen与Metaspace
image / pdf
- 聊聊Color中的alpha值
- 聊聊ImageIO使用argb操作jpg的bug
- 使用BufferedImage进行渐变色操作
- 聊聊selenium的webdriver的超时参数
- 聊聊Selenium不同webdriver的构造
- 解决WebDriverWait中的cannot be applied的问题
- 聊聊phantomjs的优化措施
- phanbedder使用实例
- java对图片进行压缩和resize
- 使用imgscalr进行图片操作
- 使用tesseract进行图形验证码识别
- 使用asprise进行图片验证码识别
- 使用zxing生成和识别二维码
- 聊聊zxing的qrcode
- 聊聊qrcode的detect position
- 记一个OfficeException
- jodconverter4.1.0版本改进解析
- 使用pdfdom将pdf转为html
- 使用pdfbox实现pdf转image
- 使用tika将pdf转为html
spring-boot
- SpringMVC数据绑定实例
- spring mvc如何计算BEST_MATCHING_PATTERN_ATTRIBUTE
- spring mvc中的几类拦截器对比
- springmvc不断输出文本到网页
- springboot定制404错误信息
- 使用spring mail发送html邮件
- SpringBoot配置文件日期属性转换实例
- spring获取controller方法中自定义注解的信息
- springboot的PathVariable接收参数值带点号问题
- 文件下载分chunk写
- 解决metrics-spring与springboot1.4不兼容问题
- springboot动态加载sigar
- springboot动态加载native类库
- springboot不同servlet容器benchmark
- springboot运行时加载statsd-jvm-profiler
- springboot的HealthAggregator
- 关闭spring boot jackson的FAIL_ON_EMPTY_BEANS
- springboot异步mvc使用threadlocal的正确姿势
- springboot设置RestTemplate的超时时间
- springboot的ApplicationReadyEvent
- 使用reactor eventbus进行事件驱动开发
- spring event发布及监听实例
- 如何在async线程中访问RequestContextHolder
- 聊聊spring的async注解
- 聊聊TaskExecutor的spring托管
- springboot的diskSpaceHealthIndicator
- 在springboot中扩展tomcat的executor
- 解决springboot读取jar包中文件的问题
- springboot的ConfigurationProperties使用
- spring boot admin 使用consul discovery
- 使用cached的wrapper类读取请求响应内容
- 重复消费input stream的方法
- springboot Environment注入异常
- reactor自定义RejectedExecutionHandler
- logback输出日志到sentry
- logback日志增加行号
- activiti的job设计浅析
- quartz设置misfire策略
- quartz的api及数据库表映射解析
- 使用springboot构造quartz的rest api
- 聊聊quartz的调度及性能
- springboot集成quartz2.3.0
- springboot集成mqtt
- springboot中使用esper入门
spring-cloud
- zuul修改请求url
- 修复zuul跨域配置异常
- zuul自定义SimpleHostRoutingFilter
- zuul转发的一些常见异常
- ZuulFilter的order小结
- zuul进行rate limit
- zuul添加request header
- zuulfilter获取proxy的id
- zuul的forward error
- zuul修改请求响应body
- zuul修改request query param
- zuul动态路由加载配置
- zuul文件大小限制
- zuul转发Set-Cookie丢失问题
- SpringCloud运行时刷新数据源相关配置
- 聊聊Spring Cloud Config的ConfigClientWatch
- 记一个hystrix异常
- hystrix MaxConcurrentConnections reached 异常
- feign client的retry及超时设置
- feignclient设置hystrix参数
- feignclient的拦截
- 关于feign client触发熔断的异常
- spring cloud feign使用okhttp3
- spring cloud feign 上传文件
- spring cloud eureka 参数配置
- 理解eureka的自我保护机制
- EurekaClient如何更新注册信息
- eureka如何剔除实例
- eureka的惊群效应
- eureka的RateLimiter
- spring cloud atlas使用
- 在spring cloud中使用springboot admin
- ribbon static server list
- 关于ribbonClient配置的一个坑
- ribbon设置url级别的超时时间
- ribbon个性化参数设置
- ribbon的ServerListRefreshInterval
- ribbon使用eureka的meta进行动态路由
- springcloud基于ribbon的canary路由方案
- consul的server模式启用ui
- springcloud文件上传文件名乱码
security / spring security / oauth2
- java加解密实例
- 使用aerogear生成totp
- 聊聊二维码登录
- 聊聊directory traversal attack
- 聊聊session fixation attacks
- 聊聊springboot session timeout参数设置
- spring security动态配置url权限
- spring security动态配置权限的方案2
- spring security运行时配置ignore url
- spring security免登录动态配置方案2
- spring security ajax登录及返回
- spring security自定义AuthenticationEntryPoint
- spring security自定义指南
- 聊聊spring security的role hierarchy
- 聊聊SecurityContextPersistenceFilter
- 聊聊FilterSecurityInterceptor
- 聊聊spring security的账户锁定
- 聊聊SwitchUserFilter的使用
- SwitchUserFilter源码解析
- 聊聊spring security的permitAll以及webIgnore
- 列出spring security的所有SecurityFilterChain
- spring security filter获取请求的urlpattern
- 解决spring security自定义filter重复执行问题
- oauth2四种授权方式小结
- spring security oauth2 client_credentials模式
- spring security oauth2 password授权模式
- spring security oauth2 authorization code模式
- spring security oauth2 implicit模式
- 使用spring-security-oauth2作为client实现
- spring security oauth2之refresh token
- 聊聊spring security oauth2的password方式的认证
- 聊聊spring security oauth2的几个endpoint的认证
- spring security oauth2使用redis存储token
- spring security oauth2 allowFormAuthenticationForClients原理解析
jdbc / redis / elasticsearch / mongo
- 聊聊sql的并发update
- 拖拽数据库设计方案小结
- javax的PrePersist注解
- jdbc连接pg数据库timeout
- 记一个pg连接数过多的异常
- 利用hibernate生成建表语句
- 聊聊hibernate的hbm2ddl的实现
- spring data jpa数据变更审计
- javer的表结构设计
- 使用envers记录数据变更版本
- 聊聊spring jdbc的RowMapper
- spring-data-jpa设置fetchsize
- spring-data-jpa的auditor设置
- spring-data-jpa软删除方案
- spring data jpa 使用native sql实例
- jpa存储byte到postgresql
- mybatis spring boot starter配置
- jpa postgresql 使用uuid作为主键
- mongo查看数据库空间大小
- redis监控命令
- 聊聊jesque的几个dao
- 聊聊jesque在redis中的数据结构
- 聊聊jesque的event机制
- 聊聊jesque的WorkerImpl与WorkerPool
- springboot使用jest操作elasticsearch
- 修复jest的Connection is still allocated异常
- mongo的geo查询
kafka
- 聊聊spring对kafka的集成方式
- springboot集成akka
- spring cloud stream kafka实例
- spring-cloud-stream-binder-kafka属性配置
- kafka0.8生产者实例
- kafka0.8消费者实例
- kafka0.8生产者配置参数解析
- kafka0.8生产者异常处理
- 聊聊kafka的partition分配
- 聊聊kafka0.8的consumer超时时间属性
- 聊聊kafka0.8的topic的partition以及topicCountMap
- 聊聊kafka consumer offset lag increase异常
- 聊聊kafka consumer offset lag的监控
- 聊聊kafka 0.8 ConsumerFetcherManager的MaxLag指标
- 聊聊kafka client chunkQueue 与 MaxLag值
- kafka0.10client使用实例
- 聊聊spring kafka的retry
- 聊聊spring for kafka的AckMode
- spring for kafka自动配置及配置属性
- 自定义spring kafka consumer 线程池
- 聊聊kafka的group coordinator
- 聊聊kafka client的auto commit
- 聊聊spring for kafka对producer的封装与集成
- 聊聊spring for kafka对consumer的封装与集成
- kafka streams的join实例
- 自定义kafka streams的processor
- kafka stream errorlog报警实例
- kafka stream word count实例
监控
- spring boot admin slack报警
- springboot读取dropwizard的metrics
- springboot输出metrics到prometheus
- 输出hystrix指标到dropwizard metrics
- Prometheus的架构及持久化
- 通过jmx监控docker中的java应用
- 使用pcp监控spring boot的docker应用
- docker运行badjs
- 使用grafana4的alert功能
- 在java里头读取/proc/net/dev
- curl记录响应时间
- 进程cpu使用率的计算
- java获取指定进程的stat
- 关于statsd timer的几个指标
- 关于graphite的几个function
- 关于codahale的HistogramMetric
- grafana使用mysql存储
- SlidingTimeWindowReservoir的大小控制
- grafana高可用架构
- sentry8.15禁用注册
arch / design / data structure
- ArchiMate分层概念
- 聊聊partition的方式
- 聊聊replication的方式
- 分布式id生成方案概述
- 聊聊base62与tinyURL
- 高性能SPSC无锁队列设计之路
- 缓存的Cache Aside模式
- JCTools简介
- HashedWheelTimer算法详解
- lamport面包店算法简介
- 使用ratelimitj进行api的限流
- 基于权重的随机负载均衡路由算法
- hyperloglog的java版使用
- 聊聊jump consistent hash
- bloomfilter的简单实现
- 使用合适的数据结构统计单词次数
- 敏感词检测算法小结
- Trie树使用实例
- 聊聊GenericObjectPool的泄露检测
- GenericObjectPool参数解析
- shedlock源码解析
- 使用shedlock将spring schedule上锁
mac /linux /app build
- 动态生成ios plist的方法
- ios打包报错:User interaction is not allowed
- zsh: you have running jobs
- 使用sed替换文本
- mac unable to get application ASN from launchservicesd
- mac上Tesseract3.04.01_2样本训练
- mac安装consul
- shell获取文件大小及checksum
- apk文件的sign以及align命令
测试 / 部署
- 使用JUnitParams简化Parameterized tests
- 如何批量压测登录态的接口
- 使用jmh进行微基准测试
- 关于性能测试的几个要点
- Delivery Pipeline
- 使用postman作为rest api自动化测试工具
- 批量执行newman
- jenkins的bash shell使用boolean值
- jenkins推送镜像到私有docker-registry
- jenkins构建docker镜像
- jenkins集成java静态代码分析工具
- sonar自定义规则
- jenkins集成sonarqube
- 部署本地jar到maven私服仓库
- mac安装gitlab-ci-multi-runner运行sonar
- maven仓库jar包发布指南
- maven加载外部依赖包
- maven的test使用main的resources
doc
- 2016年终总结
- 过去的2015年