微服务是将一个单体服务拆分成一个个服务,而这一个个小服务可以独立部署,并且可以用多种语言构建一个个小服务,且各个服务之间可以统一。微服务之间可以独立地缩放,已达到最高的性能。
微服务之间的通信一般有两种方式:
RPCHTTP
Resutful
RPC 是远程过程调用服务,它提供了一套机制,使得多个语言也能调用其代码,符合Server/Client的风格方式。
Resutful则是使用HTTP的方式构建,来达到通信的目的。
其两者的本质是不同的,一个HTTP ,一个是TCP构建的。
大部分情况下我们使用gRPC的方式进行通信,他是基于HTTP 2.0的传输协议承载了高性能的一种框架,使用起来轻便高效。它使用Proto Buffer为基础作为序列化的格式,这是一种约定俗成。
现在我们创建一个简单的Hello World服务,首先创建Hello.proto
sytanx = "proto3"
package hello;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
接着直接创建一个服务,让他读取proto里面的内容。nodejs这边的包主要使用@grpc/grpc-js和@grpc/proto-loader这两个。
安装一下依赖:
npm install @grpc/grpc-js @grpc/proto-loader -D
接着编写load.js文件:
const path = require('path')
const grpc = require('@grpc/grpc-js')
const protoLoader = require('@grpc/proto-loader')
const PROTO_PATH = path.join(__dirname, 'hello.proto')
const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
})
const protoDescriptor = grpc.loadPackageDefinition(packageDefinition)
// user package
const { hello} = protoDescriptor
module.exports = {
hello,
}
载入到proto 文件之后,我们需要实现这个服务的接口,创建名为server.js的文件:
const grpc = require('@grpc/grpc-js')
function sayHello(call, callback) {
callback(null, {message: 'Hello ' + call.request.name});
}
function main() {
var server = new grpc.Server();
server.addService(hello.Greeter.service,
{sayHello: sayHello});
server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => {
server.start();
});
}
把它运行起来,一个简单的微服务就起来了。
node index.js
既然微服务创建起来了,那么怎么样让人知道,他是什么微服务,应该是由哪个端口调用等等…
配置中心
大多情况下我们的服务是未知的,例如服务内连接了数据库,消息队列,以及连接不同的服务。那么怎么让“主”服务知道服务中的位置呢?一般是用分布式的配置中心,将一个个服务配置存储起来,等下次调用的时候直接读取。
那么主服务器发现多个子服务就简单多了。让子服务器主动注册服务到配置中心里,等下次主服务器调用时就知道注册了那些子服务了。
配置中心最常见的是:etcd、consul、nacos。
我们框架的选型是使用consul,主要是因为它包含K/V配对,多数据中心方案,服务的注册与发布,不需要依赖其他的工具。
直接使用docker部署一下consul:
docker run \\
-d \\
-p 8500:8500 \\
-p 8600:8600/udp \\
--name=badger \\
consul agent -server -ui -node=server-1 -bootstrap-expect=1 -client=0.0.0.0
接着我们连接配置中心,这样写:
const consul = new Consul({
host:"0.0.0.0",
port:8500,
promisity:true
})
consul.agent.service.register({
name:"hello",
address:"0.0.0.0",
port:50051
})
这样就主动注册到注册中心了。
怎么获取注册中心呢?
直接用API的方式拉取注册中心的一些服务,API 为:
consul.agent.service.list(function (err, data, res) {
console.log(data);
});
他返回的值是:
{
'express-app': {
ID: 'express-app',
Service: 'express-app',
Tags: [],
Meta: {},
Port: 3001,
Address: 'localhost',
SocketPath: '',
Weights: { Passing: 1, Warning: 1 },
EnableTagOverride: false,
Datacenter: 'dc1'
}
}
© 著作权归作者所有
发表评论