go搭建简单grpc服务(登录服务)1

开发环境

window10系统

vscode 1.69.2

golang 1.18.3

项目介绍

通过grpc搭建一个简单的登录服务,并实现多种客户端样例代码。

项目地址:https://github.com/kalaGN/usermservice

数据库结构

 

CREATE TABLE `bz_account` (
  `accountid` int(10) NOT NULL AUTO_INCREMENT COMMENT '自增账号编号',
  `username` varchar(32) COLLATE utf8_unicode_ci NOT NULL COMMENT '用户名',
  `password` varchar(32) COLLATE utf8_unicode_ci NOT NULL COMMENT '密码',
  `corpid` int(10) NOT NULL COMMENT '企业编号',
  `createTime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `lastLogin` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `isdelete` tinyint(4) NOT NULL DEFAULT '0' COMMENT '待定',
  PRIMARY KEY (`accountid`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=DYNAMIC COMMENT='账号表';

 

INSERT INTO `test`.`bz_account`(`accountid`, `username`, `password`, `corpid`, `createTime`, `lastLogin`, `isdelete`) VALUES (1, 'afei', 'e10adc3949ba59abbe56e057f20f883e', 1, '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0);

 

代码目录

 

 

 

实现步骤

  1. 初始化工程

 

echo "# usermservice" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M "main"
git remote add origin https://github.com/kalaGN/usermservice.git
git push -u origin "main"

 

增加.gitignore文件

 

  1. 编写proto文件

 打开pb\users\login.proto文件填入如下内容

 

syntax = "proto3";

package login;

message Request{
    string name = 1;
    string pwd = 2;
    string sign =3;
}

message Response{
    string code = 1;
    string msg = 2;
    string data =3;
    string token =4;
}

service LoginService{
    rpc Login(Request) returns (Response){}
}

 执行如下命令:

 

protoc --proto_path=./pb/users/ ./pb/users/*.proto --go-grpc_out=./pb/users/

 

报错

protoc-gen-go-grpc: unable to determine Go import path for "login.proto"

Please specify either:
        • a "go_package" option in the .proto source file, or
        • a "M" argument on the command line.

See https://developers.google.com/protocol-buffers/docs/reference/go-generated#package for more information.

--go-grpc_out: protoc-gen-go-grpc: Plugin failed with status code 1.

package login; 下增加一行代码

option go_package="./;login";

再次执行命令,生成pb\users\login_grpc.pb.go文件如下。

 

 再执行如下命令

 protoc --proto_path=./pb/users/ ./pb/users/*.proto --go_out=./pb/users/

 生成pb/users/login.pb.go 文件

 

提交代码

git commit -m "pb and gen"
git push -u origin "main"

 

  • 服务端代码

进入 server/v1/目录

新建文件server.go,输入如下内容

package main

import (
	"context"
	"fmt"
	"login"
	"net"

	"google.golang.org/grpc"
)

type LoginService struct {
}

func (s *LoginService) Login(ctx context.Context, req *login.Request) (*login.Response, error) {
	fmt.Printf("req name:%s, pwd:%s\n", req.Name, req.Pwd)

	return &login.Response{
		Code:  "1",
		Msg:   "login success",
		Data:  "ok",
		Token: "ttt",
	}, nil
}

func main() {
	l, err := net.Listen("tcp", ":8889")

	if err != nil {
		panic(err)
	}

	fmt.Println("listen on 127.0.0.1:8889")

	grpcServer := grpc.NewServer()

	loginService := LoginService{}
	login.RegisterLoginServiceServer(grpcServer, &loginService)

	err = grpcServer.Serve(l)

	if err != nil {
		println(err)
	}

}

 在同级目录初始化module

go mod init server
go mod tidy

 执行完成后go.mod go.sum生成。go.mod 文件如下

module server

go 1.18

require google.golang.org/grpc v1.48.0

require (
	github.com/golang/protobuf v1.5.2 // indirect
	golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect
	golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 // indirect
	golang.org/x/text v0.3.3 // indirect
	google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
	google.golang.org/protobuf v1.27.1 // indirect
)

 在go.mod 后面增加引入本地包方法:

require login v0.0.0

replace login => ../../pb/users

 再执行 go mod tidy

运行 go run server.go

 

 说明启动成功。

 

  • 客户端代码(go)

进入目录 client 新建 client.go,内容如下:

package main

import (
	"context"
	"flag"
	"fmt"
	"login"
	"time"

	"google.golang.org/grpc"
)

//初始化测试数据
var (
	dest = flag.String("dest", ":8889", "The server address in the format of host:port")
	name = flag.String("name", "afei", "The name is login account name")
	pwd  = flag.String("pwd", "123456", "The passwd is the login account password to login")
	sign = flag.String("sign", "sign123123123", "The cmd is the login cmd")
)

func printLogin(client login.LoginServiceClient, req *login.Request) {
	fmt.Printf("Client: Request sign:%s, name:%s, pwd:%s\n", req.Sign, req.Name, req.Pwd)

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	response, err := client.Login(ctx, req)
	if err != nil {
		fmt.Printf("%v\n", err)
		return
	}

	fmt.Println(response)
}

func main() {
	flag.Parse()
	conn, err := grpc.Dial(*dest, grpc.WithInsecure())
	if err != nil {
		fmt.Printf("failed to Dial")
	}
	defer conn.Close()

	client := login.NewLoginServiceClient(conn)

	printLogin(client, &login.Request{
		Name: *name,
		Pwd:  *pwd,
		Sign: *sign,
	})

}

 同理 需要初始化modele 并加入本地包login

启动客户端:

go run client.go

 出现如下输出说明通信成功

 

  • 增加配置文件config.ini

通过以上步骤,只是将最简单的通讯样例调试通了。接下来向生产可用改造。

首先我们应该引入配置文件。一些跟环境有关和资源(数据库,缓存)有关的配置放入配置文件方便修改。

我们在server 下建立pkg文件夹,新增config.go文件并输入如下内容:

package config

import (
	"fmt"

	"github.com/tietang/props/ini"
)

// ConfigFunc 动态加载配置信息
type ConfigFunc func() map[string]interface{}

// ConfigFuncs 先加载到此数组,loadConfig 再动态生成配置信息
var ConfigFuncs map[string]ConfigFunc

func LoadPort() (string, error) {
	file := "../v1/config.ini"
	conf := ini.NewIniFileConfigSource(file)
	return conf.Get("production.server.port")
}

func GetProduction() {
	file := "./config.ini"
	conf := ini.NewIniFileConfigSource(file)
	fmt.Println(conf.Get("production"))
}

 此包只是读取 server/v1/config.ini  文件  然后返回 [production] 下的server.port,配置文件内容如下

 

 并在pkg/config下初始化模块

go mod init config

go mod tidy

 

 修改server.go 中启动端口的地方 左侧是修改前,右侧是修改后

 

 

	port, _ := config.LoadPort()

	l, err := net.Listen("tcp", ":"+port)

	if err != nil {
		panic(err)
	}

	fmt.Println("listen on 127.0.0.1:" + port)

 提交到github

  • 增加gorm使用database

新建文件夹pkg/database,新建文件database.go,先定义字段并写一个简单的查询方法GetUser()。

package database

import (
	"fmt"
	"pkg/config"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

func Conn() (db *gorm.DB, er error) {

	// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
	dsn := config.GetDatabaseDsn()
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	fmt.Printf("Conn db=%v, err=%v\n", db, err)
	er = err
	return db, er
}

type Account struct {
	Accountid  string `json:accountid`
	Username   string `json:username` //用户名',
	Password   string `json:password` //密码',
	Corpid     int    `json:corpid`   //企业编号',
	CreateTime string `gorm:"type:datetime" json:"createTime"`
	LastLogin  string `json:lastLogin`
	Isdelete   string `json:isdelete`
}

func GetUser(name string, pwd string) {

	db, err1 := Conn()
	if err1 != nil {
		fmt.Println(err1.Error())
	}
	account := new(Account)
	res := db.Where("username=?", name).Where("password=?", pwd).First(account)

	fmt.Println(res.Error)        //判断返回值的错误
	fmt.Println(res.RowsAffected) //查看返回条数
	fmt.Println("查询到的对象为", *account)
	fmt.Println("查询到的对象为", account) //相对于上面
}

 

 在pkg/database下初始化模块database

go mod init database

go mod tidy

 应为这里的数据库连接方法 config.GetDatabaseDsn() 是在/pkg/config/config.go 中定义,所以在config.go文件末尾增加方法

 

// root:pwd@tcp(ip:3306)/test
func GetDatabaseDsn() string {
	file := "../v1/config.ini"
	conf := ini.NewIniFileConfigSource(file)
	users, _ := conf.Get("production.database.user")
	passwd, _ := conf.Get("production.database.password")
	host, _ := conf.Get("production.database.host")
	port, _ := conf.Get("production.database.port")
	db, _ := conf.Get("production.database.dbname")
	return users + ":" + passwd + "@tcp(" + host + ":" + port + ")/" + db + "?charset=utf8mb4&parseTime=True&loc=Local"
}

 

在 /server/v1/config.ini中增加数据库有关配置项(需要改成自己的数据库连接信息)

database.host=127.0.0.1
database.port=3306
database.user=root
database.password=afei
database.dbname=test

 同理 database.go 引用了本地的pkg/config包,所以要在database 下go.mod中增加本地包导入规则

require pkg/config v0.0.0

replace pkg/config => ../config

 执行

go mod tidy

 

我们在/server/v1/server.go main函数中测试一下GetUser()方法

database.GetUser("afei", "e10adc3949ba59abbe56e057f20f883e")

 

 

运行

 

posted @ 2022-07-22 07:10  阿飞afei  阅读(594)  评论(0编辑  收藏  举报