Skip to content

Commit 20db496

Browse files
committed
refactor: 将限流功能集成至Raft缓存管理器
- 在CacheManagerRaftReq和CacheManagerRaftResult中添加Limit和Limiter变体 - 在DirectCacheManager中实现handle_limit方法处理限流逻辑 - 更新Console登录API和OpenAPI登录使用新的Raft缓存限流 - 统一登录限流和限流计数清除的缓存操作 - 更新AGENTS.md构建命令
1 parent aa60e0f commit 20db496

File tree

5 files changed

+89
-16
lines changed

5 files changed

+89
-16
lines changed

AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# AGENTS.md - r-nacos 开发指南
22

33
## 构建/测试命令
4-
- 构建:`cargo build --release`
4+
- 构建:`cargo build`
55
- 测试:`python3 integration_tests/scripts/run_test.py` (运行完整集成测试)
66
- 单元测试:`cargo test` (运行所有单元测试)
77
- 单个测试:`cargo test test_name` (运行指定测试)
@@ -42,4 +42,4 @@
4242
### 部署相关
4343
- 环境变量前缀:`RNACOS_`
4444
- 默认端口:8848 (HTTP), 9848 (gRPC), 10848 (Console)
45-
- 支持单机和集群部署模式
45+
- 支持单机和集群部署模式

src/cache/actor_model.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use crate::cache::model::{CacheKey, CacheValue};
22
use crate::now_second_i32;
3+
use crate::raft::cache::CacheLimiterReq;
34
use actix::Message;
5+
use ratelimiter_rs::RateLimiter;
46
use serde::{Deserialize, Serialize};
7+
use std::sync::Arc;
58

69
#[derive(Clone, Debug, Serialize, Deserialize)]
710
pub struct CacheSetParam {
@@ -60,6 +63,7 @@ pub enum CacheManagerRaftReq {
6063
Get(CacheKey),
6164
Exists(CacheKey),
6265
Ttl(CacheKey),
66+
Limit(CacheLimiterReq),
6367
}
6468

6569
#[derive(Clone, Debug, Serialize, Deserialize)]
@@ -70,6 +74,7 @@ pub enum CacheManagerRaftResult {
7074
Value(CacheValue),
7175
Exists(bool),
7276
Ttl(i32),
77+
Limiter(bool),
7378
}
7479

7580
pub type CacheManagerResult = CacheManagerRaftResult;

src/cache/core.rs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
use crate::cache::actor_model::{
2-
CacheManagerLocalReq, CacheManagerRaftReq, CacheManagerRaftResult, CacheSetParam,
2+
CacheManagerLocalReq, CacheManagerRaftReq, CacheManagerRaftResult, CacheManagerResult,
3+
CacheSetParam,
34
};
45
use crate::cache::model::{CacheKey, CacheValue};
56
use crate::common::constant::DIRECT_CACHE_TABLE_NAME;
7+
use crate::common::datetime_utils::now_millis_i64;
68
use crate::common::datetime_utils::now_second_i32;
9+
use crate::common::limiter_utils::LimiterData;
710
use crate::common::pb::data_object::DirectCacheItemDo;
11+
use crate::raft::cache::CacheLimiterReq;
812
use crate::raft::filestore::model::SnapshotRecordDto;
913
use crate::raft::filestore::raftapply::{RaftApplyDataRequest, RaftApplyDataResponse};
1014
use crate::raft::filestore::raftsnapshot::{SnapshotWriterActor, SnapshotWriterRequest};
1115
use actix::prelude::*;
1216
use bean_factory::{bean, Inject};
13-
use inner_mem_cache::{MemCache, TimeoutSet};
17+
use inner_mem_cache::TimeoutSet;
1418
use quick_protobuf::{BytesReader, Writer};
19+
use ratelimiter_rs::RateLimiter;
1520
use std::collections::HashMap;
21+
use std::convert::TryInto;
1622
use std::sync::Arc;
1723

1824
pub struct CacheItem {
@@ -211,6 +217,43 @@ impl DirectCacheManager {
211217
}
212218
}
213219

220+
fn handle_limit(&mut self, limit_req: CacheLimiterReq) -> anyhow::Result<CacheManagerResult> {
221+
let (rate_to_ms_conversion, key, limit) = match limit_req {
222+
CacheLimiterReq::Second { key, limit } => (1000, key, limit),
223+
CacheLimiterReq::Minutes { key, limit } => (60 * 1000, key, limit),
224+
CacheLimiterReq::Hour { key, limit } => (60 * 60 * 1000, key, limit),
225+
CacheLimiterReq::Day { key, limit } => (24 * 60 * 60 * 1000, key, limit),
226+
CacheLimiterReq::OtherMills {
227+
key,
228+
limit,
229+
rate_to_ms_conversion,
230+
} => (rate_to_ms_conversion, key, limit),
231+
};
232+
let key = CacheKey::new(crate::cache::model::CacheType::String, key);
233+
let now = now_millis_i64();
234+
let mut limiter = if let Some(v) = self.get_valid_value(&key) {
235+
if let Some(s) = v.try_to_string() {
236+
let limiter_data: LimiterData = s.as_str().try_into()?;
237+
limiter_data.to_rate_limiter()
238+
} else {
239+
RateLimiter::load(rate_to_ms_conversion, 0, now)
240+
}
241+
} else {
242+
RateLimiter::load(rate_to_ms_conversion, 0, now)
243+
};
244+
let r = limiter.acquire(limit, limit as i64);
245+
if r {
246+
let limiter_data: LimiterData = limiter.into();
247+
let cache_value = CacheValue::String(Arc::new(limiter_data.to_string()));
248+
self.do_set(
249+
key.clone(),
250+
cache_value,
251+
((now + rate_to_ms_conversion as i64) / 1000) as i32,
252+
);
253+
}
254+
Ok(CacheManagerRaftResult::Limiter(r))
255+
}
256+
214257
fn build_snapshot(&self, writer: Addr<SnapshotWriterActor>) -> anyhow::Result<()> {
215258
let now = now_second_i32();
216259
for (key, v) in self.cache.iter() {
@@ -295,6 +338,7 @@ impl Handler<CacheManagerRaftReq> for DirectCacheManager {
295338
CacheManagerRaftReq::Ttl(key) => Ok(self.get_ttl(&key)),
296339
CacheManagerRaftReq::Incr(key, expire) => Ok(self.incr(key, expire)),
297340
CacheManagerRaftReq::Decr(key, expire) => Ok(self.decr(key, expire)),
341+
CacheManagerRaftReq::Limit(limit_req) => self.handle_limit(limit_req),
298342
}
299343
}
300344
}

src/console/login_api.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::ldap::model::actor_model::{LdapMsgReq, LdapMsgResult};
77
use crate::ldap::model::LdapUserParam;
88
use crate::oauth2::model::actor_model::{OAuth2MsgReq, OAuth2MsgResult};
99
use crate::oauth2::model::OAuth2UserParam;
10-
use crate::raft::store::ClientRequest;
10+
use crate::raft::store::{ClientRequest, ClientResponse};
1111
use crate::{
1212
common::{
1313
appdata::AppShareData,
@@ -255,8 +255,16 @@ async fn apply_session(
255255
.request(ClientRequest::CacheReq { req: cache_req })
256256
.await?;
257257
//登录成功后清除登陆限流计数
258-
let clear_limit_req = CacheManagerReq::Remove(CacheKey::new(CacheType::String, limit_key));
259-
app.cache_manager.do_send(clear_limit_req);
258+
let clear_limit_req = crate::cache::actor_model::CacheManagerRaftReq::Remove(CacheKey::new(
259+
CacheType::String,
260+
limit_key,
261+
));
262+
app.raft_request_route
263+
.request(ClientRequest::CacheReq {
264+
req: clear_limit_req,
265+
})
266+
.await
267+
.ok();
260268
let login_token = LoginToken {
261269
token: token.to_string(),
262270
};
@@ -315,9 +323,14 @@ async fn login_limit(
315323
key: limit_key.clone(),
316324
limit: app.sys_config.console_login_one_hour_limit as i32,
317325
};
326+
let cache_req = crate::cache::actor_model::CacheManagerRaftReq::Limit(limit_req);
318327
//登录前先判断是否登陆准入
319-
if let Ok(CacheManagerResult::Limiter(acquire_result)) =
320-
app.raft_cache_route.request_limiter(limit_req).await
328+
if let Ok(ClientResponse::CacheResp {
329+
resp: CacheManagerRaftResult::Limiter(acquire_result),
330+
}) = app
331+
.raft_request_route
332+
.request(ClientRequest::CacheReq { req: cache_req })
333+
.await
321334
{
322335
if !acquire_result {
323336
return Some(HttpResponse::Ok().json(ApiResult::<()>::error(

src/openapi/auth.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
use crate::cache::actor_model::CacheSetParam;
1+
use crate::cache::actor_model::{CacheManagerRaftResult, CacheSetParam};
22
use crate::common::appdata::AppShareData;
33
use crate::common::model::TokenSession;
44
use crate::common::option_utils::OptionUtils;
55
use crate::merge_web_param_with_result;
66
use crate::raft::cache::model::{CacheKey, CacheType, CacheValue};
77
use crate::raft::cache::{CacheLimiterReq, CacheManagerReq, CacheManagerResult};
8-
use crate::raft::store::ClientRequest;
8+
use crate::raft::store::{ClientRequest, ClientResponse};
99
use crate::user::{UserManagerReq, UserManagerResult};
1010
use actix_web::{web, HttpResponse, Responder};
1111
use serde::{Deserialize, Serialize};
@@ -70,9 +70,14 @@ async fn do_login(
7070
key: limit_key.clone(),
7171
limit: app.sys_config.openapi_login_one_minute_limit as i32,
7272
};
73+
let cache_req = crate::cache::actor_model::CacheManagerRaftReq::Limit(limit_req);
7374
//登录前先判断是否登陆准入
74-
if let Ok(CacheManagerResult::Limiter(acquire_result)) =
75-
app.raft_cache_route.request_limiter(limit_req).await
75+
if let ClientResponse::CacheResp {
76+
resp: CacheManagerRaftResult::Limiter(acquire_result),
77+
} = app
78+
.raft_request_route
79+
.request(ClientRequest::CacheReq { req: cache_req })
80+
.await?
7681
{
7782
if !acquire_result {
7883
return Err(anyhow::anyhow!(
@@ -118,9 +123,15 @@ async fn do_login(
118123
.request(ClientRequest::CacheReq { req: cache_req })
119124
.await?;
120125
//登录成功后清除登陆限流计数
121-
let clear_limit_req =
122-
CacheManagerReq::Remove(CacheKey::new(CacheType::String, limit_key));
123-
app.cache_manager.do_send(clear_limit_req);
126+
let clear_limit_req = crate::cache::actor_model::CacheManagerRaftReq::Remove(
127+
CacheKey::new(CacheType::String, limit_key),
128+
);
129+
app.raft_request_route
130+
.request(ClientRequest::CacheReq {
131+
req: clear_limit_req,
132+
})
133+
.await
134+
.ok();
124135
let login_result = LoginResult {
125136
access_token: Some(token),
126137
token_ttl: app.sys_config.openapi_login_timeout as i64,

0 commit comments

Comments
 (0)