随着云原生时代的到来,微服务架构已经成为构建大规模应用程序的首选方法。通过将应用程序拆分为一系列小的、相互独立的服务,开发团队可以更快地开发和部署功能,并实现更高的可伸缩性和弹性。
在这种分布式系统中,微服务的治理变得越来越重要。通过微服务治理,我们可以管理服务之间的依赖关系、版本控制、路由和负载均衡、访问控制等方面的问题。在本文中,我们将介绍如何使用 Fastify 框架实现 Node.js 微服务治理,并提供示例代码和深度指导。
Fastify 框架简介
Fastify 是一个高性能的 Node.js Web 框架,它具有非常低的开销和快速的响应能力。Fastify 能够处理每秒数百万次请求,是 Node.js 中最快的框架之一。
Fastify 的设计目标是提供一个清晰、轻量级和易于开发的框架,同时保持高效和严格的开发标准。它采用异步请求处理和共享数据的方式,能够轻松扩展和维护。
Fastify 采用了一些高效的技术来提高性能,例如使用快速的 JSON 解析器 fast-json-stringify、使用高性能的路由库find-my-way、支持 HTTP2 和 JSON Schema 校验等。除此之外,它还提供了大量的插件来扩展功能。
实现微服务治理
在分布式系统中,微服务需要相互通信以实现相互调用。在微服务系统中,服务与服务之间的通信通常采用基于 HTTP 的 RESTful API。
Fastify 框架可以轻松地创建和扩展 RESTful API,并适用于微服务环境。下面我们将介绍如何使用 Fastify 框架构建微服务,并提供一个例子。
1. 安装 Fastify
首先,我们需要安装 Fastify 和一些相关的插件。
npm install fastify fastify-cors fastify-oas fastify-swagger fast-json-stringify
fastify-cors是 Fastify 的 CORS 插件,用于跨域请求支持。fastify-oas是 Fastify 的 OpenAPI 规范插件。fastify-swagger是 Fastify 的 Swagger UI 插件。fast-json-stringify是 Fastify 的 JSON 序列化插件。
2. 编写服务
接下来,我们需要编写一个服务,该服务将作为微服务进行部署。在本例中,我们将实现一个简单的服务,该服务提供了一些常用的算法。
// www.javascriptcn.com code example
const fastify = require('fastify')();
const jwt = require('jsonwebtoken');
const fib = require('fibonacci');
fastify.get('/', async () => {
return { message: 'Hello world!' };
});
fastify.get('/fibonacci/:n', async (request) => {
const n = request.params.n || 0;
const result = fib.iterate(n);
return { result: result };
});
fastify.listen(3000, (err, address) => {
if (err) throw err;
console.log(`Server listening on ${address}`);
});在上面的示例中,我们实现了两个 HTTP GET 方法,一个是 / 路径,它返回 "Hello world!" 字符串,另一个是 /fibonacci/:n 路径,它返回斐波那契数列的结果。
3. 部署服务
现在,我们可以将这个服务作为微服务进行部署了。我们可以将它部署到云端,也可以在本地部署它。这里我们将它部署到本地。
node service.js
4. 创建网关
下一步,我们需要创建一个网关,它将作为微服务系统的入口。Fastify 框架同样适用于创建网关服务,下面是一个网关的示例。
// www.javascriptcn.com code example
const fastify = require('fastify')();
const fastifyCors = require('fastify-cors');
const fastifyOAS = require('fastify-oas');
const fastifySwagger = require('fastify-swagger');
const jwt = require('jsonwebtoken');
const fetch = require('node-fetch');
const FgYellow = '\x1b[33m';
const FgRed = '\x1b[31m';
const Reset = '\x1b[0m';
// 各个微服务的路由地址
const SERVICES = [
{ name: 'service1', url: 'http://localhost:3000' },
{ name: 'service2', url: 'http://localhost:4000' },
{ name: 'service3', url: 'http://localhost:5000' },
];
// JWT 鉴权密钥
const secretKey = 'my_secret_key';
// CORS 跨域支持
fastify.use(fastifyCors('http://localhost:3000'));
// API 文档规范
fastify.register(fastifyOAS, {
routePrefix: '/docs',
swagger: {
info: {
title: 'Microservice Example',
description: 'Microservice Example with Fastify, JWT and Fetch',
version: '0.1.0',
},
servers: [
{ url: 'http://localhost:8000', description: 'Server' },
{ url: 'http://localhost:3000', description: 'Service1' },
{ url: 'http://localhost:4000', description: 'Service2' },
{ url: 'http://localhost:5000', description: 'Service3' },
],
schemes: ['http'],
consumes: ['application/json'],
produces: ['application/json'],
security: [{ bearerAuth: [] }],
},
exposeRoute: true,
});
// Swagger UI 页面
fastify.register(fastifySwagger, {
routePrefix: '/docs',
swagger: {
info: {
title: 'Microservice Example',
description: 'Microservice Example with Fastify, JWT and Fetch',
version: '0.1.0',
},
servers: [
{ url: 'http://localhost:8000', description: 'Server' },
{ url: 'http://localhost:3000', description: 'Service1' },
{ url: 'http://localhost:4000', description: 'Service2' },
{ url: 'http://localhost:5000', description: 'Service3' },
],
schemes: ['http'],
consumes: ['application/json'],
produces: ['application/json'],
security: [{ bearerAuth: [] }],
},
exposeRoute: true,
});
// 鉴权插件
fastify.register((fastify, opts, done) => {
fastify.decorate('jwtVerify', async (request, reply) => {
try {
const authHeader = request.headers.authorization;
if (authHeader) {
const token = authHeader.split(' ')[1];
const decoded = jwt.verify(token, secretKey);
request.user = { id: decoded.sub };
}
} catch (err) {
console.log(FgRed + `Error verifying token: ${err}` + Reset);
reply.send({ error: 'Invalid token' }).code(401);
}
});
done();
});
// 所有微服务的路由
fastify.get('/hello', { preValidation: [fastify.jwtVerify] }, async (request) => {
console.log(FgYellow + `Path: ${request.query.path}` + Reset);
const token = jwt.sign({ sub: request.user.id }, secretKey);
const responses = await Promise.allSettled(
SERVICES.map(async (service) => {
const url = `${service.url}/${request.query.path}`;
try {
const response = await fetch(url, {
headers: {
Authorization: `Bearer ${token}`,
},
});
if (response.ok) {
return {
message: `Response from ${service.name}: ${JSON.stringify(await response.json())}`,
};
} else {
throw new Error(`Response error from ${service.name}: ${await response.text()}`);
}
} catch (err) {
return {
error: `Request error from ${service.name}: ${err}`,
};
}
})
);
return { responses };
});
// 服务启动
fastify.listen(8000, (err, address) => {
if (err) throw err;
console.log(`Server listening on ${address}`);
});在以上的示例中,fastify-cors 用于支持跨域请求。fastify-oas 和 fastify-swagger 用于创建 API 文档和 Swagger UI 页面。我们也使用了一个 JWT 鉴权插件,用于处理鉴权逻辑。
最重要的部分是 /hello 路径,它作为网关的主入口。为了调用其他微服务,我们使用 node-fetch 实现了向其他微服务的请求。在这里,我们使用了前面创建的 3 个微服务的地址。
5. 测试微服务治理
现在,我们已经成功创建了微服务,并实现了通过网关进行通信。我们可以使用 Swagger UI 页面测试它们。
打开 http://localhost:8000/docs 页面,可以看到一个包含所有微服务 API 的页面。在这里,我们测试 /hello 的路径,它会返回 httpbin.org 网站的信息。

点击 "Try it out" 按钮,输入 /ip 的路径。点击 "Execute",可以看到返回的结果。

在控制台中,可以看到请求经过的微服务日志。

到这里,我们已经成功地实现了 Fastify 框架下的微服务治理。通过网关,我们可以访问不同的微服务,并将它们的响应结果汇聚到一个 JSON 对象中。我们也使用了 JWT 鉴权机制,确保只有认证用户可以访问微服务。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d78e22a941bf7134d86278