- 博客(185)
- 收藏
- 关注
原创 SpringBoot动态数据源实现
AbstractRoutingDataSource是Spring-jdbc提供一个继承自AbstractDataSource的抽象类。AbstractRoutingDataSource 关键属性targetDataSources:存放Key和数据库连接映射关系defaultTargetDataSource: 默认连接resolvedDataSources:这个数据是通过targetDataSources构建而成,也是存放Key和数据库连接映射关系。
2024-03-28 15:58:48
574
原创 SpringBoot Redis 之Lettuce 驱动
因为默认不再引入Jedis驱动包,所以直接加载Lettuce驱动。Lettuce:它的连接是基于Netty,连接实例可以在多个线程并发访问,一个连接实例可以满足多线程环境的并发访问,当然一个实例不够也可以按需增加实例,使用连接池。创建SpringBoot2.6项目,引入spring-boot-starter-data-redis,打开Depnedencies可以看到他的依赖如下。Jedis:采用的是直接连接redis-server,多线程操作时是不安全的,需要使用Jedis pool来规避线程不安全问题。
2024-03-28 15:25:24
440
原创 spring.factories
spring.factories配置机制类似于Java SPI,META-INF/spring.factories 文件中配置了接口实现类名称,然后springboot在启动时候扫描该配置文件并实例化配置文件中的Bean. SPI可以参考《通常将Bean注入到Spring容器中有多种方法,比如@Autowire、@import注解,而Spring.factoires的意义在于可以将第三方Jar包中的Bean有选择地注入到容器中。注:下一篇讲Springboot的starte机制。
2024-03-27 20:03:25
877
2
原创 spring-boot-devtools配置和原理
基本原理是使用了两个ClassLoader,一个ClassLoader加载那些不会改变的类(第三方Jar包),另一个ClassLoader加载会更改的类,称为restart ClassLoader,在代码更改时原来的restart ClassLoader会被丢弃,重新创建一个restart ClassLoader,由于需要被加载的类比较少,所以实现较快的重新加载。注:使用RestartClassLoader来加载Main启动类。然后你修改类应用就会立即重启生效,比手工重启要快很多。
2024-03-27 19:54:51
837
原创 SPI机制详解
1、服务提供方提供接口具体实现,并且必须在Jar包的META-INF/services目录下创建以“接口全名”为文件名,内容为实现类全类名。ServiceLoader<S> load(Class<S> service),为给定的接口创建类加载器并通过反射加载具体的实现类。META-INF/service/java.sql.Driver内容com.mysql.cj.jdbc.Driver。1、ServiceLoader加载的是有共同接口的实现类,ClassLoader是个万能类加载器。
2024-03-27 19:40:50
1279
原创 SMTP发送邮件
是为SMTPS(SMTP-over-SS)协议开放的,使用SSL加密信息,可以防止黑客截取邮件,但并未得到IETF机构的认证,SMTP/SMTPS之间关系类似于HTTP/HTTPS。TLS/STARTTLS,基于身份验证的,使用该端口的SMTP服务 客户端必须要登录验证身份才能发送邮件,有效的避免垃圾邮件。SMTP即简单邮件传输协议,基于TCP提供可靠的邮件传输,它是一个推协议,如果使用邮件客户端收取邮件则需要用POP3协议。通过代码发送邮件是程序最基本的功能,比如监控程序告警邮件,客户营销邮件等。
2024-03-27 19:32:08
1614
原创 Signal机制之Flask 篇
昨日在读Flask_Login源代码的时候,读到user_logged_in.send()后发现没办法继续跟下去了,因为这里用了Signal机制,代码是没办法跟下去,今天我们就来了解一下Flask 的Signal机制。注:当订单完成时发送信号,两个订阅方收到该信号后分别发送短信和推送微信公众号消息,我们牛奶业务的系统当时对接的是阿里云的MQ来进行系统解藕。Flask Signal用于解藕系统行为和业务逻辑,当行为被触发时发送定义好的一个信号,与该信号绑定的业务逻辑在收到信号后会自动执行。
2024-03-27 19:24:12
333
原创 Shiro快速入门之三
注:在需要授权的接口加上RequiresPermissions("权限key")来设置,这里我用qingcai18036登录后(初始化数据中qingcai18036账号配置了角色admin,admin角色配置了权限user:view和user:add),然后访问http://localhost:8080/userAdd、或http://localhost:8080/userList?shiro权限有5个注解,如果一个类或方法上有多个注解,按下列次序进行处理,如果通过的会继续检查后面,否则返回。
2023-11-14 11:22:44
207
原创 Shiro快速入门之二
用Shiro写认证代码,第一步要先实现Realm的认证方法,将从数据库查出来的密码,salt设置到AuthenticationInfo对象中,在用户登录时会将输入的用户名密码传给SecurityManger,然后进行比对用户名和密码是否正确。介绍了Shiro三大核心组件,四大核心功能,以及一个简单的Test Demo,接下来两篇我会用一个比较完整的例子来讲述Shiro的认证及授权是怎么做的,本篇侧重于介绍认证的过程。自定义的Realm实现,主要实现两个方法一个是认证,一个是授权。注:授权代码下篇再讲。
2023-11-14 11:13:37
189
原创 Shiro快速入门之一
Java有两个出名的安全框架,一个是Apache Shiro,另一个是Spring Security ,相对而言Shiro更简单、控制权限的粒度可粗可细,我们项目中使用的是Shiro。
2023-11-14 10:17:18
307
原创 Session、Token、Jwt三种登录方案介绍
4、如果应用部署在多台服务器,需要做Session同步,这里一般有两种做法,一种是通过容器(Tomcat)本身进行Session复制,但存在一个问题,当用户量大的时候,每台服务器重复存放大量的Session对象,会占用大量的内存,另外一种做法是写一个拦截器,用户在A机器登录后会在当前服务器生成Session,然后用户下一个请求被路由到机器B,这时需要做Session的恢复,解析出Cookie中用户名查找到用户数据然后放到Session里去,该用户下次请求如果还是路由到该台机器就不用再查数据库了。
2023-11-14 10:06:25
496
原创 ReportLab创建合同PDF
有一个项目需要将电子签名后的报价合同和生成的发票发送给客户,这种发送给客户的文件一般都是使用PDF格式,主要是因为PDF特别适合阅读且不同平台打开文件格式不会变形,不过要在程序中生成PDF还是比较麻烦的,我们的发票是用Java IText生成PDF文件,而报价合同因为内容有7,8页比较长,很难用IText画出来,这个我们是通过先将报价文件Word模板渲染数据,然后将渲染数据后的Word再使用aspose-words转换为PDF并且贴上签名图片。注:构建pdf对象,然后将标题和表格添加到文档中。
2023-11-14 09:55:54
559
原创 Redis应用之二分布式锁2
1、设置锁的超时时间,超时时间不能设置太短,一定要比业务代码执行耗时最长的时间再大一些,一般设置为3秒差不多,上一篇文章用了Redis分布式锁还产生问题的原因就是因为超时时间设置太短造成的,业务代码还未执行完,锁就失效被另外一个线程持有然后在并发量大的情况就产生问题了。将代码部署在两台机器,库存设置为10000, set "inventory:9321785256118" 10000,然后Jemter创建两个线程组,每个线程组起500个线程,循环执行10次,结果库存值为0,没有产生并发问题。
2023-11-13 22:30:44
172
原创 Redis应用之二分布式锁
将代码部署到两台机器,然后用Jmeter创建两个线程组,分别对两台机器接口进行请求,每个请求只使用一个线程请求500次,执行结果 Redis中的库存值并不为0,而是大于0不确定的值(第一次结果348,第二次结果55),如果改成每个线程组的线程数为10个请求次数为50次,这时结果会更大一些。这就是分布式环境多台机器并发的问题,多台机器从Redis中取出相同的值,然后分别再执行扣减库存操作,结果就会发生超卖的问题,线程数更多结果更大这是因为更多的请求从Redis中取出了相同的值,然后进行扣减库存。
2023-11-13 22:16:57
274
原创 Redis应用之一自增编号
淘宝订单编号 827768001755267512 ,共18位,其中最后6位是不变的,这个订单编码变更过几次,现在具体规则我也不太清楚,原来和淘宝的商品中心打过一些交道,好像还下载代码,不管是表结构还是代码架构扩展性做得很好,不像商品发布Shell平台那么乱。Redis是IO多路复用单线程模型,一个CPU绑定了一块内存区域,所有客户端的命令都会放入队列,然后逐条执行,所以Redis INCR命令本身是原子性的,它能保证每次返回的结果不会是相同的值,可以做为原子性计数器。订单编码要保证绝对不能重复。
2023-11-13 22:00:47
707
原创 Redis被攻击纪实
1、2017年时候测试环境安装的是Redis4.0版本(或者更低,记不太清了),默认安装6379端口可以远程访问,然后被黑了,被人家做为挖矿机,他们太狠了,一定要把我CPU耗尽,搞得别的程序都跑不了(这样别人不就发现了吗,不能控制CPU的占用情况吗?上周新来的同事分享Redis的原理和机制,想起2017年的时候测试环境Redis被攻击,最后只能重新安装服务器,今天试验一把利用Redis漏洞进行攻击,只有理解了别人是怎么攻击的,才能更好地进行防范。注:忘记截屏了,重启了Redis,那个注入的key找不到了。
2023-11-08 17:43:04
545
原创 Quartz介绍
Quartz相对 Linux的Crontab更强大,Crontab是进程调度而Quartz是线程调度,Quartz支持集群,另外Quartz还支持Listener便于进行Job的监控,因为数据可以存在DB便于做Job任务管理的可视化。几乎所有系统都需要定时任务,如果系统中定时任务比较少并且是单机环境的直接使用SpringTask即可,如果定时任务比较多且需要经常维护或者要部署在分布式环境中就要考虑使用Quartz或者xxl-job等开源框架,今天我们来了解一下Quartz的基本使用。
2023-11-06 07:47:35
245
2
原创 Python Tkinter快速入门
Tkinter 有21个核心组件,常见的比如Label(标签)、Button(按纽)、Entry(输入框)、Frame(框架)、Menu(菜单)、RadioButton(单选)、CheckButton(复选)、Canvas(画布)、Bitmap(图像)等。接了一个小活,需要做一个比特币走势分析小工具,客户希望能安装在Mac上,考虑后决定采用Python的Tkinter+matplotlib来做,今天我们就来了快速了解一下Tkinter。注:顶部栏Menu在Mac下测试不成功,但右键弹出的Menu是可以的。
2023-11-06 07:32:58
155
原创 Python Faker批量生成测试数据
在做自动化测试或压力测试时会需要大批量生成测试数据,简单的方式你可以写一个存储过程使用随机函数来生成记录,但这种生成数据看起来不够真实,其实有蛮多现成的工具可以完成这一任务。注:使用faker构造user及post对象,然后批量创建记录,生成了100万条记录大约花费了30分钟左右。进入faker源代码目录faker/providers下,可以看到提供了下列类别的生成数据方法。faker是一个生成伪造数据Python第三方库,可以伪造姓名、城市等等,并且支持中文。使用flask shell交互生成测试数据。
2023-11-06 07:19:09
297
原创 PDF文件解析
PDF是英文Portable Document Format缩写,就是可移植的意思,它是以PostScript语言图象模型为基础,无论在哪种打印机上都可保证精确的颜色和准确的打印效果,PostScript咱也不懂,估计和SVG的原理差不多吧。
2023-11-05 12:07:46
1609
原创 MySQL Too Many Connections
可以查看当前MySQL允许打开的文件句柄数,我们在设置max_connections最大连接数时不能超过 open_files_limit的值,因为 open_files_limit除了包含Socket连接还包含打开的文件数(数据库表文件等,如下图),如果max_connections大于open_files_limit MySQL是无法启动的。:调整max_connections的值,在MySQL命令行中执行后可以立即生效,但MySQL服务器重启后会被恢复成默认的设置。
2023-11-05 11:33:26
168
原创 MySQL Create table as select无法执行
MySQL5.6及更低版本系统参数enforce_gtid_consistency 默认值为OFF,MySQL5.7及更高版本默认值为ON,当设置为ON时,MySQL只允许能够保障事务安全并且能够被日志记录的语句才会被执行,而像create table as select 或create temporarytable 这种一条语句中包括事务和非事务是不被允许执行的。根据GTID可以知道事务最初是在哪个实例上提交的,可以更简单实现主从复制且更安全。注:下次写一篇传统的主从复制和GTID主从复制的文章。
2023-11-05 10:32:11
2114
1
原创 MySQL BinLog实战应用之二
注:这里是仅单机环境,我们的场景单机也就可以了,如果要保证可靠性使用多个接收端,需要引入zk来保证同一时间只有一个消费端工作,因为canal通过ack保证必须按顺序消费,以免数据无序造成数据错乱。我们知道MySQL主从复制是Mster将数据变更写入BinLog,然后Slave将Master的BinLog拷贝到它的中继日志,最后重放中继日志完成将数据同步到Slave。Canal其实它就是参考主从复制原理,将自己伪装成Slave,接收Master推送的二进制日志。类似于MQ的消息接收端。
2023-11-03 09:54:28
224
原创 MySQL Binlog实战应用之一
最开始了解到BinLog是在2007年左右,当时公司会员数据库是1主3从架构,主从复制其实是依赖于binlog,印象比较深的就是主从复制延迟的问题。2、对接Binlog日志解析数据生成日志数据,这种方案可以记录字段变更前旧值以及变更后的值,但日志不够清晰,主要是记录谁什么时间对哪张表哪个字段做了变更,变更前数据是什么,变更后数据是什么。记录的方式是行,即如果批量修改数据,记录的不是批量修改的SQL语句事件,而是每条记录被更改的SQL语句。安装的MySQL默认是没有开启BinLog的,可以用命令进行确认。
2023-11-02 09:03:11
232
原创 matplotlib入门-基金走势图
注:matplotlib实际项目中应用接触比较少,网页上画统计报表图现在比较常用的是百度的ECharts,我们收银台销售报表用的也是EChars,后端Java接口提供数据,前端使用EChars将图渲染出来。它的绘图接口在matplotlib.pyplot模块中,pyplot提供和MATLIB绘图API类似的接口。plot方法:plot(x,y) 接收X轴坐标列表和Y轴坐标列表,扩展的参数可以设置线条形状,颜色等。读取csv文件格式如下,每天一条记录,第二列是基金净值,第三列是累计净值,然后画出图表。
2023-11-01 22:56:16
235
原创 JVM参数调优
由于eden区的空间大小为512K,无法容纳每次生成的1MB数组,这种就是大对象,直接分配在老年代,老年代最终占用内存为used 10240K。由于eden区的空间大小为6M有足够的空间,但又并不足以有10M空间,所以发生了一次GC,由于每申请一次空间,同时也废弃上次申请的空间(上次申请的失去引用),做GC时被回收。老年代空间几乎没有被占用。PSYoungGen: 404K->320K(1536K):新生代GC前后空间使用大小,3476K->3400K(5632K)整个堆内存GC前后空间使用大小。
2023-11-01 10:27:07
158
原创 JVM堆内存解析
老年代对象比较稳定,当有新生代对象移到老年代,如果空间不够时会触发MajorGC,采用标记清除法,即扫描内存区块后标记出存活的对象,然后将未标记的进行回收,MajorGC耗时比较长(监测两周数据,只有启动的时候执行了4次MajorGC,每次耗时200毫秒)。当Eden区满的时候进行Minor GC,如果对象还存活的,会被移到幸存区,以后每次GC时对象的年龄会加1,当年龄加到一定程度就会被移到老年代,幸存区分成两个区,每次只使用一个区,当一个区块填满了后会将还活着对象复制到另一个区。
2023-11-01 09:17:24
631
原创 Java日志组件之三Log4j2漏洞剖析及重现
先搭建一个SpringBoot项目,然后将spring-boot-starter-logging这个依赖移除,自己引用log4j-api-2.13.3.jar、log4j-core-2.13.3.jar这两个包,注(这是我们从自己以前老机器上找到的,现在官方应该是已经修复了,直接maven依赖进来应该是不能重现了)。你调用logger.info(name);注:我这里演示用的是同一台机器,但也可以很明显看得出来是在服务器上去执行远程黑客机器上的代码(那个代码在你的服务器上执行,而不是黑客自己的机器)。
2023-11-01 08:37:57
279
原创 Java日志组件介绍之二
SpringBoot默认的日志组件就是logback,只要引入spring-boot-start就会把logback依赖引入,如果没logback配置文件,则会直接使用默认的org.springframework.boot.logging.logback.base.xml,默认日志输出级别为INFO。slf4j-simple、logback都是slf4j的具体实现,log4j并不直接实现slf4j,但是有专门的一层桥接slf4j-log4j12来实现slf4j。
2023-10-31 23:33:00
398
原创 Java日志组件介绍之一
前段时间爆出Log4j安全漏洞的事情,XX云因未及时报告漏洞被工信部暂停网络安全威胁和漏洞信息共享平台合作单位(https://www.cstis.cn/),话说Java的日志组件真是多而且也比较乱,后续几篇文章就聊一下各日志组件的使用及区别。common-logging是apache提供的一个通用日志接口,可以让应用程序使用日志不依赖于具体的实现类,提供了对Log4j、jdk内置Log、Avalon LogKit进行简单的包装,在应用程序运行时会动态适配找到对应的日志实现类。注:SPI机制的原理,见。
2023-10-31 22:48:16
263
原创 Java访问直接内存
直接内存是在Java堆外的,直接向系统申请内存空间,它不受JVM的内存管理机制控制。直接内存分配、使用和回收是通过java.nio.DirectByteBuffer这个类。
2023-10-31 08:22:41
203
原创 IDEA MyBatisX插件介绍
一般在项目中通过该方法生成基础的增、删、改、查基础代码,复杂的查询还是要自己写,一般对于一张表可以通过生成器生成一套代码,然后自己再根据需求扩展一套代码(XML和Mapper类),比如再加一个MapperExt类里边放你自己编写的代码,这样在数据库新增字段的时候原来那套(XML和Mapper)可以重新生成直接覆盖。在这里可以配置各种数据的连接,配置好后点测试连接会自动下载对应数据库的驱动。然后就可以生成对应的代码,在Database中选中表。代码生成后,我们可以在DAO和XML中快速进行跳转。
2023-10-31 08:08:44
2141
原创 gRPC源码剖析-Builder模式
创建一个Person对象,姓名和性别是必须的,年龄和身高等其他属性是可选的,我们有几种方法来创建,第一种是用需要写很多个重载的构造函数,另外一种直接使用JavaBean的set方法但没有办法约束是否必选。关于设计模式的概念对于业务开发人员掌握常用的几种就行(用得最多的是策略模式),但要读懂各底层框架,还是需要对所有设计模式都有所了解,否则很难读得懂源代码,并且好多设计模式加上各种变种容易搞混,似是而非,看似简单掌握起来确不容易,用好更难。当创建复杂对象的算法应独立于该对象的组成部分以及它们的装配方式时。
2023-10-31 07:22:03
810
原创 gRPC源码剖析-Server启动流程
SPI 全称Service Provider Interface是一种服务发现机制,它通过在ClassPath路径下提供的META-INF/services目录里查找文件,然后自动加载文件所定义的类,SPI的应用还是比较广泛的,比如加载JDBC驱动,另外业务层架构也有使用SPI机制的,比如淘宝早期交易中心系统,各业务方提供自己的交易扩展类,这样不会影响主交易流程。注:低版本好像是会为每一个监听地址构建一个NettyServr,但grpc-netty1.7.1版本源代码只构建了一个NettyServer。
2023-10-31 07:10:05
539
3
原创 gRPC通信模式
这个文章的例子其实和RESTful在通信模式上没有什么区别,也是一次请求然后一个响应的模式,如果真是这样那gRPC就没啥意思了,今天我们来看一下gRPC四种通信模式。一个请求消息对应一个响应消息,然后关闭连接,请求信息以EOS结尾,响应消息以trailer结尾。Game必须继续,妹子很喜欢你,你要相信凭你的长相和钱包有这样的妹子你不好好把握那是个大傻子。一直在接收消息,但就是不想回你,最后才烦了,回你一句滚,Game Over吧。你:宝,我去输液,输的什么液,想你的夜。妹子:快点和我说,我急死了。
2023-10-31 06:56:31
131
原创 gRPC初体验
1、RPC是远程过程调用的简称,在分布式系统中,客户端可以像调用本地对象一样调用远程机器上服务端对象,用于系统的垂直拆分,常见的JAVA RPC框架有JAVA自带的RMI、基于Http的Hessian、阿里基于TCP的Dubbo、淘宝基于TCP的HSF、Spring Cloud等。服务接口的编码依赖于protoc-gen-grpc-java插件,mac下安装protoc-gen-grpc-java,下载protoc-gen-grpc-java配置环境。service:服务端代码。clien:客户端代码。
2023-10-30 18:01:17
278
原创 Gateway一个诡异问题处理过程
虽然在日志中没有发现OOM,但观察到gc日志在40分钟左右heap会升到300多M,然后GC也比较频繁(YGC),怀疑是我们网关中一个定时任务(每隔15秒从Redis中注册的权限(路径+权限标识)同步到本地Map)占用了大量资源,这个定时任务在我们应用场景中必要性并不大,属于过度设计了,先摘掉再说,YGC频度降下来了,但问题依旧。但因为我们测试环境,微服务是单机并不是集群部署的,怀疑单机配置了这个负载均衡造成无法访问,移除掉代码,重启服务,一段时间后问题又出现。
2023-10-30 16:07:05
466
原创 Flask-SQLAlchemy事件钩子介绍
注:大多数据开源框架都会提供扩展点(钩子),在十几年前做数据库水平切割的时候就是扩展了IBatis 的SQL执行器,通过对UUID取模的方式做记录到对应分表的路由,其实说白了就是在SQL执行器里把SQL语句中的表名替换成分表表名 ,这样使用你这个组件的人就不用去关注具体的分表逻辑,只需要配置分表的数量和分表算法依赖的字段。属性事件的参数既有value,也有oldvalue,这和MySQL的触发器差不多,所以有文章在介绍SQLAlchemy事件时也叫触发器,其实指的就是SQLAlchemy属性事件。
2023-10-30 08:44:49
1000
2
原创 Flask_Login使用与源码解读
注:Flask是一个微框架,仅提供包含基本服务的核心(路由、网关接口、模板),其它功能都是通过扩展来实现,它有无数扩展,你可以根据需要自由组合,这一系列文章我们会来介绍一下这些扩展的使用以及解读一下其源码,另外关于分布系统登录方案可以参考 《注:如果用户登录后,会将user存储在当前request_context中,我们就可以直接获取,如果request_context中没有user对象,将调用_load_user()来恢复(服务器重启就会走这个路径,浏览器并不需要重新登录)
2023-10-30 08:33:27
817
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人