go-proj

module
v0.0.0-...-2499e25 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 27, 2023 License: MIT

README

go-proj 项目

基于golang gin框架和grpc框架封装而成。
涉及到的包:gin,grpc,protobuf,redigo,daheige/thinkgo

go version选择

推荐使用go v1.16.15+版本

golang linux环境安装

golang下载地址: https://golang.google.cn/dl/

以go最新版本go1.16.15版本为例 https://golang.google.cn/dl/go1.20.2.linux-amd64.tar.gz

  1. linux环境(centos,ubuntu操作系统),下载
cd /usr/local/
    sudo wget https://golang.google.cn/dl/go1.16.15.linux-amd64.tar.gz
    sudo tar zxvf go1.16.15.linux-amd64.tar.gz
    # 创建golang需要的目录
    sudo mkdir ~/go
    sudo mkdir ~/go/bin
    sudo mkdir ~/go/src
    sudo mkdir ~/go/pkg
  1. 设置环境变量vim ~/.bashrc 或者sudo vim /etc/profile
    export GOROOT=/usr/local/go
    export GOOS=linux
    export GOPATH=~/go
    export GOSRC=$GOPATH/src
    export GOBIN=$GOPATH/bin
    export GOPKG=$GOPATH/pkg
    
    #开启go mod机制
    export GO111MODULE=on

    #禁用cgo模块
    export CGO_ENABLED=0
    export GOPROXY=https://goproxy.cn,direct

    export PATH=$GOROOT/bin:$GOBIN:$PATH

:wq 保存退出 3. source ~/.bashrc 生效配置

golang mac系统安装

只需要下载 https://golang.google.cn/dl/go1.16.15.darwin-amd64.pkg 然后点击下一步,下一步就可以安装完毕 环境变量配置: vim ~/.bash_profile

    export GOROOT=/usr/local/go
    export GOOS=linux
    export GOPATH=~/go
    export GOSRC=$GOPATH/src
    export GOBIN=$GOPATH/bin
    export GOPKG=$GOPATH/pkg
    #开启go mod机制
    export GO111MODULE=on
    
    #禁用cgo模块
    export CGO_ENABLED=0
    
    #配置goproxy代理
    export GOPROXY=https://goproxy.cn,direct
    export PATH=$GOROOT/bin:$GOBIN:$PATH

:wq 退出即可,然后执行 source ~/.bash_profile 生效

go-proj 目录结构

.
├── app                             应用目录
│   ├── job                         job/task作业层
│   ├── logic                       公共逻辑层,上下文采用标准上下文ctx
│   ├── rpc                         grpc service层
│   │   └── service
│   └── web                         web/api
│       ├── controller
│       ├── middleware
│       └── routes
├── bin                             存放golang生成的二进制文件和shell脚本
│   ├── go-gen                      golang生成的二进制文件
│   │   ├── rpc
│   │   └── web
│   ├── nodejs-generate.sh
│   ├── pb-generate.sh              golang pb和php pb代码生成脚本
│   ├── php7.2_install.sh
│   └── web-init.sh                 golang rpc,web,job自动化构建脚本
├── conf                            项目配置文件目录
├── clients                         golang,php,nodejs客户端生成的代码
│   ├── go
│   │   └── client.go
│   └── php
│       ├── App                     自动生成的php代码
│       ├── composer.json           composer文件,可以指定App命名空间自动加载
│       ├── composer.lock
│       ├── hello_client.php
│       ├── readme.md
│       └── vendor
├── cmd                             各个应用的main.go文件和配置文件app.yaml,线上可以放在别的目录
│   ├── job
│   ├── rpc
│   │   ├── app.yaml                开发模式下的配置文件
│   │   ├── logs
│   │   └── main.go
│   └── web
│       ├── app.yaml
│       ├── logs
│       └── main.go
├── go.mod
├── go.sum
├── library                         公共库主要是第三方库,logger,gin metrics监控等
│   ├── helper                      助手函数库
│   ├── ginMonitor                  gin web/api打点监控
│   └── logger                      日志服务
├── LICENSE
├── logs                            运行日志目录,线上可放在别的目录,开发模式goland日志放在logs中
│   ├── rpc
│   └── web
├── pb                              根据pb协议,自动生成的golang pb代码
│   └── hello.pb.go
├── protos                          pb协议文件
│   └── hello.proto
└── readme.md

关于web层

基于gin1.8.2+框架封装而成

关于gin validate参数校验

gin1.8.2+ 基于gopkg.in/go-playground/validator.v10封装之后
将validator库的validate tag改成了binding方便gin使用

参考手册:
    https://github.com/go-playground/validator/tree/v9
    https://godoc.org/github.com/go-playground/validator
    https://github.com/go-playground/validator/blob/master/_examples/simple/main.go

gin使用手册

参考 https://github.com/gin-gonic/gin
中文翻译: https://github.com/daheige/gin-doc-cn 如果有更新,以官网为准

go-grpc 和 php grpc 工具安装

ubuntu系统
    参考 https://github.com/daheige/hg-grpc
centos系统
    参考 docs/centos7-protoc-install.md

php grpc工具和拓展安装

参考 docs/centos7-protoc-install.md

grpc 运行

1、生成pb代码 (生成代码之前,请先安装好go-grpc 和 php grpc 工具)
    sh bin/go-generate.sh
    sh bin/php-generate.sh

2、启动服务端
$ cp app.exam.yaml app.yaml
$ sh bin/app-start.sh rpc
2019/07/14 11:25:26 server pprof run on:  51051
2019/07/14 11:25:26 go-proj grpc run on: 50051

3、运行客户端
$ go run clients/go/client.go
2019/07/14 11:26:36 name:hello,golang grpc,message:call ok

php客户端
$ php clients/php/hello_client.php
检测App\Grpc\GPBMetadata\Hello\HelloReq是否存在
bool(true)
status code: 0
name:hello,world
call ok

grpc拦截器使用

grpc拦截器用法,看go grpc源代码,里面都有对应的方法
Go-gRPC 实践指南 https://www.bookstack.cn/read/go-grpc/chapter2-interceptor.md

grpc 中间件

go-proj/app/rpc/middleware/chain.go
定义多个中间件(拦截器)
// 注册interceptor和中间件
opts = append(opts, grpc.UnaryInterceptor(
	middleware.ChainUnaryServer(
		middleware.RequestInterceptor,
		middleware.Limit(&middleware.MockPassLimiter{}),
	)))

server := grpc.NewServer(opts...)
具体demo参考cmd/rpc/main.go

grpc中间件参考: https://github.com/grpc-ecosystem/go-grpc-middleware

grpc 和 http gw共用一个端口进行对外服务

实现方式参考: https://eddycjy.com/posts/go/grpc-gateway/2019-06-22-grpc-gateway-tls/

1 安装好必要的依赖
    go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
    go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger
    go get -u github.com/golang/protobuf/protoc-gen-go

2 生成pb文件 
    % sh bin/go-generate.sh

    Generating codes...

    generating golang stubs...
    generating golang code success

    Generate codes successfully!

3 开始运行
    % cd cmd/rpc
    % go run http/server.go -config_dir=./
    2020/06/13 19:57:02 maxprocs: Leaving GOMAXPROCS=12: CPU quota undefined
    2020/06/13 19:57:02 config path:  /Users/heige/web/go/go-proj/cmd/rpc
    2020/06/13 19:57:02 server PProf run on:  2339
    2020/06/13 19:57:02 go-proj grpc run on: 1339

    运行客户端
    % go run clients/go/client_gw.go
    2020/06/13 19:58:51 name:hello,golang grpc,message:call ok

    这个时候去观察server服务端
    2020/06/13 19:58:51 req method:  /App.Grpc.Hello.GreeterService/SayHello
    2020/06/13 19:58:51 req data:  name:"golang grpc"

    通过http方式,访问grpc服务,浏览器中访问下面url
    http://localhost:1339/v1/say/123s
    返回信息
    {"name":"hello,123s","message":"call ok"}
    
    如果发生http 请求出错就会抛出类似下面的错误提示:
    {"error":"connection closed","code":14,"message":"connection closed"}

grpc-gateway 官方提供的gw 实现方式

需要先启动grpc server通过endpoint 方式实现
参考地址: https://github.com/grpc-ecosystem/grpc-gateway

grpc http gw 负载均衡和反向代理

# go grpc http层nginx配置
# 多个实例负载均衡
upstream gorpc_http {
        server 127.0.0.1:1339 weight=80 max_fails=2 fail_timeout=10;
        server 127.0.0.1:1340 weight=80 max_fails=2 fail_timeout=10;
}

# nginx配置
server {
        listen 80;

        # 根据实际情况设置
        server_name myrpc.com www.myrpc.com *.myrpc.com;

        # 访问日志设置
        access_log /data/logs/mygrpc/go-rpc-access.log;
        error_log /data/logs/mygrpc/go-rpc-error.log;

        # error_page 404 /etc/nginx/html/40x.html;
        # error_page 500 502 503 504 /50x.html;

        location = /50x.html {
            root /etc/nginx/html;
        }

        location @gorpc {
            proxy_redirect off;
            proxy_set_header Host $host;    #为反向设置原请求头
            proxy_set_header X-Read-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-NginX-Proxy true;
            proxy_set_header X-Request-Uri $request_uri;
            proxy_set_header X-Referer $http_referer;
            proxy_pass http://gorpc_http; #负载代理
        }

        location / {
            try_files $uri @gorpc;
        }
}

# nginx grpc_pass配置
# 对内服务,如果以grpc server pb格式,可以直接连接到这个ip:port上,也就是宿主机 ip:30051 就可以
server {
    listen 30051 http2;
    #server_name localhost;

    access_log /web/wwwlogs/go-grpc-access.log;

    location / {
        grpc_pass grpc://gorpc_http;
    }
}

配置上面的nginx后,启动cmd/rpc/http/server.go
% go run http/server.go -config_dir=./ -port=1339
2020/06/14 10:31:49 maxprocs: Leaving GOMAXPROCS=12: CPU quota undefined
2020/06/14 10:31:49 config path:  /Users/heige/web/go/go-proj/cmd/rpc
2020/06/14 10:31:49 server PProf run on:  2339
2020/06/14 10:31:49 go-proj grpc run on: 1339
以同样的方式启动1340端口
% go run http/server.go -config_dir=./ -port=1340
2020/06/14 10:31:49 maxprocs: Leaving GOMAXPROCS=12: CPU quota undefined
2020/06/14 10:31:49 config path:  /Users/heige/web/go/go-proj/cmd/rpc
2020/06/14 10:31:49 server PProf run on:  2340
2020/06/14 10:31:49 go-proj grpc run on: 1340

开始访问 
    http://localhost:1339/v1/say/daheige
    http://localhost:1340/v1/say/daheige

重启nginx
% /usr/local/nginx/bin/nginx -t
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
% sudo /usr/local/nginx/bin/nginx -s reload

配置/etc/hosts
127.0.0.1 myrpc.com www.myrpc.com *.myrpc.com
保存退出
浏览器中访问
http://myrpc.com/v1/say/daheige
http://myrpc.com/v1/say/daheige134

通过查看日志,在1339,1340两个实例上都可以看到请求打过来
2020/06/14 10:45:43 req method:  /App.Grpc.Hello.GreeterService/SayHello
2020/06/14 10:45:43 req data:  name:"daheige"
2020/06/14 10:46:11 req method:  /App.Grpc.Hello.GreeterService/SayHello
2020/06/14 10:46:11 req data:  name:"daheige134"

2020/06/14 10:46:00 req method:  /App.Grpc.Hello.GreeterService/SayHello
2020/06/14 10:46:00 req data:  name:"daheige123"
2020/06/14 10:47:28 req method:  /App.Grpc.Hello.GreeterService/SayHello
2020/06/14 10:47:28 req data:  name:"daheige123"

如果使用pb格式调用go grpc server
运行grpc client
$ go run clients/go/client_ng_grpc.go
2020/06/20 21:01:18 name:hello,golang grpc,message:call ok

实际生产环境中,可以同时提供http格式和grpc pb格式的调用
对外可以采用http协议,用clb在nginx上游做负载
对内服务,pb格式提供grpc server服务,直接用上面的nginx grpc_pass 机制就可以

woker job/task 运行

开发环境下运行job/task
$ cp app.exam.yaml cmd/worker/app.yaml
$ go run cmd/worker/worker.go
2019/07/17 21:29:37 ===worker service start===
2019/07/17 21:29:37 server pprof run on:  30031
2019/07/17 21:29:38 hello world
2019/07/17 21:29:39 current id:  heige
2019/07/17 21:29:40 hello world
2019/07/17 21:29:42 current id:  heige

项目工程化构建

构建web
$ sh bin/web-init.sh web
开始构建web二进制文件
构建web成功!

构建rpc
$ sh bin/web-init.sh rpc
Generating codes...

generating golang stubs...
generating golang code success
generating php stubs...
generating php stubs from: /web/go/go-proj/protos/hello.proto
        [DONE]


Generate codes successfully!

开始构建web二进制文件
构建rpc成功!

开发模式启动

可以把项目中的app.exam.yaml复制到cmd对应的应用中,然后go run main.go启动

关于项目部署

建议将web,grpc,job分开单独部署,可采用不同的app.yaml配置文件启动

项目上线说明

1、可将bin下面的对应cmd下面的main.go生成的二进制文件,分发到线上部署,配置文件参考cmd/web/app.yaml
2、上线二进制文件,需要指定app.yaml目录和logs目录

grpc server服务--nginx grpc_pass

这种方式对于内网其他业务调用grpc server提供的方法,建议用这个方式来控制grpc server服务的负载均衡处理
启动两个实例
$ cd cmd/rpc
$ go run main.go --port=50051
2019/11/09 18:55:00 server pprof run on:  51051
2019/11/09 18:55:00 go-proj grpc run on: 50051

新开一个终端
$ cd cmd/rpc
$ go run main.go --port=50052 --log_dir=/web/wwwlogs
2019/11/09 18:56:32 server pprof run on:  51052
2019/11/09 18:56:32 go-proj grpc run on: 50052

配置nginx grpc负载均衡
参考:
https://github.com/daheige/hg-grpc/blob/master/readme.md#%E9%85%8D%E7%BD%AEnginx-grpc%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1
为了go grpc服务高可用,需要对grpc服务做负载均衡处理,这里借助nginx grpc模块实现,配置如下:

#nginx gprc负载均衡配置,要求nginx1.13.0+以上版本
#nginx gprc负载均衡配置
# 多个ip:port实例
upstream go_grpc {
    server 127.0.0.1:50051 weight=5 max_fails=3 fail_timeout=10;
    server 127.0.0.1:50052 weight=1 max_fails=3 fail_timeout=10;
}

server {
    listen 50050 http2;
    server_name localhost;

    access_log /web/wwwlogs/go-grpc-access.log;

    location / {
        grpc_pass grpc://go_grpc;
    }
}

重启nginx
sudo service nginx restart

运行grpc client
$ go run clients/go/client_rpc.go
2019/11/09 19:01:18 name:hello,golang grpc,message:call ok
$ go run clients/go/client_rpc.go
2019/11/09 19:01:20 name:hello,golang grpc,message:call ok
$ go run clients/go/client_rpc.go
2019/11/09 19:01:23 name:hello,golang grpc,message:call ok

请求过程中可以看到两个实例,会产生响应日志
2019/11/09 19:07:46 req method:  /App.Grpc.Hello.GreeterService/SayHello
2019/11/09 19:07:46 req data:  name:"golang grpc"

查看请求日志
$ tail -f cmd/rpc/logs/go-grpc.log

$ tail -f /web/wwwlogs/go-grpc.log

通过查看日志,可以看到请求到50051这个实例的grpc请求相对多一点,50052这个实例相对少一点
因为nginx grpc的权重不一样

go mod 编译方式

方式1:
            如果采用go mod tidy 拉取依赖,会在$GOPATH/pkg/mod缓存go.mod中的包
            cd cmd/web 然后执行 go build进行编译就可以,更新go.mod包,会自动进行包依赖拉取

方式2:
            如果采用vendor机制,执行  go mod vendor  后会按需把项目用到的包,放在go-proj根目录的vendor下面
            cd cmd/web  然后执行  go build -mod=vendor 拉取当前目录下的vendor作为编译依赖包,进行编译

以上两种方式推荐使用方式1,这样只需要升级go.mod中的包,就不需要担心包依赖问题

docker 构建镜像

web层:
    $ docker build -t go-proj-web:v1 -f web-Dockerfile .
    运行:
    $ docker run -itd --name=go-proj-web -v /data/logs:/data/logs -v /data/www/go-proj:/data/conf -p 1338:1338 -p 2338:2338 go-proj-web:v1

job层:
    $ docker build -itd go-proj-job:v1 -f job-Dockerfile .
    运行:
    $ docker run -it --name=go-proj-job -v /data/logs:/data/logs -v /data/www/go-proj:/data/conf -p 30031:30031 go-proj-job:v1

rpc层:
    $ docker build -t go-proj-job:v1 -f job-Dockerfile .
    运行:
         $ docker run -itd --name=go-proj-rpc -v /data/logs:/data/logs -v /data/www/go-proj:/data/conf -p 50051:50051 -p 51051:51051 go-proj-rpc:v1

如果要在后台运行,docker run 加一个 -d参数

采用脚步构建镜像 sh bin/docker-build.sh web

版权

MIT

Directories

Path Synopsis
app
clients
go
cmd
rpc
web
library
ginmonitor
gin monitor打点监控 主要是对每个api/web请求做打点监控
gin monitor打点监控 主要是对每个api/web请求做打点监控
Package pb is a reverse proxy.
Package pb is a reverse proxy.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL