在 Ubuntu 上,Node.js 集成第三方服务通常分为两类:一是作为客户端调用外部 HTTP/HTTPS API,二是作为服务端被反向代理或对接消息/监控等外部系统。下面给出可直接落地的做法与关键注意事项。
调用外部 HTTP API 的常用方式
npm install axiosconst axios = require('axios');
// GET
axios.get('https://api.example.com/data', {
headers: { 'Authorization': 'Bearer <TOKEN>' },
timeout: 5000
}).then(r => console.log(r.data)).catch(e => {
if (e.response) console.error('HTTP', e.response.status, e.response.data);
else if (e.request) console.error('No response');
else console.error('Error', e.message);
});
// POST
axios.post('https://api.example.com/data', { key: 'value' }, {
headers: { 'Content-Type': 'application/json' }
}).then(r => console.log(r.data));
const https = require('https');
https.get('https://api.example.com/data', { headers: { 'Authorization': 'Bearer <TOKEN>' } }, res => {
let d = '';
res.on('data', c => d += c);
res.on('end', () => console.log(JSON.parse(d)));
}).on('error', e => console.error(e));
// Node >= 17
fetch('https://api.example.com/data', {
headers: { 'Authorization': 'Bearer <TOKEN>' }
}).then(r => r.json()).then(console.log).catch(console.error);
process.env.API_KEY),不要硬编码;将 Node.js 接入 Apache2 或 Nginx 反向代理
sudo a2enmod proxy proxy_http proxy_html headers<VirtualHost *:80>
ServerName my-node-app.com
ProxyPreserveHost On
ProxyRequests Off
ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/
ErrorLog ${APACHE_LOG_DIR}/my-node-app_error.log
CustomLog ${APACHE_LOG_DIR}/my-node-app_access.log combined
</VirtualHost>
sudo a2ensite my-node-app.conf && sudo systemctl restart apache2server {
listen 80;
server_name _;
root /opt/yourapp/dist;
index index.html;
location / {
try_files $uri $uri/ @proxy;
}
location @proxy {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
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_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400;
}
location ~ /\. { deny all; }
}
进程守护与运行监控
npm install -g pm2pm2 start server.js --name myapppm2 logs myapp、pm2 restart myapp、pm2 list、pm2 startup(生成 systemd 启动脚本)npm install prom-clientconst client = require('prom-client');
const http = require('http');
const httpReqDur = new client.Histogram({
name: 'http_request_duration_ms',
help: 'Duration of HTTP requests in ms',
labelNames: ['method', 'route', 'code'],
buckets: [0.1, 5, 15, 50, 100, 200, 300, 400, 500]
});
const server = http.createServer((req, res) => {
const end = httpReqDur.startTimer();
res.on('finish', () => {
end({ method: req.method, route: req.url, code: res.statusCode });
});
// ...你的业务处理
});
server.listen(3000, () => console.log('Metrics on :3000/metrics'));
http://<your-host>:3000/metrics,Grafana 配置 Prometheus 数据源并导入面板。错误追踪与日志集成
npm install @sentry/nodeconst Sentry = require('@sentry/node');
Sentry.init({ dsn: process.env.SENTRY_DSN, environment: 'production' });
// 示例:触发一个测试异常
app.get('/', () => { throw new Error('Test Sentry error'); });
const { createLogger, format, transports } = require('winston');
const logger = createLogger({
level: 'info',
format: format.combine(format.timestamp(), format.json()),
transports: [
new transports.File({ filename: 'error.log', level: 'error' }),
new transports.File({ filename: 'combined.log' })
]
});
if (process.env.NODE_ENV !== 'production') {
logger.add(new transports.Console({ format: format.simple() }));
}
logger.info('Hello, world!');
logger.error('Something went wrong!');