You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

日志中间件微服务改造:Express日志中间件独立化方案咨询

独立日志微服务改造方案(基于Node.js+Express+Nginx)

一、核心改造思路

把原嵌入各微服务的日志中间件抽离为独立微服务,通过Nginx实现统一流量拦截:所有客户端请求先转发到日志微服务,日志服务完成请求内容记录后,再将请求转发至目标业务微服务;收到业务服务的响应后,记录响应内容,最后把响应返回给客户端。全程无需修改任何业务微服务代码。

二、独立日志微服务实现

基于Express搭建日志服务,核心实现请求转发与双向日志记录,代码如下:

const express = require('express');
const http = require('http');
const { URL } = require('url');
const connection = require('./database/db'); // 复用原数据库连接逻辑

const app = express();
// 接收原始请求体,避免解析丢失内容
app.use(express.raw({ type: '*/*' }));

// 日志存储核心函数
async function saveLog(req, resBody, statusCode) {
  const now = new Date();
  const reqBody = req.body ? req.body.toString('utf8') : '{}';
  try {
    await connection.query("CALL HospitalGatifu.insertLog(?,?,?,?,?)", [
      `[${req.method}] - ${req.originalUrl}`,
      reqBody,
      resBody,
      statusCode === 400 ? 1 : 0,
      now,
    ]);
  } catch (err) {
    console.error('日志存储失败:', err);
    // 日志存储失败不阻塞业务流程
  }
}

// 处理所有请求的转发与日志记录
app.all('*', async (req, res) => {
  // 从Nginx传递的请求头获取目标业务服务地址
  const targetServer = req.headers['x-target-server'];
  if (!targetServer) {
    res.status(500).send('Missing target server');
    return;
  }

  try {
    const targetUrl = new URL(req.originalUrl, targetServer);
    // 构造转发请求配置
    const proxyOptions = {
      hostname: targetUrl.hostname,
      port: targetUrl.port,
      path: targetUrl.pathname + targetUrl.search,
      method: req.method,
      headers: {
        ...req.headers,
        'host': targetUrl.host,
        'x-target-server': undefined // 移除自定义头,不传递给业务服务
      }
    };

    // 转发请求到业务服务
    const proxyReq = http.request(proxyOptions, (proxyRes) => {
      let resChunks = [];
      proxyRes.on('data', (chunk) => resChunks.push(chunk));
      proxyRes.on('end', async () => {
        const resBody = Buffer.concat(resChunks).toString('utf8');
        // 异步存储日志
        await saveLog(req, resBody, proxyRes.statusCode);
        // 将业务服务响应返回给客户端
        res.writeHead(proxyRes.statusCode, proxyRes.headers);
        res.end(resBody);
      });
    });

    // 传递原始请求体到业务服务
    if (req.body) proxyReq.write(req.body);
    proxyReq.end();

    proxyReq.on('error', (err) => {
      console.error('请求转发失败:', err);
      res.status(502).send('Bad Gateway');
    });
  } catch (err) {
    console.error('请求处理失败:', err);
    res.status(500).send('Internal Server Error');
  }
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`日志微服务运行在端口 ${PORT}`);
});

三、Nginx反向代理配置

修改Nginx配置,将各业务微服务的请求先转发到日志微服务,并通过自定义请求头传递目标服务地址。示例配置如下:

http {
  # 定义业务微服务上游节点
  upstream service_user {
    server user-service:3001; # 用户微服务地址
  }
  upstream service_order {
    server order-service:3002; # 订单微服务地址
  }

  server {
    listen 80;
    server_name your-domain.com;

    # 用户服务请求转发规则
    location /user/ {
      proxy_pass http://log-service:3000; # 日志微服务地址
      proxy_set_header X-Target-Server http://service_user; # 传递目标服务地址
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      # 确保请求体与请求头完整传递
      proxy_pass_request_body on;
      proxy_pass_request_headers on;
    }

    # 订单服务请求转发规则
    location /order/ {
      proxy_pass http://log-service:3000;
      proxy_set_header X-Target-Server http://service_order;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_pass_request_body on;
      proxy_pass_request_headers on;
    }

    # 其他业务服务可参照上述规则配置
  }
}

四、关键注意事项

  • 请求体处理:使用express.raw()接收原始请求体,避免Express自动解析JSON/表单导致日志记录的请求内容与实际发送给业务服务的不一致。
  • 异步日志存储:日志存储操作异步执行,不阻塞响应返回,避免影响业务接口的响应速度。
  • 错误隔离:日志服务的异常(如数据库连接失败)不会中断业务请求转发,保证业务可用性。
  • 目标服务寻址:除了请求头传递目标地址,也可通过请求路径前缀、Host等方式匹配目标服务,可根据实际架构调整。
  • 性能优化:高流量场景下,可引入消息队列(如Redis、RabbitMQ)将日志存储操作完全异步化,进一步降低日志服务的性能损耗。

内容的提问来源于stack exchange,提问作者Erick Villatoro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 00:05:32