Я работаю над созданием шлюза API, и до сих пор мне удавалось заставить все работать для единичных случаев, когда я жестко кодирую IP-адрес и порт сервера, к которому должен подключаться мой API-шлюз.
Я видел несколько примеров того, как выполнить обнаружение службы с помощью Consul / Node.js.
Я нашел это и попытался заставить его работать, но я не могу заставить наблюдателя работать правильно и передать мне IP: порт, который мне нужен для подключения к службе.
Все приведенные ниже файлы являются только частями, а не целыми. Важные части там, хотя.
Это мой файл app.js
app.listen(port, () => {
const CONSUL_ID = require('uuid').v4();
const ip = require('ip');
const my_IP = ip.address();
let options = {
name: 'api-gateway',
address: `${my_IP}`,
port: 8080,
id: CONSUL_ID,
check: {
ttl: '10s',
deregister_critical_service_after: '1m'
}
};
consul.agent.service.register(options, function(err) {
if (err) throw err;
console.log(`Registered service with ID of ${CONSUL_ID}`);
});
setInterval(() => {
consul.agent.check.pass({id:`service:${CONSUL_ID}`}, err => {
if (err) throw new Error(err);
});
}, 5 * 1000);
process.on('SIGINT', () => {
console.log(`SIGINT. De-Registering service with ID of ${CONSUL_ID}`);
consul.agent.service.deregister(CONSUL_ID, (err) => {
if(err) console.log(`Error de-registering service from consul, with error of : ${err}`);
if(!err) console.log(`De-registered service with ID of ${CONSUL_ID}`);
process.exit();
});
});
console.log(`API gateway server running express started on port ${port}.`);
});
У меня работают две другие тестовые службы, единственное отличие между моим app.js выше и этими тестовыми заключается в том, что они имеют name: 'test-service',
для имени службы.
Это мой файл маршрутов
var consul = require("consul")({host: '10.0.1.248'});
var known_data_instances = [];
const apiAdapter = require('./apiAdapter')
// Keep a list of healthy services
var watcher = consul.watch({
method: consul.health.service,
options: {
service:'test-service',
passing:true
}
});
watcher.on('change', data => {
console.log('received discovery update:', data.length);
known_data_instances = [];
data.forEach(entry => {
known_data_instances.push(`http://${entry.Service.Address}:${entry.Service.Port}/`);
});
});
watcher.on('error', err => {
console.error('watch error', err);
});
const BASE_URL = known_data_instances[Math.floor(Math.random()*known_data_instances.length)];
// const api = apiAdapter(BASE_URL + ':8081');
const api = apiAdapter(BASE_URL);
// router.get('/login', isAuthorized, (req, res) => {
router.get('/login', (req, res) => {
api.get(req.path).then(resp => {
res.send(resp.data);
});
});
Файл адаптера API
const axios = require('axios');
module.exports = (baseURL) => {
return axios.create({
baseURL: baseURL,
});
};
Я ожидаю, что смогу отправить запрос с помощью axios на конечную точку HTTP другого сервиса на другом сервере при получении IP-адреса и порта от консула.
Фактический результат:
(node:3230) UnhandledPromiseRejectionWarning: Error: connect ECONNREFUSED 127.0.0.1:80
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1191:14)
Мне кажется, что он не берет URL-адреса и возвращается по умолчанию на локальный хост-порт 80.
Я немного растерялся из-за всего этого, так как я никогда не создавал приложение с консулом, и хотя документы consul.io великолепны, в Интернете не так уж много справочной базы для облегчения изучения.
Полагаю, вопрос сводится к тому, как мне заставить мой адаптер api отправлять запросы различным службам, в данном случае test-service
?