Skip to content

Commit bcf4855

Browse files
committed
hot-reload
1 parent d53377a commit bcf4855

File tree

3 files changed

+58
-24
lines changed

3 files changed

+58
-24
lines changed

oneport/config.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ config:
22
# 监听地址
33
listen: 0.0.0.0:1111
44
# 热重启接口
5-
# api: 127.0.0.111:1111
5+
# api: 127.0.0.111:11111
66

77
rules:
88
# 字符串匹配

oneport/src/config.rs

+26-6
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use yaml_rust::YamlLoader;
99
pub static RULES: Lazy<Mutex<Vec<(Vec<u8>, String)>>> = Lazy::new(|| Mutex::new(Vec::new()));
1010
static CONFIG_PATHS: Lazy<Vec<&str>> = Lazy::new(|| vec!["config.yml", "oneport.yml", "oneport/config.yml", "oneport/oneport.yml"]);
1111
static LISTEN: &str = "0.0.0.0:1111";
12-
static LOCAL_API: &str = "127.0.0.111:1111";
12+
static LOCAL_API: &str = "127.0.0.111:11111";
1313

1414
/// 解引用内置规则
1515
fn dereference(key: &str) -> Vec<Vec<u8>> {
@@ -25,16 +25,35 @@ fn dereference(key: &str) -> Vec<Vec<u8>> {
2525
}
2626
}
2727

28-
pub async fn find_config(file: Option<String>) -> Result<String, ()> {
28+
/// 以UTF-8编码读取指定的配置文件文本内容, 如果file为None, 则使用默认配置文件
29+
pub async fn read_config(file: Option<String>) -> Option<String> {
30+
match find_config(file.clone()).await {
31+
Some(v) => Some(v),
32+
None => {
33+
e!(
34+
"Not found the config file({})!",
35+
if file.is_none() {
36+
"such as: config.yml, oneport.yml"
37+
} else {
38+
file.as_ref().unwrap()
39+
}
40+
);
41+
None
42+
}
43+
}
44+
}
45+
46+
/// 如果未从命令行指定配置文件, 则尝试加载默认配置文件
47+
async fn find_config(file: Option<String>) -> Option<String> {
2948
match file {
3049
Some(file) => {
3150
i!("Finding config: {file}");
3251
let config = match tokio::fs::read(file).await {
3352
Ok(v) => v,
34-
_ => return Err(()),
53+
_ => return None,
3554
};
3655
let config = String::from_utf8(config).unwrap_or_default();
37-
return Ok(config);
56+
Some(config)
3857
}
3958
None => {
4059
for file in CONFIG_PATHS.as_slice() {
@@ -44,13 +63,14 @@ pub async fn find_config(file: Option<String>) -> Result<String, ()> {
4463
_ => continue,
4564
};
4665
let config = String::from_utf8(config).unwrap_or_default();
47-
return Ok(config);
66+
return Some(config);
4867
}
68+
None
4969
}
5070
}
51-
Err(())
5271
}
5372

73+
/// 根据JSON字符串加载规则, 返回监听地址和API地址
5474
pub async fn load_config(config: &str) -> std::io::Result<(String, String)> {
5575
let config = YamlLoader::load_from_str(config)
5676
.map_err(|_err| {

oneport/src/main.rs

+31-17
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@ mod config;
22

33
use core::*;
44
use config::*;
5-
use once_cell::sync::Lazy;
65
use std::{net::SocketAddr, time::Duration};
76

8-
use tokio::{net::{TcpListener, TcpStream}, io::AsyncWriteExt, task::JoinHandle, sync::Mutex, time::sleep};
9-
10-
static API: Lazy<Mutex<String>> = Lazy::new(|| Mutex::new("".into()));
7+
use tokio::{net::{TcpListener, TcpStream}, io::AsyncWriteExt, task::JoinHandle, time::sleep};
118

129
#[tokio::main]
1310
async fn main() {
@@ -19,23 +16,42 @@ async fn main() {
1916
config_file = args.next();
2017
},
2118
"--reload" | "-reload" | "--r" | "-r" => {
22-
let api = API.lock().await;
23-
let _ = TcpStream::connect(api.as_str()).await;
24-
return;
19+
return reload(config_file).await;
2520
}
2621
_ => {}
2722
}
28-
};
23+
}
2924
loop {
3025
boot(config_file.clone()).await;
3126
sleep(Duration::from_millis(5000)).await;
3227
}
3328
}
3429

30+
/// 热重启, 目前暂时不支持修改热重启接口, 修改将导致无法再次通过命令行进行热重启
31+
async fn reload(config_file: Option<String>) {
32+
let config = match read_config(config_file).await {
33+
Some(v) => v,
34+
None => return,
35+
};
36+
match load_config(&config).await {
37+
Ok((_listen, api)) => {
38+
match TcpStream::connect(api).await {
39+
Ok(_) => {
40+
i!("Restarting...");
41+
}
42+
_ => ()
43+
}
44+
},
45+
Err(e) => {
46+
return e!("Config load failed: {e}");
47+
}
48+
}
49+
}
50+
3551
async fn boot(config_file: Option<String>) {
36-
let config = match find_config(config_file).await {
37-
Ok(v) => v,
38-
_ => return e!("Not found the config file(such as: config.yml, oneport.yml)!"),
52+
let config = match read_config(config_file).await {
53+
Some(v) => v,
54+
None => return,
3955
};
4056
let (listen, api) = match load_config(&config).await {
4157
Ok((listen, api)) => {
@@ -47,12 +63,10 @@ async fn boot(config_file: Option<String>) {
4763
}
4864
};
4965
let task = tokio::spawn(boot_oneport(listen));
50-
let mut mutex_api = API.lock().await;
51-
*mutex_api = api.clone();
5266
boot_api(api, task).await;
5367
}
5468

55-
/// 默认监听 127.0.0.111:1111, 有客户端连接时, 在不断开已有会话的前提下重启服务
69+
/// 启动热重启服务, 默认监听 127.0.0.111:11111, 当有客户端连接时, 在不断开已有会话的前提下重启服务
5670
async fn boot_api(api: String, task: JoinHandle<()>) {
5771
i!("Starting api service on {api}");
5872
let listener = TcpListener::bind(api).await.unwrap();
@@ -66,6 +80,7 @@ async fn boot_api(api: String, task: JoinHandle<()>) {
6680
}
6781
}
6882

83+
/// 启动oneport主服务, 默认监听 0.0.0.0:1111
6984
async fn boot_oneport(listen: String) {
7085
i!("Starting oneport service on {listen}");
7186
let listener = TcpListener::bind(listen).await.unwrap();
@@ -75,6 +90,7 @@ async fn boot_oneport(listen: String) {
7590
Err(e) => unreachable!("{:?}", e),
7691
};
7792
i!("Request {addr} incoming");
93+
// Feature: 已有的会话不会在热重启时断开
7894
tokio::spawn(async move {
7995
serv(visitor, addr).await;
8096
});
@@ -100,9 +116,7 @@ async fn serv(mut visitor: TcpStream, addr: SocketAddr) {
100116
return;
101117
}
102118
}
103-
for i in 0..2 {
104-
d!("Request {addr} msg[{}] = {}", i, msg[i]);
105-
}
119+
i!("Request {addr} msg = {:?}", &msg[..if msg.len() > 10 { 10 } else { msg.len() }]);
106120
let rules = RULES.lock().await;
107121
let mut address = None;
108122
for (rule, target) in rules.as_slice() {

0 commit comments

Comments
 (0)