Devops

Docker

Docker是一种开源的容器化平台,它可以将应用程序及其依赖项打包成一个独立的Docker容器,可以很方便的在不同的服务器上部署运行,作用就是一句话:Docker解决了运行环境不一致所带来的问题,可以有效地防止开发、测试、运维互相扯皮。

常用命令

  1. docker run:启动一个容器,如果镜像不存在则从Docker Hub上下载。
  2. docker ps:列出当前正在运行的容器。
  3. docker stop:停止一个容器。
  4. docker rm:删除一个容器。
  5. docker images:列出本地镜像。
  6. docker pull:下载一个镜像。
  7. docker push:将一个镜像上传到Docker Hub。
  8. docker exec:在运行的容器中执行命令。

K8S

常用命令

  1. kubectl create:创建一个资源。
  2. kubectl get:获取资源的状态。
  3. kubectl apply:更新或创建资源。
  4. kubectl delete:删除资源。
  5. kubectl describe:显示资源的详细信息。
  6. kubectl logs:获取Pod的日志。
  7. kubectl exec:在Pod中执行命令。
  8. kubectl scale:扩展或缩小Deployment的副本数量。

Redis+lua

可以使用Redis和Lua脚本来实现防止重复提交攻击的功能,具体步骤如下:

  1. 客户端在提交请求前,先向Redis中查询是否已经存在相同的请求,如果存在则直接返回重复提交的错误提示。
  2. 如果Redis中不存在该请求,则将该请求的唯一标识作为key,设置一个过期时间,并将其保存在Redis中。这里的唯一标识可以是请求的URL、请求的参数组合、或者是一个由多个参数计算得出的hash值等。
  3. 为了避免在高并发情况下,多个客户端同时设置同一个key的情况,可以使用Redis提供的setnx(SET if Not eXists)指令,确保只有第一个请求才能成功设置该key。
  4. 为了避免客户端异常退出或崩溃等情况导致锁无法释放,可以使用Redis提供的expire命令设置过期时间,确保在一定时间后自动释放该锁。
  5. 在Redis中保存的key的命名方式需要有一定的规则,避免和其他key产生冲突。
  6. 使用Lua脚本来实现以上的操作,可以确保在Redis执行脚本期间,不会有其他客户端干扰其中的操作。

下面是一个简单的示例代码,实现了使用Redis和Lua脚本防止重复提交攻击的功能:

1
2
3
4
5
6
7
-- 判断key是否存在,如果存在则返回1,否则设置key,并设置过期时间,返回0
if redis.call("exists", KEYS[1]) == 1 then
return 1
else
redis.call("set", KEYS[1], ARGV[1], "ex", ARGV[2])
return 0
end

在使用时,客户端只需要调用Redis提供的eval命令来执行以上的Lua脚本,并传入需要设置的key、value以及过期时间即可。如果返回值为1,则说明该请求已经存在,需要提示用户重复提交;如果返回值为0,则说明该请求是新的请求,可以继续处理。

JWT

JWT(JSON Web Token)是一种基于 Token 的认证授权机制,是一种轻量级的、跨语言的认证方式。JWT将用户信息加密后存储在 Token 中,在用户请求服务时,客户端将 Token 作为请求头或参数发送到服务端,服务端通过验证 Token 来进行认证授权。

JWT由三部分组成,分别是 Header、Payload、Signature,它们使用点号”.”分隔开。具体格式如下:

1
{Base64UrlEncode(Header)}.{Base64UrlEncode(Payload)}.{Signature}

其中,Header是一个JSON对象,包含加密算法和类型等信息。Payload是一个JSON对象,存储用户的一些基本信息,如用户ID、角色等信息。Signature则是用于验证Token是否被篡改的签名,由Header、Payload以及一个密钥共同生成。

JWT的认证流程如下:

  1. 用户使用用户名和密码向服务端发送请求。
  2. 服务端验证用户信息,如果验证成功,将用户ID等信息加密生成JWT。
  3. 服务端将JWT作为响应返回给客户端,客户端将JWT保存在本地。
  4. 客户端在后续请求中将JWT作为请求头或参数发送给服务端。
  5. 服务端验证JWT的合法性和有效期,如果验证通过,继续处理请求;否则返回未授权的错误信息。

JWT的优点如下:

  1. 轻量级、跨语言。JWT是一种轻量级的认证方式,不需要在服务端保存用户信息,因此可以很方便地跨语言使用。
  2. 安全性高。由于JWT是基于Token的,因此不会在服务端保存用户信息,也不需要在客户端保存敏感信息,因此安全性相对较高。
  3. 可扩展性强。由于JWT使用JSON格式存储用户信息,因此可以很方便地扩展其他信息。
  4. 无状态性。JWT是无状态的,服务端不需要保存任何状态信息,可以很方便地进行负载均衡。

JWT的缺点如下:

  1. 存在安全隐患。如果密钥泄露,那么攻击者可以伪造Token,并进行恶意操作。
  2. Token大小较大。由于Token中需要携带用户信息和签名等信息,因此相对于其他认证方式,Token的大小较大,可能会导致网络传输开销较大。

综上所述,JWT是一种安全性高、可扩展性强的认证方式,适合于轻量级的跨语言应用场景。

Spring Schedule定时任务

Spring Schedule是Spring框架提供的一种定时任务调度框架,可以轻松地创建和管理各种类型的定时任务。Spring Schedule提供了很多功能,包括简单的定时任务、定时任务调度、任务超时控制等等。

在Spring中,使用Spring Schedule创建定时任务非常简单,只需要遵循以下步骤:

  1. 在Spring的配置文件中配置定时任务。可以使用注解或XML方式配置。
  2. 创建一个带有@Scheduled注解的方法,该方法将被定期执行。
  3. 在定时任务方法上设置执行周期,包括定时任务执行的间隔时间、执行时间、任务延迟等。

下面是一个简单的Spring Schedule定时任务的例子,使用注解方式:

1
2
3
4
5
6
7
8
@Component
public class MyTask {

@Scheduled(fixedRate = 1000) // 每隔1秒执行一次
public void doTask() {
// 执行任务逻辑
}
}

上面的代码使用@Scheduled注解表示这个方法是一个定时任务,并且使用fixedRate属性设置了每隔1秒执行一次。可以使用cron表达式指定任务的执行时间,例如:

1
2
3
4
5
6
7
8
@Component
public class MyTask {

@Scheduled(cron = "0 0/1 * * * ?") // 每分钟执行一次
public void doTask() {
// 执行任务逻辑
}
}

在上面的例子中,使用了cron表达式来指定定时任务的执行时间。cron表达式是一种灵活的语法,可以指定具体的执行时间,比如每分钟、每小时、每天等。

Spring Schedule还提供了其他很多定时任务的属性,可以控制任务的延迟、执行顺序、异常处理等。Spring Schedule还支持任务超时控制,可以设置任务的超时时间,并在任务超时后进行处理。

总之,Spring Schedule是一种简单、灵活、功能丰富的定时任务调度框架,非常适合Java开发人员创建和管理各种类型的定时任务。

CompletableFuture异步编排

概念

  • CompletableFuture是JDK1.8里面引入的一个异步回调类,就是说当前使用异步线程去执行一个任务时候,我们希望在这个任务结束以后,触发一个后续的动作,而CompletableFuture就可以实现这样的功能。
1
举个简单的例子:在一个批量支付的业务逻辑里面,涉及到查询订单,支付和发送邮件通知这三个逻辑,那么这三个逻辑是按照顺序,同步去实现的,也就是说先查询订单,查询到以后再针对这个订单发起支付,支付成功以后再发送邮件通知,而这种设计方式会导致这个方法的执行效率会比较慢。
1
所以,在这里我们可以直接使用CompletableFuture,也就是说我们可以把查询到订单的逻辑,放在一个异步线程里面去处理,然后基于CompletableFuture 一个事件回调机制,我们可以配置查询订单,结束之后的一个触发支付的一个动作,支付结束之后再自动触发邮件通知,从而极大的去提升这个业务场景的处理性能。
  • CompletableFuture提供了5种不同方式,把多个异步任务组成一个具有先后关系的任务链,然后基于事件来驱动任务链的一个执行。

  • 第一种是thenCombine, 把2个任务组合在一起,当2个任务都执行结束以后,触发某个事件的回调,

  • 第二种是thenCompose,它同样是把2个任务组合在一起,那么这2个任务是串行执行的,也就是说第一个任务执行结束以后,自动去触发执行第二个任务,

  • 第三种thenAccept,它是第一个任务执行结束以后,触发第二个任务,并且第一个任务的执行结果,作为第二个任务的一个参数,这个方法是纯粹的接受上一个任务的执行结果,不返回任何新的计算值。

  • 第四种是thenApply和thenAccept一样,它是一种具有返回值的一个方法;

  • 第五种是thenRun,就是说第一个任务执行完成以后,触发执行一个实现Runnable接口的一个任务,

  • 最后我认为CompletableFuture,弥补了原本Future的一个不足,使得程序可以在非阻塞的状态下,去完成异步的一个回调机制。

Seata中的TCC事务

Seata是一个分布式事务解决方案,它支持多种事务模式,其中之一就是TCC(Try-Confirm-Cancel)事务模式。

TCC事务模式是一种基于预留资源的分布式事务处理方式,将整个事务分为三个步骤:尝试(Try)、确认(Confirm)和撤销(Cancel)。在TCC事务模式中,每个步骤都对应一个方法。这些方法可以是本地方法,也可以是远程方法,它们通过执行来进行预留和释放资源。

在TCC事务模式中,事务管理器首先执行“尝试”步骤,以预留所有参与者的资源。如果所有步骤都成功,则执行“确认”步骤来提交整个事务。如果任何一个步骤失败,事务管理器将执行“撤销”步骤来回滚整个事务,并释放所有已经预留的资源。

Seata的TCC事务模式提供了一个注解式编程模型,可以在业务方法中添加相关注解,以使用TCC事务模式。同时,Seata还提供了可扩展的TCC事务协调器接口,允许开发人员实现自定义的TCC事务协调器,以满足不同的业务需求。

Seata是什么

Seata是一个开源的分布式事务解决方案,它旨在解决分布式系统下的事务问题。Seata提供了高可用性、高性能和易扩展的分布式事务解决方案,适用于微服务架构下的分布式事务场景。

Seata包括三个核心组件:

  1. Transaction Coordinator (TC) - 事务协调器:负责协调全局事务的启动、提交和回滚等操作,是Seata中的核心组件。
  2. Transaction Manager (TM) - 事务管理器:负责本地事务的管理和协调,与业务代码集成。
  3. Resource Manager (RM) - 资源管理器:负责管理分支事务,如数据库、消息队列、缓存等资源的事务操作。

在Seata的架构中,应用程序通过Seata的Client端来访问TC,从而实现全局事务的控制。当应用程序调用业务代码时,TM会对业务代码进行增强,将业务代码包装在本地事务中,并协调各个RM参与全局事务的分支事务。

Seata支持多种分布式事务模式,如 AT、TCC、SAGA 等。它还提供了与多种编程语言和框架集成的支持,如 Java、Spring、Dubbo、Hystrix、Feign 等。此外,Seata还支持容器化部署和云原生架构。

总之,Seata是一个非常强大和流行的分布式事务解决方案,可以帮助开发者解决分布式事务的问题,提高系统的可靠性和性能。

一个分布式事务在Seata中的执行流程:

  1. TM 向 TC 申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的 XID。
  2. XID 在微服务调用链路的上下文中传播。
  3. RM 向 TC 注册分支事务,接着执行这个分支事务并提交(重点:RM在第一阶段就已经执行了本地事务的提交/回滚),最后将执行结果汇报给TC。
  4. TM 根据 TC 中所有的分支事务的执行情况,发起全局提交或回滚决议。
  5. TC 调度 XID 下管辖的全部分支事务完成提交或回滚请求。

Seata的工作原理是什么

Seata的工作原理如下:

  1. 事务发起方向 Seata Server 发起全局事务,Seata Server 生成全局事务ID。
  2. 事务参与方在本地事务完成后,向 Seata Server 发起注册分支事务请求,包括本地事务ID和全局事务ID。
  3. Seata Server 记录全局事务和分支事务的关系,以及各分支事务的状态信息。
  4. 分支事务向 Seata Server 汇报本地事务执行结果。
  5. 当所有分支事务都成功执行并向 Seata Server 汇报时,Seata Server 发起针对全局事务的提交请求。
  6. Seata Server 将提交请求发送给所有分支事务,各分支事务收到请求后执行本地事务的提交操作。
  7. 当所有分支事务都提交成功后,Seata Server 向事务发起方发送全局事务提交成功的响应。
  8. 如果有任何一个分支事务执行失败,Seata Server 发起针对全局事务的回滚请求。
  9. Seata Server 将回滚请求发送给所有分支事务,各分支事务收到请求后执行本地事务的回滚操作。
  10. 当所有分支事务都回滚成功后,Seata Server 向事务发起方发送全局事务回滚成功的响应。

总的来说,Seata 通过在分支事务和全局事务之间建立映射关系,以及在 Seata Server 上协调和管理各个分支事务的状态,来实现分布式事务的一致性。

Seata怎么使用

  1. 下载Seata

可以从Seata的官网(https://seata.io/zh-cn/)下载Seata的发行版,也可以从Seata的Github仓库(https://github.com/seata/seata)获取最新的代码。

  1. 配置Seata

Seata的配置主要包括全局配置和各个组件的配置,具体配置可以参考Seata的官方文档。在配置中,需要指定TC、TM和RM的地址和端口等信息,以及各种事务模式的相关配置。

  1. 引入Seata依赖

如果是使用Java语言开发,可以通过Maven或Gradle等构建工具引入Seata的依赖,例如:

1
2
3
4
5
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
<version>${seata.version}</version>
</dependency>
  1. 集成Seata

Seata提供了与多种框架和组件的集成支持,如Spring、Dubbo、MyBatis、RocketMQ等,具体集成方式可以参考Seata的官方文档。

以Spring Boot框架为例,需要在启动类上添加注解@EnableAutoDataSourceProxy,以开启数据源代理;并在application.yml或application.properties文件中配置Seata的相关信息,例如:

1
2
3
4
5
6
7
8
9
10
seata:
enabled: true
application-id: seata-demo
tx-service-group: my_tx_group
service:
vgroup-mapping:
my_tx_group: default
group-id: default
enable-degrade: false
disable-global-transaction: false
  1. 编写业务代码

在业务代码中,需要使用Seata提供的API,将本地事务注册到全局事务中,例如:

1
2
3
4
5
@GlobalTransactional(timeoutMills = 300000, name = "demo-tx")
public void doBusiness() {
// do some business logic
// ...
}

在上述代码中,通过@GlobalTransactional注解将doBusiness方法注册到全局事务中,指定了事务的超时时间和事务名称。

  1. 启动Seata

在所有的配置和代码编写完成后,可以启动Seata的各个组件,如TC、TM和RM等,以及应用程序本身。

总之,使用Seata的过程中,需要进行配置、引入依赖、集成Seata、编写业务代码和启动Seata等步骤,同时需要了解Seata的各种配置和API,以便正确地使用分布式事务的功能。

0%