spring boot迁移计划 第Ⅰ章 --chapter 1. rust hyper 结合rust nacos-client开发nacos网关 part ④ nacos-client

1. toml依赖

nacos_rust_client = "0.3"
local_ipaddress = "0.1"
ahash = "0.8"
arc-swap = "1"

2. 代码

2025-01-17更新: 新增全局服务地址缓存

use std::sync::{Arc, LazyLock};

use ahash::AHashMap;
use arc_swap::ArcSwap;
use log::{error, info};
use nacos_rust_client::client::{
    naming_client::{
        Instance, InstanceDefaultListener, QueryInstanceListParams, ServiceInstanceKey,
    }, ClientBuilder
};

use crate::init::config::Config;

//由于nacos不广播权重配置的更改,而且nacos内置了raft和负载均衡算法所以改为每次去注册中心请求一个服务地址
//LazyLock延迟加载,ArcSwap+AhashMap提高性能
pub static NAMING_MAP: LazyLock<ArcSwap<AHashMap<String, Arc<Vec<Arc<Instance>>>>>> =
    LazyLock::new(|| ArcSwap::from_pointee(AHashMap::new()));

pub async fn init_nacos() {
    let server_name = Config::global().server_name();
    let server_port = Config::global().server_port();
    let nacos_ip = Config::global().nacos_ip();
    let nacos_port = Config::global().nacos_port();
    let nacos_group_name = Config::global().nacos_group();
    //这里小小的吐槽一下rnacos的大神,希望能把这个u32的端口号类型更新成跟其他工具一样,我看作者说用的actix-web,我试过actix,它的端口号也是u16的哈
    connect(
        &server_name,
        server_port,
        &nacos_ip,
        nacos_port,
        &nacos_group_name,
    );
    //add_naming_listener(&server_name).await;
}

//注册
pub fn connect(
    service_name: &str,
    service_port: u16,
    nacos_ip: &str,
    nacos_port: u16,
    nacos_group_name: &str,
) {
    let nacos_addr = &format!("{}:{}", nacos_ip, nacos_port as u32);
    ClientBuilder::new()
        .set_endpoint_addrs(nacos_addr)
        .set_use_grpc(true) //使用grpc,不用可以设置为false
        .build_naming_client();
    let ip = local_ipaddress::get().unwrap();
    let instance = Instance::new_simple(&ip, service_port as u32, service_name, nacos_group_name);
    let naming_client = nacos_rust_client::get_last_naming_client().unwrap();
    //向nacos注册
    naming_client.register(instance);
}

//监听服务上下线的变化
pub async fn add_naming_listener(service_name: &str) {
    let naming_client = nacos_rust_client::get_last_naming_client().unwrap();
    let servcie_key = ServiceInstanceKey::new(service_name, &Config::global().nacos_group());
    let default_listener =
        InstanceDefaultListener::new(*Box::new(servcie_key), Some(Arc::new(handle_listen_list)));
    naming_client
        .subscribe(Box::new(default_listener))
        .await
        .unwrap();
}

//将服务列表同步至缓存
fn handle_listen_list(
    instance_list: Arc<Vec<Arc<Instance>>>,
    add_list: Vec<Arc<Instance>>,
    remove_list: Vec<Arc<Instance>>,
) {
    let service_name = if instance_list.len() > 0 {
        &instance_list[0].service_name
    } else if add_list.len() > 0 {
        &add_list[0].service_name
    } else {
        &remove_list[0].service_name
    };
    let service_name: String = service_name.split("@@").collect::<Vec<&str>>()[1].to_owned();
    info!(
        "{} instances changed, add count:{}, remove count:{}",
        service_name,
        add_list.len(),
        remove_list.len()
    );
    update_naming_map(&service_name, instance_list);
}

pub fn update_naming_map(service_name: &str, instance_list: Arc<Vec<Arc<Instance>>>) {
    info!("update gloable server cache : {:?}", service_name);
    let mut map = NAMING_MAP.load().as_ref().clone();
    map.insert(service_name.to_owned(), instance_list);
    NAMING_MAP.store(map.into());
}

//向注册中心请求一个已注册服务
pub async fn select_service(service_name: &str) -> String {
    let query = QueryInstanceListParams::new_simple(service_name, &Config::global().nacos_group());
    let naming_client = nacos_rust_client::get_last_naming_client().unwrap();
    match naming_client.select_instance(query).await {
        Ok(instances) => {
            let target_address = format!("{}:{}", &instances.ip, &instances.port);
            //add_naming_listener(service_name).await;
            target_address
        }
        Err(e) => {
            error!("select_instance error {}", &e.to_string());
            "".to_owned()
        }
    }
}

posted @ 2024-12-31 22:28  JiajieZeee  阅读(43)  评论(0)    收藏  举报