当前位置:网站首页>Kratos ares microservice framework (II)
Kratos ares microservice framework (II)
2022-07-06 09:13:00 【~Pompeii】
Kratos Ares microservice framework ( Two )
Catalog
Project structure
api To write
protobuf To write
syntax = "proto3";
package realworld.v1;
import "google/api/annotations.proto";
option go_package = "realworld/api/realworld/v1;v1";
// The greeting service definition.
service RealWorld {
rpc Login(LoginRequest) returns (UserReply) {
option (google.api.http) = {
post: "/api/users/login",
body: "*", // Be careful post The request must be crossed body term
};
}
}
message LoginRequest{
message User {
string email = 1;
string password = 2;
}
User user = 1;
}
message UserReply {
message User {
string email = 1;
string token = 2;
string username = 3;
string bio = 4;
string image = 5;
}
User user = 1;
}
Use makefile
notes : Need to install make Instructions
GOPATH:=$(shell go env GOPATH)
VERSION=$(shell git describe --tags --always)
INTERNAL_PROTO_FILES=$(shell find internal -name *.proto)
API_PROTO_FILES=$(shell find api -name *.proto)
.PHONY: init
# init env
init:
go install google.golang.org/protobuf/cmd/[email protected]
go install google.golang.org/grpc/cmd/[email protected]
go install github.com/go-kratos/kratos/cmd/kratos/[email protected]
go install github.com/go-kratos/kratos/cmd/protoc-gen-go-http/[email protected]
go install github.com/google/gnostic/cmd/[email protected]
.PHONY: config
# generate internal proto
config:
protoc --proto_path=./internal \
--proto_path=./third_party \
--go_out=paths=source_relative:./internal \
./internal/conf/*.proto
# $(INTERNAL_PROTO_FILES)
.PHONY: api
# generate api proto
api:
protoc --proto_path=./api \
--proto_path=./third_party \
--go_out=paths=source_relative:./api \
--go-http_out=paths=source_relative:./api \
--go-grpc_out=paths=source_relative:./api \
--openapi_out=fq_schema_naming=true,default_response=false:. \
./api/realworld/v1/*.proto
# $(API_PROTO_FILES)
.PHONY: build
# build
build:
mkdir -p bin/ && go build -ldflags "-X main.Version=$(VERSION)" -o ./bin/ ./...
.PHONY: generate
# generate
generate:
go mod tidy
go get github.com/google/wire/cmd/[email protected]
go generate ./...
.PHONY: wire
# wire
wire:
cd cmd/realworld/ && wire
.PHONY: run
# run
run:
kratos run
.PHONY: all
# generate all
all:
make api;
make config;
make generate;
# show help
help:
@echo ''
@echo 'Usage:'
@echo ' make [target]'
@echo ''
@echo 'Targets:'
@awk '/^[a-zA-Z\-\_0-9]+:/ { \
helpMessage = match(lastLine, /^# (.*)/); \
if (helpMessage) { \
helpCommand = substr($$1, 0, index($$1, ":")-1); \
helpMessage = substr(lastLine, RSTART + 2, RLENGTH); \
printf "\033[36m%-22s\033[0m %s\n", helpCommand,helpMessage; \
} \
} \
{ lastLine = $$0 }' $(MAKEFILE_LIST)
.DEFAULT_GOAL := help
notes : The default is linux command ,windwos You need to change the path
service Layer interface implementation
Get into internal/service Catalog
service.go
package service
import (
"github.com/go-kratos/kratos/v2/log"
"github.com/google/wire"
v1 "helloworld/api/realworld/v1"
"helloworld/internal/biz"
)
// ProviderSet is service providers.
var ProviderSet = wire.NewSet(NewRealWorldService) // Dependency injection
type RealWorldService struct {
v1.UnimplementedRealWorldServer
pu *biz.SocialUsecase
uc *biz.UserUsecase
log *log.Helper
}
func NewRealWorldService(uc *biz.UserUsecase, logger log.Logger) *RealWorldService {
return &RealWorldService{
uc: uc, log: log.NewHelper(logger)}
}
// Implementation method
func (s *RealWorldService) Login(ctx context.Context, req *v1.LoginRequest) (*v1.UserReply, error) {
return &v1.UserReply{
User: &v1.UserReply_User{
Username: "jtyyds",
},
}, nil
}
biz layer
package biz
import "github.com/google/wire"
// ProviderSet is biz providers.
var ProviderSet = wire.NewSet(NewSocialUsecase, NewUserUsecase) // Dependency injection
type User struct {
Email string
Username string
Bio string
Image string
PasswordHash string
}
type UserLogin struct {
Email string
Username string
Token string
Bio string
Image string
}
// bcrypt Method encryption
func hashPassword(pwd string) string {
password, err := bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.DefaultCost)
if err != nil {
panic(err)
}
fmt.Printf("%v", password)
return string(password)
}
// Compare passwords
func verifyPassword(hashed, input string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hashed), []byte(input))
if err != nil {
return false
}
return true
}
// Interface method
type UserRepo interface {
CreateUser(ctx context.Context, user *User) error
GetUserByEmail(ctx context.Context, email string) (*User, error)
}
type ProfileRepo interface {
}
type UserUsecase struct {
ur UserRepo
pr ProfileRepo
jwtc *conf.JWT
log *log.Helper
}
func NewUserUsecase(ur UserRepo, pr ProfileRepo, jwtc *conf.JWT, logger log.Logger) *UserUsecase {
return &UserUsecase{
ur: ur, pr: pr, jwtc: jwtc, log: log.NewHelper(logger)}
}
func (uc *UserUsecase) generateToken(username string) string {
return auth.GenerateToken(uc.jwtc.Token, username)
}
// Registered business logic
func (uu *UserUsecase) Register(ctx context.Context, username, email, password string) (*UserLogin, error) {
u := &User{
Email: email,
Username: username,
PasswordHash: hashPassword(password),
}
if err := uu.ur.CreateUser(ctx, u); err != nil {
return nil, err
}
return &UserLogin{
Email: email,
Username: username,
Token: uu.generateToken(username),
}, nil
}
// Login business logic implementation
func (uu *UserUsecase) Login(ctx context.Context, email, password string) (*UserLogin, error) {
u, err := uu.ur.GetUserByEmail(ctx, email)
if err != nil {
return nil, err
}
b := verifyPassword(u.PasswordHash, password)
if b == true {
return nil, errors.New("Loin")
}
return &UserLogin{
Email: u.Email,
Username: u.Username,
Bio: u.Bio,
Image: u.Image,
Token: uu.generateToken(u.Username),
}, nil
}
data layer
data.go
package data
import (
"fmt"
"github.com/go-kratos/kratos/v2/log"
"github.com/google/wire"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"helloworld/internal/conf"
)
// ProviderSet is data providers.
var ProviderSet = wire.NewSet(NewData, NewDB, NewUserRepo, NewProfileRepo) // Dependency injection
// Data .
type Data struct {
// TODO wrapped database client
db *gorm.DB
}
// NewData .
func NewData(c *conf.Data, logger log.Logger, db *gorm.DB) (*Data, func(), error) {
cleanup := func() {
log.NewHelper(logger).Info("closing the data resources")
}
return &Data{
db: db}, cleanup, nil
}
// Connect mysql database
func NewDB(c *conf.Data) *gorm.DB {
fmt.Println(c.Database.Dsn)
db, err := gorm.Open(mysql.Open(c.Database.Dsn), &gorm.Config{
})
if err != nil {
panic("failed")
}
if err := db.AutoMigrate(); err != nil {
panic(err)
}
return db
}
package data
import (
"context"
"github.com/go-kratos/kratos/v2/log"
"helloworld/internal/biz"
)
type userRepo struct {
data *Data
log *log.Helper
}
func NewUserRepo(data *Data, logger log.Logger) biz.UserRepo {
return &userRepo{
data: data,
log: log.NewHelper(logger),
}
}
func (r *userRepo) CreateUser(ctx context.Context, g *biz.User) error {
// It can operate the database , This has not been achieved
return nil
}
func (r *userRepo) GetUserByEmail(ctx context.Context, email string) (*biz.User, error) {
// It can operate the database , This has not been achieved
return nil, nil
}
configs The configuration file
server:
http:
addr: 0.0.0.0:8000
timeout: 1s
grpc:
addr: 0.0.0.0:9000
timeout: 1s
data:
database:
driver: mysql
dsn: "root:[email protected](127.0.0.1:3306)/realworld?charset=utf8mb4&parseTime=True&loc=Local"
jwt:
secret : "hello"
After modifying the configuration file , Need modification internal/conf Under the conf.proto
syntax = "proto3";
package kratos.api;
option go_package = "helloworld/internal/conf;conf";
import "google/protobuf/duration.proto";
message Bootstrap {
Server server = 1;
Data data = 2;
JWT jwt = 3;
}
message Server {
message HTTP {
string network = 1;
string addr = 2;
google.protobuf.Duration timeout = 3;
}
message GRPC {
string network = 1;
string addr = 2;
google.protobuf.Duration timeout = 3;
}
HTTP http = 1;
GRPC grpc = 2;
}
message Data {
message Database {
string driver = 1;
string dsn = 2;
}
Database database = 1;
}
message JWT {
string token = 1;
}
Use make config Generate conf.pb.go
notes : Need to modify config Of makefile
边栏推荐
- Chapter 1 :Application of Artificial intelligence in Drug Design:Opportunity and Challenges
- [OC]-<UI入门>--常用控件-提示对话框 And 等待提示器(圈)
- Redis之持久化实操(Linux版)
- [OC foundation framework] - string and date and time >
- LeetCode:34. Find the first and last positions of elements in a sorted array
- Kratos战神微服务框架(二)
- LeetCode:394. String decoding
- I-BERT
- Connexion d'initialisation pour go redis
- LeetCode:124. Maximum path sum in binary tree
猜你喜欢
BN folding and its quantification
如何正确截取字符串(例:应用报错信息截取入库操作)
注意力机制的一种卷积替代方式
Simclr: comparative learning in NLP
Improved deep embedded clustering with local structure preservation (Idec)
CUDA implementation of self defined convolution attention operator
Redis之五大基础数据结构深入、应用场景
Chapter 1 :Application of Artificial intelligence in Drug Design:Opportunity and Challenges
MySQL uninstallation and installation methods
Advanced Computer Network Review(4)——Congestion Control of MPTCP
随机推荐
requests的深入刨析及封装调用
[OC foundation framework] - [set array]
Pytest's collection use case rules and running specified use cases
Philosophical enlightenment from single point to distributed
go-redis之初始化连接
MySQL uninstallation and installation methods
【图的三大存储方式】只会用邻接矩阵就out了
[OC-Foundation框架]---【集合数组】
Ijcai2022 collection of papers (continuously updated)
Pytest之收集用例规则与运行指定用例
Redis之主从复制
IJCAI2022论文合集(持续更新中)
Advanced Computer Network Review(3)——BBR
Mathematical modeling 2004b question (transmission problem)
Problems encountered in connecting the database of the project and their solutions
Compétences en mémoire des graphiques UML
[OC foundation framework] - string and date and time >
postman之参数化详解
Reids之缓存预热、雪崩、穿透
CSP student queue