開啟負載均衡和重啟自身
- 更換axum后臺的意外
- 解決的嘗試
- 在caddy反代,使用負載均衡,加多一個節點
- axum主程序 ip映射信息做全局共享
- axum重啟自身刷新全局共享配置
前期剛實現了rust的后臺關鍵業務.結果出現了兩類大問題停止服務.在正用著的時候,出現很多意外,真是刺激…
更換axum后臺的意外
1, ip2sta的配置沒有在原flask服務重啟后,沒有導入到redis,導致rust后臺無法取到,修改原flask初始redis的代碼才解決, 停服一天,
2,rust服務,工作進程被我誤退出了,結果所有的地點無法訪問簽到. 停服一天.
3,開啟12小時觀察到的,新的rust所在主機,沒有使用東8區, 只是8點前無法使用業務數據.修改時區,未再造成停服.
下面說下負載均衡和動態監測可以解決這個問題,同時,
解決的嘗試
在caddy反代,使用負載均衡,加多一個節點
更新了Caddyfile文件的handle_path改為handle,避免了一次無用的rewrite.
redir /ck/test /rk/test/0handle /rk/* {# handle_path /rk/* # rewrite * /rk{path}reverse_proxy {header_up Host {host}header_up X-Real-IP {remote}health_uri /health_interval 5shealth_timeout 1sto 10.180.133.35:6055 192.168.11.179:3001
}}
目測現在有兩處提供服務,并且在一處斷開后,只使用能用的那個.
axum主程序 ip映射信息做全局共享
上個文章
Android后端簽到flask遷移到rust的axum的過程-簽到性能和便攜 ,ip2sta,加載到axum的啟動配置.這樣不要每次redis取值.
/*** 連接connection_redis*/
fn connection_redis() -> redis::RedisResult<Connection> {let client = redis::Client::open(REDURL)?;let con = client.get_connection()?;Ok(con)
}fn init_app_config() -> HashMap<String, String> {let mut con = connection_redis().ok().unwrap();// 測試是否成功連接Reidslet keys:Vec<String>= con.hkeys("ip2sta" ).ok().unwrap();let mut map=HashMap::new(); for i in keys{let v:String= con.hget("ip2sta", &i).ok().unwrap();map.insert(i,v); }map
}
lazy_static! {static ref IP2STA: HashMap<String,String> = init_app_config(); }
#[tokio::main]
async fn main() {
在main主任務啟動以前加載一次.就可以如下使用
.route("/rk/test/",get(somehandle)).......
async fn somehandle(){
match IP2STA.get(&cip) {Some(sta)=> pobsta( State(pool.clone()),formatted,sta,person).await ,None => Ok(Html(format!("請聯系管理員{:?}未設置~!",&cip))),}
這造成一個問題,ip2sta無法使用最新的數據.
雖然很久不會更新這個底層數據,但是手動重啟不是合適的風格.必須要能讓后臺自動加載新信息…
axum重啟自身刷新全局共享配置
https://zhuanlan.zhihu.com/p/649783802
Axum筆記:配置管理
這里提供了很多刷新的方式,其中state的方式已經被pool占有,lazy_static!是本文用的,剩下的我不理解,
下面是我提供的刷新方式,重啟自身
在某個handle啟動一個新spawn,即調用如下函數.
use tokio::time::{sleep, Duration};
use std::{process,env};async fn restartme(){let delay = Duration::from_millis(50);// 在延時后啟動新進程tokio::spawn(async move {// 等待延時sleep(delay).await;// 獲取程序自身的路徑let me = env::current_exe().expect("Failed to get current exe path");// 重啟程序let status = process::Command::new(me).spawn();match status {Ok(_child) => {// 如果成功,則退出當前實例std::process::exit(0);}Err(e) => {// 如果重啟失敗,打印錯誤并退出println!("Failed to restart: {}", e);std::process::exit(1);}}});
}
這樣并不容易,因為當前process肯定占有了tcp端口. 所有子線程的成功判斷,應該在tcp還未開始時.而且必須在父線程必須釋放端口后再打開,可能tokia的axum 使用了,等待重試,和恰好的判斷時機,讓程序也就是web服務自己完成了配置加載和重啟自身.