自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(37)
  • 收藏
  • 关注

原创 领域驱动设计(DDD)——应用架构落地方案

1. 什么是DDD与传统设计相比,总结了以下两个维度的不同点设计思维在传统设计思维里,会先设计表结构,然后根据表结构进行业务代码的开发,聚焦点在数据库上。而DDD是要先构建领域模型,也就是把需求拆分成独立的模块,这些模块有自己独立的功能,并与其他模块相互协作。DDD的聚焦点在领域模型上,一切都以模型为基础。编码风格虽然现在用的开发语言都是面向对象语言(比如Java),但是实际开发中还是采用的面向过程编程,因为现在的编程风格都是把数据模型和行为模型分开的,不符合对象的定义(对象应当有自己的属性和行为

2022-04-09 11:58:26 2432

原创 InnoDB并发插入—间隙锁引发死锁的原因分析

1 间隙锁生成条件事务隔离级别为RR(可重复读),间隙锁是为了防止幻读执行delete/update/select for update操作,且where条件中没有(或没有生效)主键或唯一索引2 间隙锁的区间间隙锁的区间取最靠近索引的左右值例如:create table user( id int primary key, no varchar(16) );create index idx on user(no);执行delete from user wher

2021-04-30 18:25:16 1832 6

原创 阿里开源EasyExcel数字转换问题

单元格中的数据为小数,如果位数超过十位且单元格格式设置为常规,此时数据只显示十位,超出的会末尾截取。invoke方法接收到的数据是截取后的,即240451327.4。这是因为在进入到自定义的Listener之前先调了ModelBuildEventListener,这个Listener中会把CellData中的单元格数据转换成String类型,问题就出在这里,常规和数值转换的格式不一样。单元格为常规格式的转换单元格为数值格式的转换下面看下格式为常规出现的问题ModelBuildEventLi

2021-02-10 15:27:44 4275 2

原创 Java诊断工具Arthas——部署及演示

1 安装下载命令curl -O https://arthas.aliyun.com/arthas-boot.jar安装命令java -jar arthas-boot.jar//使用阿里云镜像下载arthasjava -jar arthas-boot.jar --repo-mirror aliyun --use-http在安装之前需要启动一个java应用程序,否则会报下面的异常[root@master arthas]# java -jar arthas-boot.jar --repo-mi

2021-02-07 19:37:49 1045 1

原创 云原生监控系列—源码级剖析SkyWalking(应用层数据采集)

1 核心概念1.1 spanspan是链路跟踪的基本单元,记录了每个节点的跟踪信息,每经过一个interceptor都会去创建span,通过span将跟踪信息串联起来。整个跟踪流程类似一个有向无环图:span包括三种类型:EntrySpan:在同一个TraceSegment中,EntrySpan只有一个,作为链路的根节点。EntrySpan代表服务提供方的链路节点,比如Tomcat的入口,在TomcatInvokeInterceptor中会创建EntrySpan。ExitSpan:代表服务消费方

2021-02-01 20:52:56 1259

原创 云原生监控系列—源码级剖析SkyWalking(架构及Agent初始化)

1 整体架构SkyWalking是一个开源的APM系统,包括云原生架构下分布式系统的监视、跟踪、诊断功能。架构图如下(图片来自SkyWalking官网):SkyWalking大致分为数据采集层、数据处理层、数据存储层和web应用层。数据采集层SkyWalking为不同的编程语言环境下的服务提供了相应的自动打点代理,比如Java Agent,只需要在启动命令上加上Agent的目录即可实现数据采集。Agent会给需要打点的方法生成一个代理,在代理中收集打点数据。SkyWalking还支持Service

2021-01-05 21:23:04 762

原创 类加载机制

1 加载流程Java的类加载采用的是双亲委派机制,每个类加载器在加载类的时候会先委托父加载器加载,直到最顶层的启动类加载器BootstrapClassLoader,该加载器由jvm实现,对外暴露findBootstrapClass方法创建Class对象。如果被加载类不在BootstrapClassLoader加载范围,会一层一层的交由下一层加载器加载,每层加载器通过覆盖ClassLoader的findClass方法来加载各自范围的类,最终需要调用ClassLoader.defineClass()方法创建

2020-12-15 19:56:54 109

原创 云原生监控系列—基于Docker搭建SkyWalking

当前的应用架构基本都采用微服务架构,微服务解决了传统单体应用臃肿、难以扩展等问题,但同时也带来了新的问题。众多的微服务交织在一起,使得定位线上问题变的特别棘手,所以就需要一个链路追踪系统,把一次请求所经过的路径全部串起来,一旦请求失败了,能很直观的定位到问题出现在哪一环。目前主流的链路追踪系统有zipkin、SkyWalking、cat、jaeger等,SkyWalking是非常优秀的国产软件,对应用性能的影响是最低的,目前已成为Apache基金会的顶级项目,本文将介绍SkyWalking。1 安装Doc

2020-11-27 20:30:37 869 2

原创 JVM内存监控及故障分析

1 设置jvm参数以下参数值只是为了演示用的,具体要根据项目实际情况来设。* -XX:NewSize=104857600 新生代初始内存的大小:100M* -XX:MaxNewSize=104857600 新生代可被分配的内存的最大上限:100M* -XX:InitialHeapSize=200m 堆的初始内存大小,默认为物理可用内存的1/64* -XX:MaxHeapSize=200m 堆内存最大上限,默认为物理可用内存的1/4* -XX:SurvivorRatio=8 Eden区与

2020-10-19 20:09:01 366

原创 互联网架构演变——中台

中台是一种企业级架构,是把企业能共享的资源整合成一个大的平台,提供给各业务应用使用。目的是让各应用变得更轻量、更专注于具体的业务,从而达到快速的更新迭代以及快速建立新的应用。中台分为业务中台和数据中台。1 业务中台假设一个公司要做一款应用A,组件团队进行开发、测试、上线,运营一段时间后效益还不错,得到了资本的青睐,公司顺利完成了融资。这个石红公开开始开拓新的业务,要做一款新的应用B,按照传统的模式就是把做A系统的过程重复的做一遍,这显然会有重复的功能建设。由于这两款应用是独立的,所以一个用户要用这两款应

2020-09-30 18:48:56 370

原创 分布式系统架构——CAP理论

1 什么是CAP在分布式系统中,任何存储系统(有状态服务)都会涉及到CAP定理:Consistency:一致性,简称C。在同一时刻所有节点是具有同样的数据副本,每个节点的数据要保证实时同步。Availability:可用性,简称A。对于一个集群整体而言,能够不间断的对外提供读写请求,集群内部一部分节点出现故障不会影响整个集群。分区容错性(P):在分布式系统中,难以避免网络故障(如网络故障、丢包等)等问题。在出现网络故障时,集群仍能正常对外提供读写请求服务,但是数据可能是一致性的或者非一致性的,也就

2020-09-27 20:23:52 455 1

原创 互联网架构演变——微服务

1 单体应用单体应用,说简单点就是把所有代码都部署到同一个进程里。在项目初期,需求可能比较少,也没多少用户,采用单体架构不会出现什么问题。但是在这个需求快速迭代的年代里,一个项目的成长是非常之快的。随着需求的不断增加,项目变得越来越庞大,就像上面的电商系统,涵盖的功能非常之多。万事万物都不可能无限的扩张,达到一定的极限就会出现一些难以解决的问题。事物发展的越大,承载它的载体就要越大。就像一艘航母,让它在湖泊里航行能行么,显然湖泊没有那么大的承载力。所以一个庞大的系统也需要一个能够承载它的硬件资源(服务器

2020-09-24 20:44:38 245

原创 云原生架构系列——kubernetes可视化部署

1 Jenkins构建镜像并push到Harbor仓库安装Jenkins参见官方文档:Jenkins文档maven配置创建一个Springboot项目,在pom文件里配置下面的maven插件<plugin> <groupId>com.spotify</groupId> <artifactId>docker-maven-plugin</artifactId> <version>0.4.13</vers

2020-09-23 19:56:15 377

原创 云原生架构系列——kubernetes部署有状态服务

有状态、无状态服务的概念参见:kubernetes原理及核心组件里的StatefullSet介绍。1 存储PV:PersistentVolume(持久卷,简称PV),是对存储系统的抽象,将存储系统抽象为k8s的一个资源,便于访问。PVC: PersistentVolumeClaim(持久卷声明,简称PVC),用户(一般是开发人员,开发人员在发布服务时要指定pod挂载Volume的空间大小、存储类型等)的一种存储请求,用户不需要知道存储的实现细节,只需要通过PVC告知存储的需求(比如:多大的空间、

2020-09-21 20:13:19 504

原创 云原生架构系列——Pod的生命周期

pause容器:参见:kubernetes原理及核心组件init容器:一个主容器可以创建一个或多个init容器,init容器用于为主容器加载一些资源。事例#init.yamlapiVersion: demo/v1kind: Podmetadata: name: init-demo labels: app: demospec: containers: - name: demo-container image: www.harbor.com/harbor/demo:v1.

2020-09-19 21:07:49 297

原创 云原生架构系列——构建Harbor企业级镜像仓库

主流的构建私有仓库的开源组件有Harbor和Registry,Harbor的功能比较强大,支持web图形化操作,支持权限控制。1 安装compose组件首先要重新搭一台服务器或虚拟机,安装docker环境,参见:kubernetes集群环境搭建建议离线安装安装compose和harbor组件,github下载速度非常慢,在线安装可能会出现一些问题。compose下载网址:https://github.com/docker/compose/releases。将下载好的文件上传至/usr/local/

2020-09-18 18:03:56 432

原创 云原生架构系列——kubernetes部署容器

1 指令部署1.1 部署镜像以myapp为例,先去镜像库搜索下myapp部署指令kubectl run myapp --image=ikubernetes/myapp:v1 --port=80其中myapp::deployment部署对象的名称(rs和pod资源会以此为前缀生成各自的名称)ikubernetes/myapp:v1:镜像地址port:指定pod的端口查看pod是否生成成功kubectl run指令创建了三个资源对象,分别是deployment、rs、pod,三者之

2020-09-17 18:02:10 452

原创 大数据系列——概论

何为大数据在万物互联的时代,数据每时每刻都在产生。你的手机、笔记本、智能穿戴设备、智能家电等等所有联网的终端设备都在不间断的向云端输送着数据,云端数据呈指数级增长。在过去,受制于人类的计算能力,只能通过随机采样来进行数据分析,分析的结果取决于样本数据的质量。但是在云计算时代,可以依托云端强大的计算能力和新的处理技术与策略,对全量数据进行分析,挖掘其中的价值。大数据的5V特点:Volume(大量):TB级别以上的数据Velocity(高速):要求高时效性,比如滴滴打车,需要知道车辆的实时位置Va

2020-09-15 17:59:00 456

原创 云原生架构系列——kubernetes集群环境搭建

1 基础环境1.1 机器环境从官方文档可知,安装k8s对操作系统、内存、CPU核数等都有要求:笔者用的是CenOS,所以要用7版本内存要在2GB以上CUP核数至少2核还有:DNS最好设置为本地网络连通的DNS,否则可能会出现网络不通,导致无法下载一些镜像linux内核必须是 4 版本以上只是为了演示,三台机器即可,一个master节点,两个node节点。可以在本地搭三台虚拟机,也可以购买云服务器。1.2 环境初始化1)给每一台机器设置主机名hostnamectl set-

2020-09-14 21:52:32 515

原创 云原生架构系列——kubernetes服务发现与集群负载均衡

1 什么是Service首先我们看下两个问题现在有一个node节点,node上有四个pod,每个pod都有自己的IP地址和端口:现在客户端发送了一个请求,能不能通过10.0.0.0:80这个地址来访问服务。显然是不行的,因为pod是一个进程,进程要想与外界通信只能通过服务器的物理地址加进程的端口进行通信。Nginx能不能作为App1-3的代理?如果App1-3的地址不会改变,那是没有问题的。pod的IP是网络插件动态随机分配,在pod重启后IP会发生改变,但Nginx感知不到pod的地址变化。所

2020-09-11 20:36:14 503

原创 云原生架构系列——kubernetes原理及核心组件

1 kubernetes基本介绍试想一下为什么高铁能有条不絮的运行在各自的轨道上,不会出现前后车相撞,那是因为有个调度中心在统一的指挥。什么时间发车,什么时间到站以及遇到故障问题需要作出什么决策,都是由调度中心统一指挥。对于容器也是一样,要想使容器能井然有序的运作,就需要一个统一的管理平台,如分配资源、扩缩容、服务宕机能及时恢复等。目前最流行的容器管理平台是Kubernetes,简称k8s,8代表中间的8个字母。其它的还有Swarm和Mesos。k8s是Google开发的开源容器管理平台,源于Googl

2020-09-08 16:05:51 615

原创 云原生架构系列——概念及原理

1 云计算发展进程2000年:sun公司研发出了高性能服务器,用于支撑企业的关键业务2001年:硬件资源难以做到弹性扩缩容,这就导致不可避免的会出现资源的浪费,比如你购买了一台8核16G的服务器,但你的应用可能只需要4核8G。所以IBM研发出了VMware,虚拟机的好处就是可以弹性扩缩容,能充分发挥硬件资源。2006年:Amazon公司提出了IaaS(Infrastructure as a Service),基础实施即服务。就是把硬件资源,比如服务器、DNS、存储等通过虚拟化技术抽象成服务给企业用

2020-09-04 15:07:39 5667

原创 云原生架构系列——资源隔离

1 为什么要对资源进行隔离举个例子,假设现在你有一套一室一厅的房子,你想把这套房子出租出去,租金是1200/月。但是如果你把这套房子隔成三个单间,主卧600/月,两个次卧400/月,每个月的总房租就变成了1400/月,这样不仅提高了房屋的利用率也增加了收益。对于服务器资源也是一样,硬件资源是固定的,通过软件把硬件资源分隔成多个单独的资源,这每个独立的资源就可以租给不同的客户商。通过软件实现隔离还有一个好处就是弹性扩容,这是云计算技术一个非常重要的特性。实现资源隔离主要有两种技术:虚拟化技术和容器技术。2

2020-09-03 20:17:44 975

原创 Redis实现分布式锁的三种方案

在进入正题之前要搞清楚两个问题:为什么需要分布式锁?Redis为什么能够实现分布式锁?假设现在有一个应用部署在了三台机器上,应用的某个资源需要进行加锁控制,如果用关键字synchronized加锁能控制住么?显然是不行的,因为synchronized是线程锁,只能作用在当前的JVM里,获取的锁是各自JVM主内存上的锁资源。就好比一个房间有三个门,不惯是打开哪个门上的锁都能进入这个房间。此时就需要一个统一的入口来提供锁资源,这就是分布式锁。能作为锁还必须满足一个条件,就是操作必须是原子性的,锁本身要能保证线

2020-07-22 19:48:01 4428

原创 EasyPoi导入导出Excel最全案例

现在有这样一个需求:1) 批量导入用户,需要校验用户的信息2) 如果有错误的数据支持导出,有错误信息的单元格用特殊颜色标出,并将错误信息设置在单元格批注里针对以上需求,笔者对EasyPoi进行了封装,下面将依次介绍1 导入EasyPoi支持hibernate-validator注解式校验,如下图如果要获取校验没通过的错误信息及行号需要实现IExcelDataModel和IExcelModel接口。这些都是基本校验,在实际开发过程中可能会遇到需要写代码来校验,比如校验用户名是否重复,EasyPo

2020-07-14 19:23:33 4305 1

原创 解决同类方法调用事务失效的工具类

假设现在类C,这个类里有两个方法methodA和methodB,methodB加了事务,如果在methodA里调用methodB,此时methodB的事务会失效。这是由于Aop导致的,具体参见日常踩坑篇—Spring事务的两个坑点。笔者采用Function函数写了一个通用工具类//Function函数类public interface FunctionHelper { //P是方法的传参,如果有多个参数可以定义成P1、P2等形式。R是方法的返回值 @FunctionalInterface

2020-07-14 17:38:54 521

原创 Mybatis核心源码分析之加载XML文件(二)

上一篇分析了Mapper初始化的核心源码,本篇主要分析一下SpringBoot如何加载Mapper.xml文件。如果在你的SpringBoot项目里引入的是下面的包: <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId>

2020-06-08 21:17:20 563

原创 Mybatis核心源码分析之Mapper初始化(一)

如果项目中的ORM框架用的是Mybatis,只需要配置一下数据源,然后再定义一个mapper接口和一个xml文件就可以实现Java对象与数据库表之间的映射,从而可以实现对数据库的访问。使用起来非常简单,这得益于Mybatis强大的封装能力。下面我们分析一下Mybatis的核心源码,看看Mybatis是怎么实现的。本篇主要介绍Mapper的初始化。Mapper是一个接口,需要有具体的实现类来完成它定义的功能,Mybatis给所有的Mapper创建了动态代理,这些动态代理是通过Spring提供的Factory

2020-06-06 09:26:31 987

原创 BeanFactory与FactoryBean的区别及设计思想

BeanFactory与FactoryBean看似是单词间的简单互换,其意义相差很大,它们分属的功能也有很大的不同。1 BeanFactory熟悉IOC容器的朋友对BeanFactory应该不会陌生,BeanFactory其实就是一种IOC容器。BeanFactory是bean工厂,在现实中工厂是用来加工生产我们所需的各种产品,BeanFactory的功能也不例外只不过是生产的产品不同而已。我们代码中的各种bean、bean的实例化以及实例化后对象的依赖关系都是交由BeanFactory来管理的。可以说

2020-05-22 19:57:33 369

原创 Mybatis拦截器给create_user、update_user等固定字段自动赋值

在表结构设计中,通常会有一些固定字段,比如create_user、update_user、create_time、update_time等,在有insert和update的的地方都需要给这些字段赋值,这种工作简单繁琐,下面用自定义的Mybatis拦截器来给这些字段自动赋值,以其中一个字段create_user为例。首先要定义一个注解,这个注解需要加在字段create_user上下面是自定义的Mybatis拦截器@Intercepts({@Signature(type = Executor.class

2020-05-15 20:43:39 2194

原创 获取类的所有属性包括父类属性

jdk自带的两个获取属性数组的方法,一个能获取到不包含父类的所有属性,见下图:一个只能获取父类属性但都是public属性,见下图这两个方法都满足不了获取包含父类的所有属性,下面写了一个工具类:...

2020-05-15 20:38:31 890 1

原创 SpringBoot项目中如何保证自定义的Mybatis拦截器在PageHelper之前执行?

如果项目中引入的是pagehelper-spring-boot-starter包,可能会遇到SqlSession拦截器执行顺序的问题。starter模式下,PageHelper在PageHelperAutoConfiguration里进行的配置,这样就不能手动设置拦截器的顺序。Mybatis拦截器是先添加的后执行,因此可以采用观察者模式在Spring容器初始化完成之后再添加自定义的拦截器。Spring提供了一个这样的接口:自定义的Listener代码如下:@Componentpublic class

2020-05-09 18:40:11 4947 8

原创 代码设计篇—数据权限拼装sql通用解决方案

笔者最近仿照PageHelper写了一个拼装sql的组件,需要灵活拼装多个字段,在遇到多子查询时难以做到通用。笔者最终放弃对sql进行截取拼装,想了一个比较讨巧的方案,仿照Mybatis自定义一个特殊字符,然后在拦截器里替换。不过这种方案也比较坑,需要在sql里列出要过滤的字段,等笔者想出更好的方案时再进行补充,下面先看下用特殊字符的方案。@Component@Intercepts( ...

2020-05-07 20:14:52 1090

原创 日常踩坑篇—Spring事务的两个坑点

现在的程序开发基本都是“拿来主义”,有很多现成的组件可以用,但是不究其原理,不掌握组件内部的实现机制,就会出现比较有意思的场景:“我什么都没改啊!”、“我只加了一个字段而已!”,因为你已经掉进坑里了。没有完美的解决方案,每种方案都有利有弊,AOP也是一样。Spring事务是基于Spring AOP实现的,如果你对Spring AOP还不是很熟悉,可以看看笔者的另一篇文章:源码剖析篇—Spring ...

2020-05-04 16:43:44 597

原创 源码剖析篇—Spring Aop

什么是AOP关于AOP的相关概念解释网上一搜一箩筐,笔者不在这里赘述。举个生活中常见的例子,现在高铁网络很发达,高铁是很多人出行的首选之一。乘坐高铁有一个重要的环节是检票,在进入候车大厅时要交出身份证进行检票检查。有趣的地方就在这里,为什么要在候车大厅的门口进行检票呢?可能有的人觉得理所应当,这是受思维定势的影响,生活中习以为常的事就变得理所应当。我们抛开所有已知的关于高铁站的事项,假设现在要建...

2020-04-29 16:49:42 375

原创 代码设计篇—别再用if else了!

1 注入Map逻辑复杂,需要根据条件分别处理的,可以采用注入Map的方式解决。以学生和老师为例,学生和老师属于用户。代码结构如下图:StudentServiceImpl和TeacherServiceImpl实现UserService,service的id与枚举UserType保持一致,UserBizService调用UserService的add方法来新增学生或老师。Map注入时,s...

2020-04-20 13:33:34 385

原创 源码剖析篇—HashMap的初始容量为什么最好设为2的次幂

这里写自定义目录标题HashMap的初始容量为什么最好设为2的次幂HashMap的初始容量为什么最好设为2的次幂首先我们来看看如果初始容量不是2的次幂会出现什么问题。为了更好的演示接下来出现的问题,我们取比较特殊一点的数字。假设我要存12个元素,为了防止HashMap扩容,初始容量应设为(12/0.75) + 1 = 17。下面我们来看下HashMap计算数组索引的源码,如下图:上图中有...

2020-04-15 13:00:30 449

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除