tonglin0325的个人主页

Thrift通信协议

Thrift的通信协议主要有下面几种:

TBinaryProtocol:二进制协议

TCompactProtocol:带压缩的二进制协议

TJSONProtocol:Json协议,序列化结果例如

1
2
{"2":{"i64":1},"3":{"str":"lintong"},"4":{"lst":["i64",3,1,2,3]}}

TSimpleJSONProtocol:simple Json协议,该协议为只写,即不可反序列化,序列化结果例如

1
2
{'name': 'XiaoMing', 'age': '20'}

TMultiplexedProtocol

TTupleProtocol

全文 >>

go学习笔记——gin限流

如果想在Gin Web服务中实现限流功能,可以使用ulule/limiter

ulule/limiter是一款支持分布式限流的框架,其可以在Redis中存储和共享限流状态,从而在分布式环境中实现一致的限流逻辑。

1.引用

1
2
go get github.com/ulule/limiter/v3@v3.11.2

2.Gin限流中间件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package middleware

import (
"github.com/gin-gonic/gin"
"github.com/redis/go-redis/v9"
"github.com/ulule/limiter/v3"
mgin "github.com/ulule/limiter/v3/drivers/middleware/gin"
redisstore "github.com/ulule/limiter/v3/drivers/store/redis"
"time"
)

func RateLimitMiddleWare(rdb *redis.Client) gin.HandlerFunc {
// 定义限流规则:1 请求/10秒
rate := limiter.Rate{
Period: 10 * time.Second,
Limit: 1,
}
// 创建限流存储
store, err := redisstore.NewStoreWithOptions(rdb, limiter.StoreOptions{
Prefix: "rate_limiter", // Redis 键的前缀
})
if err != nil {
panic(err)
}
// 创建限流实例
instance := limiter.New(store, rate)
middleware := mgin.NewMiddleware(instance)
return middleware
}

3.在router中使用限流中间件

1
2
3
4
// ratelimit
rateLimitMiddleWare := middleware.RateLimitMiddleWare(redisClient)
authGroup.Use(rateLimitMiddleWare)

4.限流效果,如果限流的话,接口将会返回429的状态码

1
2
3
4
5
6
7
8
9
10
11
12
curl -i --request GET 'http://172.17.0.229:18080/api/v1/user/3' \
--header 'Content-Type: application/json'
HTTP/1.1 429 Too Many Requests
Content-Type: text/plain; charset=utf-8
X-Ratelimit-Limit: 1
X-Ratelimit-Remaining: 0
X-Ratelimit-Reset: 1734772666
Date: Sat, 21 Dec 2024 09:17:38 GMT
Content-Length: 14

Limit exceeded

在redis中会存储限流状态,如下

其中默认的key是prefix+ip,value是API的请求次数

全文 >>

Java单例设计模式

单例模式(Singleton Pattern)是Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。 这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

1.没有使用单例:重复调用会创建多个对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package java_basic;

class Singleton{
public Singleton(){
}

public void print(){
System.out.println("Hello Word");
}
}

public class singleton {

public static void main(String[] args) {
Singleton s1 = new Singleton();
Singleton s2 = new Singleton();
Singleton s3 = new Singleton();
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(s3.hashCode());
s1.print();
s2.print();
s3.print();
}

}

全文 >>

logback,log4j和log4j2的区别

1.logback的使用,参考:logback的使用和logback.xml详解

pom文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<logback.version>1.1.7</logback.version>
<slf4j.version>1.7.21</slf4j.version>
</properties>

<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
</dependencies>

代码

1
2
3
4
5
import org.slf4j.Logger
import org.slf4j.LoggerFactory

private static final Logger log = LoggerFactory.getLogger(LoggingDemo.class);

    

2.log4j的使用

pom文件

1
2
3
4
5
6
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>

代码

1
2
3
4
import org.apache.log4j.Logger;

private final Logger LOGGER = Logger.getLogger(LoggingDemo.class.getName());

全文 >>