一文看懂:如何用go语言做微服务架构

阅读 20

2024-11-13

整体介绍

本文目的是在最短的时间内,介绍如何基于go语言来构建微服务架构

可以帮你更快更好地理解什么是微服务,以及微服务核心流程以及具体怎么实现微服务架构


一文看懂:如何用go语言做微服务架构_客户端

微服务的重要性及其优势

微服务架构通过将应用程序分解为一系列小的、自治的服务来提高系统的灵活性和可维护性。它主要解决了传统单体应用中遇到的扩展性和维护难题,尤其是在团队规模扩大时。每个服务可以独立部署、升级和伸缩,这不仅增强了后端服务的可用性和稳定性,还提高了开发者之间的协作效率。例如,在开发一个电商网站时,可以通过微服务架构将购物车、订单处理、支付等模块拆分为独立的服务。这样做可以让负责不同功能模块的团队专注于自己的领域而不互相干扰,从而加快了开发速度并简化了后期维护工作。


微服务在交易网站中的实际切分

在对一个典型的交易网站进行服务化切分时,可以采用领域模型的方式,根据业务功能和数据关联性将系统划分为多个独立的服务。以淘宝为例,首先识别出几个关键的业务领域:用户管理、商品展示与管理、在线交易处理以及评价系统。针对每个领域构建微服务,如用户服务负责账户注册、登录和个人信息维护;商品服务则专注于商品信息的增删改查及搜索推荐逻辑;交易服务涵盖购物车管理、订单生成与支付流程;评价服务支持买家对商品或卖家的反馈提交与展示。这样的划分不仅有利于团队分工合作,各自专注于特定领域的优化与扩展,同时也提高了系统的可维护性和伸缩性,便于后续的技术升级和功能迭代。


Nacos Go SDK简介

Nacos 是一个用于动态服务发现、配置管理和服务管理的平台,旨在帮助开发者更容易地构建、维护和运行分布式系统。它提供了易于使用的UI界面以及一系列开放API来简化微服务架构下的服务治理。该产品支持多种注册中心数据源,并且具备高可用性和扩展性。最近,Nacos 团队发布了 Nacos go sdk ,这是一款开源免费的产品,专为Go语言编写的应用程序设计,非常适合用来与Go语言开发的微服务进行集成,成为其最佳搭档。


服务注册与发现流程详解

服务注册的主要流程

服务注册指的是将服务实例的信息发布到服务注册中心的过程。在 Nacos 中,这个过程包括以下主要步骤:

  1. 创建服务实例:首先,在提供服务的应用程序中,根据业务需求启动一个或多个服务实例。每个实例需要具有唯一的网络地址(IP:Port)以供其他服务调用。
  2. 配置Nacos客户端:使用 gRPC 和 Nacos Go SDK 配置您的应用程序来与 Nacos 服务器通信。这一步骤涉及设置必要的参数如 Nacos 服务器地址、命名空间等,并初始化客户端连接。
  3. 实例信息构建:构造要注册的服务实例相关信息。除了基本的 IP 地址和端口号外,还可以包含额外的元数据,比如权重、健康检查策略等。
  4. 注册至Nacos:通过调用 Nacos 客户端提供的 API 方法将上一步构建好的实例信息发送给 Nacos 服务器进行注册。一旦成功注册,该服务实例就会被记录在 Nacos 的服务注册表内。
  5. 健康状态上报:为了保持服务列表的时效性,服务提供者还需定期向 Nacos 上报自身健康状况。如果检测到某个实例不再响应,则可以从服务列表中移除,避免影响整体服务质量。

服务发现的主要流程

服务发现是指客户端如何找到并访问已经注册的服务实例的过程。基于 gRPC 和 Nacos Go SDK 实现的服务发现可以遵循如下流程:

  1. 查询条件准备:首先确定你想要发现哪种类型的服务。通常会基于服务名来进行搜索;此外,也可以指定特定版本或其他标签作为过滤条件。
  2. 执行服务查找请求:利用 Nacos 客户端提供的接口发起对目标服务的查询请求。这里需要注意正确设置查询范围(如全局还是局域网内)以及是否考虑跨区域等因素。
  3. 接收返回结果:Nacos 根据接收到的请求条件从其维护的服务注册表中匹配符合条件的服务实例列表,并将这些信息反馈给请求方。
  4. 选择合适实例:对于返回的服务实例集合,可以根据实际需要采取不同的选择策略。例如,基于负载均衡算法选取最佳节点,或者随机挑选一个可用实例。
  5. 建立gRPC连接:最后,使用选定的服务实例信息(通常是 IP 地址加端口号),通过 gRPC 创建连接通道并与之交互完成业务逻辑处理。

上述两个流程描述了在采用 gRPC 传输协议以及 Nacos 作为服务注册与发现工具时的基本操作方式。通过这种方式能够有效地支持分布式系统的动态扩展性和高可用性要求。


基于gRPC与Nacos的服务发现和注册的实际构建过程

实际的构建过程,基于grpc 和 nacos 的服务发现和服务注册

根据提供的知识内容,我们可以了解到要实现基于gRPC和Nacos的服务发布与消费,首先需要安装必要的Go插件,并且设置好开发环境。然后通过定义gRPC的服务接口(使用proto文件),生成相应的Go代码。接着分别实现gRPC服务端及客户端程序,在这两个程序中集成Nacos以完成服务的注册与发现。

环境准备
  • 安装Protocol Compiler Go插件:

$ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

  • 更新PATH变量确保protoc能找到这些新安装的插件。
  • 安装Nacos Go SDK:

$ go get -u github.com/nacos-group/nacos-sdk-go/v2

gRPC Proto 文件定义 & 代码生成

创建一个简单的gRPC服务定义文件helloworld.proto:

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest { string name = 1; }
message HelloReply { string message = 1; }

在保存了上述proto文件之后,运行以下命令来生成对应的Go语言源码:

$ protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
helloworld/helloworld.proto

Go Grpc Server 实现

接下来是gRPC服务器端的实现部分,这里也包括了向Nacos注册该服务的逻辑。

package main

import (
    "context"
    "flag"
    "fmt"
    "log"
    "net"

    pb "path/to/generated/pb" // 根据实际情况修改导入路径
    "google.golang.org/grpc"
    clients "github.com/nacos-group/nacos-sdk-go/v2/clients"
    constant "github.com/nacos-group/nacos-sdk-go/v2/common/constant"
    vo "github.com/nacos-group/nacos-sdk-go/v2/vo"
)

var port = flag.Uint64("port", 50051, "The server port")

type server struct{ pb.UnimplementedGreeterServer }

func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}

func main() {
    flag.Parse()
    lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterGreeterServer(s, &server{})

    // Nacos配置和服务注册
    clientConfig := constant.ClientConfig{
        NamespaceId:         "public",
        TimeoutMs:           5000,
        NotLoadCacheAtStart: true,
        LogDir:              "/tmp/nacos/log",
        CacheDir:            "/tmp/nacos/cache",
        LogLevel:            "info",
    }
    serverConfigs := []constant.ServerConfig{{IpAddr: "mse-51d24ce0-p.nacos-ans.mse.aliyuncs.com", Port: 8848}}
    
    namingClient, _ := clients.CreateNamingClient(map[string]interface{}{
        "serverConfigs": serverConfigs,
        "clientConfig":  clientConfig,
    })

    _, err = namingClient.RegisterInstance(vo.RegisterInstanceParam{
        Ip:          "127.0.0.1",
        Port:        *port,
        ServiceName: "example.grpc.server",
        Weight:      10,
        Enable:      true,
        Healthy:     true,
        Ephemeral:   true,
    })
    if err != nil {
        log.Fatalf("Error registering service: %v", err)
    }

    log.Printf("server listening at %v", lis.Addr())
    s.Serve(lis)
}

Go Grpc Client 实现

客户端将从Nacos获取服务实例信息,并据此建立到gRPC服务器的连接。

// [此处省略了导入声明等非关键部分]
const defaultName = "world"
var name = flag.String("name", defaultName, "Name to greet")

func main() {
    flag.Parse()

    // Nacos配置...
    [同上文服务器示例]

    instance, err := namingClient.SelectOneHealthyInstance(vo.SelectOneHealthInstanceParam{
        ServiceName: "example.grpc.server",
    })
    if err != nil {
        log.Fatalf("failed to select instances: %v", err)
    }
    addr := fmt.Sprintf("%s:%d", instance.Ip, instance.Port)

    conn, err := grpc.Dial(addr, grpc.WithInsecure())
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()
    c := pb.NewGreeterClient(conn)

    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()
    r, err := c.SayHello(ctx, &pb.HelloRequest{Name: *name})
    if err != nil {
        log.Fatalf("could not greet: %v", err)
    }
    log.Printf("Greeting: %s", r.GetMessage())
}

以上就是如何结合gRPC与Nacos Go SDK来搭建一套完整的服务注册发现机制的全过程。我们首先设置了基本环境并定义了一个简单的gRPC服务;随后实现了gRPC服务器,并在其中添加了向Nacos注册自身作为可用服务的功能;最后编写了一个gRPC客户端应用,它能够从Nacos查询到正确的服务实例地址并发起调用。



精彩评论(0)

0 0 举报