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

Go语言微服务框架go-micro(入门)的更多相关文章

  1. 一文带你快速入门 Go 语言微服务开发 - Dubbo Go 入门实践总结

    更多详细示例可直接访问 Dubbo 官网 或搜索关注官方微信公众号:Apache Dubbo 1. 安装Go语言环境 建议使用最新版 go 1.17 go version >= go 1.15 ...

  2. golang微服务框架go-micro 入门笔记2.3 micro工具之消息接收和发布

    本章节阐述micro消息订阅和发布相关内容 阅读本文前你可能需要进行如下知识储备 golang分布式微服务框架go-micro 入门笔记1:搭建go-micro环境, golang微服务框架go-mi ...

  3. golang微服务框架go-micro 入门笔记2.2 micro工具之微应用利器micro web

    micro web micro 功能非常强大,本文将详细阐述micro web 命令行的功能 阅读本文前你可能需要进行如下知识储备 golang分布式微服务框架go-micro 入门笔记1:搭建go- ...

  4. golang微服务框架go-micro 入门笔记2.4 go-micro service解读

    本章节阐述go-micro 服务发现原理 go-micro架构 下图来自go-micro官方 阅读本文前你可能需要进行如下知识储备 golang分布式微服务框架go-micro 入门笔记1:搭建go- ...

  5. AG-Admin微服务框架入门

    AG-Admin微服务框架入门  @qq群:一群: 837736451  二群 169824183 一 概要介绍 AG-Admin后台地址:https://gitee.com/minull/ace-s ...

  6. Surging 微服务框架使用入门

    原文:Surging 微服务框架使用入门 前言 本文非 Surging 官方教程,只是自己学习的总结.如有哪里不对,还望指正.  我对 surging 的看法 我目前所在的公司采用架构就是类似与Sur ...

  7. YoyoGo微服务框架入门系列-快速编写WEB API

    前言 YoyoGo是一个使用Golang编写的一个简单.轻量.快速.基于依赖注入的微服务框架,目前依然在研发阶段,欢迎Star以及一起参与到框架的研发 GitHub地址:https://github. ...

  8. Taurus.MVC 微服务框架 入门开发教程:项目部署:1、微服务应用程序常规部署实现多开,节点扩容。

    系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...

  9. Taurus.MVC 微服务框架 入门开发教程:项目部署:2、让Kestrel支持绑定多个域名转发,替代Ngnix使用。

    系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...

  10. Taurus.MVC 微服务框架 入门开发教程:项目部署:3、微服务应用程序版本升级:全站升级和局部模块升级。

    系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...

随机推荐

  1. 调用mglearn时的报错 TypeError: __init__() got an unexpected keyword argument 'cachedir'

    import mglearn的时候发生的报错 原因是调用了joblib包中的memory类,但是cachedir这个参数已经弃用了 查到下面帖子之后改掉cachedir解决问题 https://blo ...

  2. vs2013安装完VASSISTX助手之后字体变成斜体如何解决?

    VC助手为最新版本. 1. 打开vc助手选项 2. 取消勾选"show stable symbols in italics"

  3. Pytorch slp singleLayerPerceptron 单层感知机

    单层感知机 \[\begin{aligned} & y = XW + b \\ & y = \sum x_i*w_i+b\\ \end{aligned} \] Derivative \ ...

  4. vscode配置c++环境(超简单)

    vscode配置c++环境(超简单) 超简单!!! 配置c++最麻烦的就是mingw的环境,有很多不同的版本,很杂乱,这里我们用最简单的办法展示. 下载一个devc++. 如果你问我,为什么下了dev ...

  5. WEB开发日志1

    2020/6/11 23:23 今天做系统时,用到二级菜单,菜单下方放了一个<iframe>标签,但二级菜单的菜单项太多,导致一部分菜单项被<iframe>覆盖,从而无法再选中 ...

  6. Chrome(谷歌)浏览器永久关闭恢复页面提示框(记录)

    使用脚本调用Chrome浏览器启动指定页面,然后代码里的命令关闭,会被浏览器识别为非正常关闭. 再次执行脚本的时候会停留在空白页面,无法进入指定页面,设置为主页也无法进入. 排查可能是浏览器自动恢复页 ...

  7. hive --service metastore 启动报错

    1.问题示例: [Hadoop@master Hive]$ hive --service metastore2021-10-28 15:37:57: Starting Hive Metastore S ...

  8. 总结Unity查找物体的几种方法

    Unity中经常需要查找对象,对应的API也有好几种,各自有不同的适用场合. 1. GameObject.Find 通过名字或路径查找游戏对象. GameObject.Find("GameO ...

  9. Leecode 21.合并两个有序链表(Java 迭代、递归两种方法)

      想法: 1.迭代 设两个指针pa和pb,不断移动pa和pb,并进行比较,则将较小元素接到新链表,该过程直至pa或pb为null,之后将未空的接到已空之后,得到升序链表   1 //官方: 2 cl ...

  10. 使用redis分布式锁重复执行采坑

    事件:生产环境部署两台,每天凌晨1点,定时任务同步更新(先删除,后全部插入)账号表,使用了redis分布式锁,发现定时任务还是执行了两次,导致数据重复,影响对应业务. 原因分析:定时任务执行的逻辑是调 ...