首页 > 其他分享 >Go语言微服务框架go-micro(入门)

Go语言微服务框架go-micro(入门)

时间:2023-01-02 00:44:43浏览次数:34  
标签:string err micro user error go Go model

Micro用于构建和管理分布式系统,是一个工具集,其中go-micro框架是对分布式系统的高度抽象,提供分布式系统开发的核心库,可插拔的架构,按需使用

简单示例

编写protobuf文件:

syntax = "proto3";

option go_package = ".;proto";

service Cap {
  rpc SayHello(SayRequest) returns (SayResponse) {}
}

message SayRequest {
  string message = 1;
}

message SayResponse {
  string answer = 1;
}

生成代码:

$ protoc -I ./ --go_out=./proto --micro_out=./proto ./proto/hello.proto 

编写服务端:

type CapServer struct{}

func (c *CapServer) SayHello(ctx context.Context, req *proto.SayRequest, resp *proto.SayResponse) error {
	resp.Answer = "hello: " + req.Message
	return nil

}

func main() {
	service := micro.NewService(micro.Name("test.server")) 	// 创建新服务
	service.Init() 	// 初始化方法
	_ = proto.RegisterCapHandler(service.Server(), new(CapServer)) 	// 注册服务
	if err := service.Run(); err != nil {
		fmt.Println(err)
	}
}

客户端:

func main() {
	service := micro.NewService(micro.Name("test.client"))
	service.Init()
	client := proto.NewCapService("test.server", service.Client())
	res, err := client.SayHello(context.TODO(), &proto.SayRequest{Message: "test"})
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(res.Answer)
}

目录搭建

使用docker的micro容器,创建一个micro目录:

$ sudo docker run --rm -v $(pwd):$(pwd) -w $(pwd) micro/micro new user

编写一个用户信息的服务

首先定义一个protobuf文件:

syntax = "proto3";

package go.micro.service.user;
option go_package = ".;proto";

service User {
  rpc Register(UserRegisterRequest) returns (UserRegisterResponse) {}
  rpc Login(UserLoginRequest) returns (UserLoginResponse) {}
  rpc GetUserInfo(UserInfoRequest) returns (UserInfoResponse) {}
}

message UserInfoRequest {
  string user_name = 1;
}

message UserInfoResponse {
  int64 user_id = 1;
  string user_name = 2;
  string first_name = 3;
}

message UserRegisterRequest {
  string user_name = 1;
  string first_name = 2;
  string password = 3;
}

message UserRegisterResponse {
  string message = 1;
}

message UserLoginRequest {
  string user_name = 1;
  string password = 2;
}

message UserLoginResponse {
  bool success = 1;
}

编译该文件:

$ protoc -I ./ --go_out=./ --micro_out=./ user.proto 

目录结构:

├── domain
│   ├── model
│   │   └── user.go
│   ├── repository
│   │   └── user_repository.go
│   └── service
│       └── user_data_service.go
├── go.mod
├── go.sum
├── handler
│   └── user.go
├── main.go
├── micro.mu
└── proto
    └── user
        ├── user.pb.go
        ├── user.pb.micro.go
        └── user.proto

核心逻辑

domain/model/user.go

定义用户结构:

package model

type User struct {
	ID           int64  `gorm:"primary_key;not_null;auto_increment"`
	UserName     string `gorm:"unique_index;not_null"`
	FirstName    string
	HashPassword string
}

domain/repository/user_repository.go

这部分代码包括创建数据库,初始化数据库表,增删改查用户信息

package repository

import (
	_ "github.com/go-sql-driver/mysql"
	"github.com/jinzhu/gorm"
	"user/domain/model"
)

type IUserRepository interface {
	InitTable() error // 初始化数据库表
	FindUserByName(string) (*model.User, error)
	FindUserByID(int64) (*model.User, error)
	CreateUser(*model.User) (int64, error)
	DeleteUserByID(int64) error
	UpdateUser(*model.User) error
	FindAll() ([]model.User, error)
}

func NewUserRepository(db *gorm.DB) IUserRepository {
	return &UserRepository{db: db}
}

type UserRepository struct {
	db *gorm.DB
}

func (u *UserRepository) FindAll() ([]model.User, error) {
	userAll := make([]model.User, 0)
	return userAll, u.db.Find(&userAll).Error
}

// InitTable 初始化表
func (u *UserRepository) InitTable() error {
	if u.db.HasTable("users") {
		return nil
	}
	return u.db.CreateTable(&model.User{}).Error
}

func (u *UserRepository) FindUserByName(name string) (*model.User, error) {
	user := &model.User{}
	return user, u.db.Where("username = ?", name).Find(user).Error
}

func (u *UserRepository) FindUserByID(userID int64) (*model.User, error) {
	user := &model.User{}
	return user, u.db.First(user, userID).Error

}

func (u *UserRepository) CreateUser(user *model.User) (int64, error) {
	return user.ID, u.db.Create(user).Error
}

func (u *UserRepository) DeleteUserByID(userID int64) error {
	return u.db.Where("id = ?", userID).Delete(&model.User{}).Error
}

func (u *UserRepository) UpdateUser(user *model.User) error {
	return u.db.Model(user).Update(&user).Error
}

domain/service/user_data_service.go

这部分代码包含业务逻辑,对用户数据进行操作

package service

import (
	"github.com/pkg/errors"
	"golang.org/x/crypto/bcrypt"
	"user/domain/model"
	"user/domain/repository"
)

type IUserDataService interface {
	AddUser(*model.User) (int64, error)
	DeleteUser(int64) error
	UpdateUser(*model.User, bool) error
	FindUserByName(string) (*model.User, error)
	CheckPwd(string, string) (bool, error)
}

func NewUserDataService(userRepository repository.IUserRepository) IUserDataService {
	return &UserDataService{UserRepository: userRepository}
}

func GeneratePassword(userPassword string) ([]byte, error) {
	return bcrypt.GenerateFromPassword([]byte(userPassword), bcrypt.DefaultCost)
}

func ValidatePassword(userPassword string, hashed string) (bool, error) {
	if err := bcrypt.CompareHashAndPassword([]byte(hashed), []byte(userPassword)); err != nil {
		return false, errors.New("wrong password")
	}
	return true, nil
}

type UserDataService struct {
	UserRepository repository.IUserRepository
}

func (u *UserDataService) AddUser(user *model.User) (int64, error) {
	pwdByte, err := GeneratePassword(user.HashPassword)
	if err != nil {
		return user.ID, err
	}
	user.HashPassword = string(pwdByte)
	return u.UserRepository.CreateUser(user)
}

func (u *UserDataService) DeleteUser(userID int64) error {
	return u.UserRepository.DeleteUserByID(userID)
}

func (u *UserDataService) UpdateUser(user *model.User, isChangedPwd bool) error {
	if isChangedPwd {
		pwdByte, err := GeneratePassword(user.HashPassword)
		if err != nil {
			return err
		}
		user.HashPassword = string(pwdByte)
	}
	return u.UserRepository.UpdateUser(user)
}

func (u *UserDataService) FindUserByName(userName string) (*model.User, error) {
	return u.UserRepository.FindUserByName(userName)
}

func (u *UserDataService) CheckPwd(userName string, pwd string) (bool, error) {
	user, err := u.UserRepository.FindUserByName(userName)
	if err != nil {
		return false, err
	}
	return ValidatePassword(pwd, user.HashPassword)
}

程序入口:

package main

import (
	"github.com/jinzhu/gorm"
	"go-micro.dev/v4"
	"log"
	"user/domain/repository"
	srv "user/domain/service"
	"user/handler"
	proto "user/proto/user"
)

func main() {
	service := micro.NewService(
		micro.Name("go.micro.service.user"),
		micro.Version("latest"))
	service.Init()

	db, err := gorm.Open("mysql", "micro:123456@/micro?charset=utf8")
	if err != nil {
		log.Fatalln(err)
	}
	defer db.Close()

	resp := repository.NewUserRepository(db)
	resp.InitTable()
	db.SingularTable(true)

	userDataService := srv.NewUserDataService(repository.NewUserRepository(db))
	err = proto.RegisterUserHandler(service.Server(), &handler.User{UserDataService: userDataService})
	if err != nil {
		log.Fatalln(err)
	}

	if err = service.Run(); err != nil {
		log.Fatalln(err)
	}
}

镜像打包

编写dockerfile打包应用

DockerFile常用命令:

  1. FROM: 定制镜像基于FROM的镜像,后续操作都基于该镜像

  2. RUN: 用于执行后面跟着的命令行命令

  3. COPY,ADD: 复制指令,从文件或者目录到容器里制定路径

  4. CMD,ENTRYPOINT: 用于运行程序

  5. ENV: 设置环境变量,在后续指令中,就可以使用这个环境变量

  6. EXPOSE: 声明端口

  7. WORKDIR: 指定工作目录

  8. USER: 于指定执行后续命令的用户和用户组

将源程序进行交叉编译为linux平台上的可执行程序:

$ CGO_ENABLE=0 GOOS=linux GOARCH=amd64 go build -o user *.go

编写Dockerfile:

FROM alpine
ADD user /user
ENTRYPOINT ["/user"]

使用以下命令配合Dockerfile即可进行打包:

$ sudo docker build -t user:latest .

使用该命令即可运行:

$ sudo docker run --rm -d user

标签:string,err,micro,user,error,go,Go,model
From: https://www.cnblogs.com/N3ptune/p/17019320.html

相关文章

  • 狂神说Go语言—并发编程
    聊聊进程、线程、协程多线程上方左图所示:在主线程中为main方法左图的右边为test方法,在main方法中调用test方法,mian方法执行就会先去执行test方法,执行完后再回到main......
  • Django之csrf校验 CBV加装饰器以及auth认证模块
    目录Django之csrf校验CBV加装饰器以及auth认证模块一、csrf跨站请求伪造二、csrf校验策略(在提交数据的位置添加唯一标识)三、CBV加装饰器四、auth认证模块五、auth认证......
  • Django视频教程 - 基于Python的Web框架(全13集)
    Django是由Python驱动的开源模型-视图-控制器(MVC)风格的Web应用程序框架,使用Django可以在即可分钟内快速开发一个高品质易维护数据库驱动的应用程序。下面是一大坨关于Django......
  • Django中logging的设置
    1.日志基础知识日志与我们的软件程序密不可分。它记录了程序的运行情况,可以给我们调试程序和故障排查提供非常有用的信息。每一条日志信息记录了一个事件的发生。具体而言......
  • osv-scanner google 开源漏洞扫描工具
    osv-scanner是google基于golang编写的开源漏洞扫描工具,支持基于osv数据库的扫描,生态比较好支持的扫描模式lockfilessbomsgit项目说明osv-scanner支持的扫描......
  • Django组件之form组件
    目录Django组件之form组件一、form组件二、forms组件渲染标签三、forms组件展示信息四、forms组件校验补充五、forms组件参数补充六、modelform组件Django组件之form组件......
  • 问题:django中对datetime类型数据在pycharm中sqlite3进行修改时,修改后datetime日期数据
    这是正在修改的  提交完之后  问题原因是sqlite数据库对日期类型不敏感,Pycharm直接插入会变成图中这样的时间戳,用POST请求添加数据或Django自带的后台管理插入不......
  • linux 安装mongoldb
    1、下载mogodb官网:www.mongodb.com//下载地址https://www.mongodb.com/download-center/community//选择版本,复制下载链接地址https://fastdl.mongodb.org/linux/......
  • [MongoDB faq]--频繁问的问题
    感谢原文链接:​​https://docs.mongodb.com/manual/faq/​​​​常见问题:MongoDB基础知识​​​​MongoDB支持哪些平台?​​​​MongoDB是作为托管服务提供的吗?​​​​集合......
  • 【无标题】常见框架:Django框架<全能型框架MTV>
    第一课django环境搭建前言Web框架:url,请求对象,响应对象,模板引擎常见框架:Django框架<全能型框架MTV>/Web.py/flask框架<已经停止维护>/Tornado<facebook维护>Web应用框架......