开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第14天,点击查看活动详情
在上篇文章中,现在我们来实现服务器端的事件通知机制和优雅关机。现在我们来实现并发连接限制和测量监控。
并发连接限制
服务器端使用tokio
的Semaphore
限制并发连接的最大数量。一旦达到限制数,服务器将停止接受新的连接,直到现有连接终止。
我们先在conf/server.json
中加入连接数配置:
{
"listen_address": {
"address": "127.0.0.1:3000"
},
"sled_path": {
"path": "tmp/kvserver"
},
"connects":{
"max_conns":500
},
}
修改src/config.rs
,新增连接数配置:
//server端配置
#[derive(Debug, Serialize, Deserialize)]
pub struct ServerConfig {
pub listen_address: ListenerAddress,
pub sled_path: SledDbPath,
pub connects: Connects,
}
// 最大连接数
#[derive(Debug, Serialize, Deserialize)]
pub struct Connects {
pub max_conns: usize,
}
同时修改src/server.rs
代码:
pub struct Server {
......
max_conns: Arc<Semaphore>, // 最大连接数
}
impl Server {
pub fn new(listen_addr: String, service: Service, max_conns: usize) -> Self {
Self {
......
max_conns: Arc::new(Semaphore::new(max_conns)),
}
}
// 与客户端建立连接
async fn execute(&self, notify_shutdown: &broadcast::Sender<()>, shutdown_complete_tx: &mpsc::Sender<()>) -> Result<(), Box<dyn Error>> {
let listener = TcpListener::bind(&self.listen_addr).await?;
info!("Listening on {} ......", self.listen_addr);
loop {
let permit = self.max_conns.clone().acquire_owned().await.unwrap();
......
tokio::spawn(async move {
// 使用Frame的LengthDelimitedCodec进行编解码操作
let mut stream = Framed::new(stream, LengthDelimitedCodec::new());
drop(permit);
......
});
}
}
}
测量监控
我们使用的性能监控和测量工具是 jaeger
,在服务器端收集监控信息,发送给 jaeger
来查看执行流程及时间。
在Cargo.toml
文件中加入依赖:
tracing-appender = "0.1"
tracing-opentelemetry = "0.15"
opentelemetry-jaeger = "0.15"
修改src/bin/kv_server.rs
代码:
let tracer = opentelemetry_jaeger::new_pipeline().with_service_name("kv_server").install_simple()?;
let tracing_layer = tracing_opentelemetry::layer().with_tracer(tracer);
tracing_subscriber::registry()
.with(EnvFilter::from_default_env())
.with(tracing_layer).init();
let root = span!(tracing::Level::INFO, "app_start", work_units = 2);
let _enter = root.enter();
在src/server.rs
中加入instrument
:
#[instrument(name = "server_run", skip_all)]
pub async fn run(&self, shutdown: impl Future) -> Result<(), Box<dyn Error>> {
......
}
#[instrument(name = "server_execute", skip_all)]
async fn execute(&self, notify_shutdown: &broadcast::Sender<()>, shutdown_complete_tx: &mpsc::Sender<()>) -> Result<(), Box<dyn Error>> {
......
}
然后运行jaeger
:
docker run -d -p6831:6831/udp -p6832:6832/udp -p16686:16686 -p14268:14268 jaegertracing/all-in-one:latest
启动kv_server
,然后运行kv_client
执行多个命令,查看http://localhost:16686/