SPI机制
SPI机制什么是SPI?
SPI 即 Service Provider Interface(服务提供者的接口),服务提供者来实现这个接口,从而实现无需修改源代码,扩展程序、解耦的效果。
很多框架都使用了 Java 的 SPI 机制,比如:Spring 框架、数据库加载驱动、日志接口、以及 Dubbo 的扩展实现等等
API和SPI区别
API:由实现方定义和实现具体内容
SPI:由调用方实现具体内容,实现方定义具体接口
实现方式
JDK中的 ServiceLoader
需要在项目路径下MATE-INF/services文件目录下,创建以接口全路径的文件名的文件,实现类全路径为内容,以行为分割。
缺点:虽然是懒实例化,但是不管你使用不使用都会给你把class对象加载进来
JDBC中的 SPI
当我们去使用JDBC的时候,会去加载驱动类,但是我们必须指定的实现类,这种也是SPI的体现
123456// 加载 MySQL 驱动程序Class.forName("com.mysql.cj.jdbc.Driver");// 获取数据库连接Connec ...
spring面试
spring是什么
spirng是一个基于java语言开发的用于web的轻量级框架,
ioc和aop是spring的核心。
并且让开发人员专心于业务开发
spring 中的一些重要组件
core核心组件:其中beans和context是实现IOC的重要依赖(依赖注入)
aop组件主要用来做切面编程
web组件实现了web层的技术,例如springmvc对于请求做处理的
websocket:全双工及时通讯,服务器也能主动发送消息给客户端。
transactions: spring事务的管理依赖
JDBC、ORM、OXM等
Portlet被替换成webflex了
spring给我们带来了什么好处
对象解耦,对于一些类我们可以交给spring 来管理,而不用每次都自己来创建。这样不仅解决的硬编码的解耦,而且提高了对象的复用
AOP的支持,对于一些通用的功能,我们无需对很多地方进行修改,而是通过切面编程来处理,例如日志记录、认证权限的处理等
声明式事务,我们可通过transational这个注解来对事物进行处理,如果处理事务中失败则可回滚恢复数据
测试的支持,由于spirng提供的ioc ...
常见限流算法
常见流量场景
业务流量:正常用户使用流量
突发流量:某些特定时间所产生的流量,例如双11
恶意流量:服务器被攻击所产生的流量
常见限流算法
基于计数器
基于滑动窗口
漏桶
令牌桶
1、基于计数器
对于计数器算法,每隔固定一段时间限流固定流量,例如上图,2-3秒内限流500,4-5秒内限流500。但是3-4秒内可以拥有流量1000。导致可能会出现这种边界问题。边界之间流量值超过限定的流量
2、基于滑动窗口
滑动窗口则是将时间进行滑动,第一次时间限制1-2秒,第二次是2-3秒,第三次是3-4秒,这样间隔粒度更小,是能解决临界问题,如果粒度够小的话。
3、基于漏桶
漏桶算法,桶的大小一定,流出速度一定,如果流量突发很大,就会导致流量被抛弃。对突发流浪处理不是很好。
4、基于令牌桶
对于令牌桶,则是对桶算法的升级。对进去的流量需要去拿一个令牌,如果令牌被拿完了。就拒绝处理。请求被处理完成后会将令牌放入桶中。这种对于突发流量兼容也是不错的。只要令牌够的话,是能处理的。
SpringCloud
Eureka搭建eureka服务application.yml12345678910111213server: port: 10086eureka: client: fetch-registry: false service-url: defaultZone: http://127.0.0.1:10086/eurekaspring: main: banner-mode: off application: name: eureka-server
maven1234<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency>
访问url:1http://127.0.0.1:10086/
eureka服务注册application1234eure ...
leetcode刷题
1、78. 子集
问题
解析
1非正常解法:直接看输入、输出,能找出规律。每个数字都会和前面的数字进行合并,例如1:1和空集(不包含),2:2和空集(不包含),2和1,3:3和空集(不包含),3和1,3和2,3和2和1
代码
123456789101112131415class Solution { public List<List<Integer>> subsets(int[] nums) { List<List<Integer>> ans = new ArrayList<>(); ans.add(new ArrayList()); for(int i = 0; i < nums.length; i++) { int len = ans.size(); for(int j = 0; j < len; j++) { List temp = n ...
Netty
一款BIO网络通信框架
三大组件
channel
buffer
selector
java.noi中的byteBuffer读写都需要切换模式,因为byteBuffe内部有三个指针,当读写的时候postition指针都会从头开始,limit来限制能读多少和写多少,capacity能存储多少,对于数据未读完,需要调用compact()方法来压缩数据
123456789FileChannel channel = new FileInputStream("data.txt").getChannel();ByteBuffer buffer = ByteBuffer.allocate(1024);while (channel.read(buffer) != -1) { buffer.flip(); while (buffer.hasRemaining()) { log.info("{}", (char) buffer.get()); } buffer.clear ...
负载均衡算法
负载均衡算法
对服务器均衡请求,达到每个服务器能够均衡处理请求。
常见算法
随机访问:可能每次都在一个服务器上,并不能分布均匀到每个服务器上
轮询:请求均匀分配,但是服务器性能差异无法解决
权重轮询:可提前根据服务器性能来配置权重,但是配置后无法动态配置
Hash取模:通过对服务器个数取模来选择服务器,但是如果其中增加或者减少服务器,会导致取模结果不一致,例如 原来只有3台服务器,新增一台但是hash(key)是一致的,但是mod不一样数字,结果是不一致的。这样如果新增的服务器是有问题的,就会导致请求失败。业务不能正常执行。
hash一致性:增删对原hash结果影响较小,每个节点获取也相对均匀
Hash一致性
下方节点ABC放在hash环上, 但是这样会导致大部分hash后到节点A上, 造成hash倾斜。
这种问题,可以通过虚拟节点来将原来的节点扩容翻倍,再放到hash环上。从而尽量均衡
具体实现123456789101112131415161718192021222324252627282930313233343536373839404142434445464748 ...
RabbitMQ
MQ
消息队列,FIFO先进先出
可流量消峰、应用解耦,异步处理
RabbitMQ核心部分
简单模式、工作模式、发布订阅模式、路由模式、主题模式、发布确认模式
一个Broker实体多个Exchange交换机多个Queue队列
一个连接(TCP)多个信道(连接中的逻辑连接)
docker下载123docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 -e RABBITMQ_DEFAULT_USER=root -e RABBITMQ_DEFAULT_PASS=123456 rabbitmq:3.8.8-managementdocker run -d --name my_rabbitmq -p 5672:5672 -p 15672:15672 -v `pwd`/data:/var/lib/rabbitmq --hostname myRabbit -e RABBITMQ_DEFAULT_VHOST=my_vhost -e RABBITMQ_DEFAULT_USER=< 你的用户名> -e RABBITMQ_ ...
Docker桌面端问题
Docker桌面端问题1、无法启动Mysql点启动弹出提示:
1Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:3306 -> 0.0.0.0:0: listen tcp 0.0.0.0:3307
重启后无效果,然后查看下端口是否被占用了3307。也并没有占用,其中我并没有再windows端装任何mysql的服务,也不会有自启把3307给占用了
1netstat -aon|findstr 3307
然后再查询端口是否被禁用了TCP协议,也没有效果
1netsh interface ipv4 show excludedportrange protocol=tcp
尝试重新启动NAT网络。首先以管理员身份运行CMD。输入以下命令重新启动
12net stop winnatnet start winnat
此后重docker的WSL端点启动mysql,启动成功。并且navicat也能连接
JVM
JVM内存结构
程序计数器
用于记住下一条执行指令的地址, 线程之间切换,获取到了时间片,将获取程序计数器中的指令进行执行。
并且线程私有
不会有内存溢出问题
虚拟机栈(栈)
先进后出, 存储非native的Java方法(栈帧),执行新方法时会将方法放入栈中,并且执行完reutrn或者抛出异常,将会弹栈
设置大小 -Xss2024k
本地方法栈
与虚拟机栈最大区别是存入的是native方法
内存溢出
栈内存溢出: 递归调用方法,栈帧过大(栈帧容量大于栈内存)
堆内存溢出:
线程运行诊断
用top定位那个进程对cpu的占用过高或死锁
ps H -eo pid,tid,%cpu | grep 进程id (来定位那个线程导致的)
jstack 进程id (其中的线程id是16进制的,ps出来的是10进制)
最终可定位到代码行数
堆
通过new关键字,创建的对象
线程共享,存在线程安全问题
存在垃圾回收机制
设置大小 -Xmx 1024k
堆内存溢出
大量新建对象存在堆中无法得到回收
123456List list = new ArrayList<>( ...