Kamafeel

求其上,得其中;求其中,得其下,求其下,必败


  • 首页

  • 归档

微服务划分指导

发表于 2022-10-05 | 分类于 微服务 , 理论

基本原理

软件是实现业务价值的。

理想的微服务,应该是能独立完成一个或一组业务能力。也最好是由一个独立团队或个人维护。

此外再考虑质量维度(吞吐量,可靠性,安全性)。

业务功能 是划分主要维度

高内聚,低耦合。
核心裕,支撑域,通用域,注意限界上下文。

business 微服务依赖 domain微服务, 反之不合理。

CCP原则

共同闭包:包中所有的类应该是同类变化的一个集合,如果要改包,要调整的类都应该包含在包内。

反例:2个微服务相互频繁调用,同步数据。

分布式单体

一个人要维护10个微服务,那大概率就只是一个分布式单体了

抗弱网

发表于 2022-10-05

SAAS架构设计

发表于 2022-03-29 | 更新于 2022-04-01 | 分类于 架构 , 产品

AWS

下面这个PDF已经说的很清楚了

https://docs.aws.amazon.com/zh_cn/wellarchitected/latest/saas-lens/wellarchitected-saas-lens.pdf

落地-资源模式

池模式(共享资源),简仓模式(独立资源)

落地-核心组件

租户公共模块(租户管理,用户鉴权,用户/租户对应关系,租户KPI,计量,计费,租户服务指标/趋势分析)

租户初始化管道将创建命名空间、部署服务(池模式,简仓模式,其他3种)

租户上下文装载和路由(nginx根据jwt解析其中租户负载部分,进行动态路由),后端K8S(pod集群安全策略PodSecurityPolicy进行访问限制)

租户上下文,在微服务中的传递,应该无感知化(mybatis-metaObjectHandler),开发人员只需要专注业务,而不应该考虑租户的维度
在微服务调用中把JWT,放header进行租户上下文传递,是比较推荐的做法,但是需要考虑JWT负载区,存放的授权信息(注意避免泄露不必要信息)

租户个性化

自定义选项来实现(租户个性化选项,系统预设)
插件模式(系统未预设,但可以灵活插件支持)
功能标记(租户功能清单),租户和SAAS服务的多对多关系

租户隔离

用户需要和租户形成映射关系(可能存在多对多的情况)
API 的入口点隔离
主题
• 筒仓隔离
(优点:隔离级别高,可满足个性化)
(缺点:敏捷差,自动装载机制复杂,去中心化复杂)
• 池隔离
(优点:敏捷,成本)
(缺点:嘈杂邻居,成本跟踪(计数不表示资源占有率))
• 桥接模式
混合隔离(简仓,池一起)
• 分层隔离
系统设计分层,有些层不需要进行隔离,都属于公共,对于资源数据层进行隔离
• 有针对性的隔离
微服务级别进行隔离,租户和微服务的对应进行资源隔离

扩展-数据保护

备份,利用基座进行数据隔离(hdfs,minio等对象存储桶策略),K8S平台的POD 安全策略PodSecurityPolicy

扩展-可靠性保障

资源限制(通过计量进行控制,利用队列进行排队,VIP租户单独队列),预留资源空闲, 并发感知,丢弃提示策略

扩展-计量维度

计算、存储、数据库、网络,访问次数

扩展-统计分析

资源占用和账单的分析比列

Spring Data Redis分析

发表于 2022-03-28 | 分类于 中间件 , Redis

价值

方便操作redis

入口

RedisAutoConfiguration(springboot系列都应该先去分析自动配置类)

底层实现

lettuce 基于netty的事情驱动模式

打开日志级别
io.netty.handler.codec.EncoderException
CommandHandler命令的编码/解码异常会导致,处理netty响应异常

jedis
单线程模式
连接使用socket = new Socket();分配在堆中,会导致线程不安全。

使用连接池可以避免,和降低Socket连接成本。

分布式锁

Redisson
核心,看门狗线程

特别注意多线程分布式锁的处理:

1
2
3
4
5
6
RLock lock = redissonClient.getLock(key);
if(lock.isLocked()){ // 是否还是锁定状态
if(lock.isHeldByCurrentThread()){ // 时候是当前执行线程的锁
lock.unlock(); // 释放锁
}
}

redis操作原子性

如果可能使用lua,进行操作原子性保障

参考

Lettuce和jedis
https://jishuin.proginn.com/p/763bfbd73b84
jedis线程不安全
https://cloud.tencent.com/developer/article/1678172

看门狗机制
https://www.cnblogs.com/jelly12345/p/14699492.html

web容器UnderTow

发表于 2022-03-25 | 分类于 中间件 , UnderTow

架构

基于Java XNIO,底层使用NIO(ByteBuffer)
Worker单元分:IO 线程池(evernLoop机制);Worker 线程池(处理阻塞的业务)

需要注意设置:

1
2
3
server:
undertow:
worker-threads: 200

对比

Jetty ,Tomcat 主要是庞杂(性能,直接内存使用)
reactor-netty(不好调试,回调写法,工程师不多)
Undertow 轻量设计

参考

https://www.helloworld.net/special/xtmylk/8793514997

缓存一致性协议MESI

发表于 2022-03-24 | 更新于 2022-03-25 | 分类于 架构 , 基础层

概念

缓存一致性协议,CPU多核缓存,主存

状态

M 修改
E 独享、互斥 (Exclusive)
S 共享 (Shared)
I 无效 (Invalid)

伪共享

Cache Line 缓存行通常是 64 字节
根据:
时间局部性(Temporal Locality):如果一个信息项正在被访问,那么在近期它很可能还会被再次访问
空间局部性(Spatial Locality):如果一个存储器的位置被引用,那么将来他附近的位置也会被引用

Cache Line加载是连续的一段

Java避免伪共享,补齐参数为64字节

1
2
3
4
5
6
//jdk1.8新方法
//添加vm options参数 -XX:-RestrictContended
@sun.misc.Contended
public final static class VolatileLong3 {
public volatile long value = 0L;
}

参考

https://www.cnblogs.com/yanlong300/p/8986041.html
https://juejin.cn/post/6934528318888738824

Pagecache和Buffercache

发表于 2022-03-24 | 更新于 2022-03-29 | 分类于 linux

基本概念

Page cache(页面缓存)
页缓冲或文件缓冲

Buffer cache(块缓存)
块缓冲,是对物理磁盘上的一个磁盘块进行的缓冲

Swap space(交换空间)
虚拟内存的表现形式。系统为了应付一些需要大量内存的应用,而将磁盘上的空间做内存使用

DMA(Direct Memory Access,直接存储器访问)

零拷贝

用户态与内核态的数据拷贝的次数为零(不使用流拷贝,使用指针,文件和进程虚拟地址空间映射)
linux底层 sendfile和mmap

java

alt

ByteBuffer申请的堆外内存也是由GC负责回收的,Hotspot在GC时会扫描Direct ByteBuffer对象是否有引用,如没有,当堆内的引用被gc回收时通过虚拟引用回收其占用的堆外内存

但是堆内可能只是一个对象引用的内存占用,不至于GC,导致堆外内存占用大,而堆内不需要GC。

堆外内存使用框架

Ehcache

参考

https://blog.csdn.net/daijiguo/article/details/106457319
https://zhuanlan.zhihu.com/p/161939673
https://juejin.cn/post/6844903744115572749

Java堆外内存使用
https://blog.csdn.net/qq_40977118/article/details/10812443
https://blog.csdn.net/liuxiao723846/article/details/89814005

Spring Boot引起的“堆外内存泄漏”排查及经验总结
https://tech.meituan.com/2019/01/03/spring-boot-native-memory-leak.html

Epoll说明和应用

发表于 2022-03-24

LRU缓存机制

发表于 2022-03-24

LongAdder

发表于 2022-03-24 | 更新于 2022-03-25 | 分类于 JAVA , 并发

概述

AtomicLong 只对一个 Long 值进行 CAS 操作。而 LongAdder 是针对 Cell 数组的某个 Cell 进行 CAS 操作 ,把线程的名字的 hash 值,作为 Cell 数组的下标,然后对 Cell[i] 的 long 进行 CAS 操作。简单粗暴的分散了高并发下的竞争压力

内核

cell对象使用@sun.misc.Contended避免伪共享

升级竞争的解决方案

参考

https://xilidou.com/2018/11/27/LongAdder/

12…21

Kamafeel

204 日志
57 分类
129 标签
© 2022 Kamafeel
由 Hexo 强力驱动 v3.9.0
|
主题 – NexT.Pisces v7.1.2