1 Star 0 Fork 0

wshadm / go11

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

研发管理平台裁剪版

  1. 创建项目骨架(同vblog一样)
  2. 编写mcenter服务业务模块:
    • 认证
    • 权限
  3. 编写一个cmdb服务, 接入用户中心(mcenter)
  4. 审计服务maudit, 记录用户操作日志, 核心使用消息独立(Kafka)

社区的一些微服务框架:

Web框架: go-restful

  1. 初始化container
//import "github.com/emicklei/go-restful/v3"

r := restful.DefaultContainer
// 设置默认ContentType
restful.DefaultResponseContentType(restful.MIME_JSON)
restful.DefaultRequestContentType(restful.MIME_JSON)

// CORS中间件
cors := restful.CrossOriginResourceSharing{
    AllowedHeaders: []string{"*"},
    AllowedDomains: []string{"*"},
    AllowedMethods: []string{"HEAD", "OPTIONS", "GET", "POST", "PUT", "PATCH", "DELETE"},
    CookiesAllowed: false,
    Container:      r,
}
// 使用Filter加载 GoRestful中间件(等同于Gin Use)
r.Filter(cors.Filter)
  1. 模块注册路由到Container: ioc: LoadGoRestfulApi
// LoadHttpApp 装载所有的http app
func LoadGoRestfulApi(pathPrefix string, root *restful.Container) {
	objects := store.Namespace(ApiNamespace)
	for _, obj := range objects.Items {
		api, ok := obj.(GoRestfulApiObject)
		if !ok {
			continue
		}

        // 为模块创建一个WebService
		pathPrefix = strings.TrimSuffix(pathPrefix, "/")
		ws := new(restful.WebService)
		ws.
			Path(fmt.Sprintf("%s/%s/%s", pathPrefix, api.Version(), api.Name())).
			Consumes(restful.MIME_JSON, form.MIME_POST_FORM, form.MIME_MULTIPART_FORM, yaml.MIME_YAML, yamlk8s.MIME_YAML).
			Produces(restful.MIME_JSON, yaml.MIME_YAML, yamlk8s.MIME_YAML)
            //把模块里面的路由 通通注册到这个WebService
		api.Registry(ws)

        // webservice 添加到container
		root.Add(ws)
	}
}

GRPC

从Protobuf的角度看,gRPC只不过是一个针对service接口生成代码的生成器。因此我们需要提前安装grpc的代码生成插件

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

安装protoc-gen-go-grpc插件

go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest 生成tag插件:go get https://github.com/favadi/protoc-go-inject-tag

项目的根路径: devcloud-mini(作为一个微服务工程)

需要进入mcenter项目内进行代码生成

$ protoc -I=. --go_out=.. --go-grpc_out=.. --go_opt=module="gitee.com/wshadm/go11/devcloud-mini" --go-grpc_opt=module="gitee.com/wshadm/go11/devcloud-mini" mcenter/apps/token/*/*.proto
xxx.pb.go生成在什么位置取决于:

1、xxx.proto中的option go_package="gitee.com/wshadm/go11/devcloud-mini/mcenter/apps/token";

2、--go_out和--go-grpc_out的位置

示例:在/d/gocode/dev-golang/devcloud/devcloud-mini目录中执行protocl命令
$ protoc -I=. --go_out=. --go-grpc_out=. --go_opt=module="gitee.com/wshadm/go11/devcloud-mini" --go-grpc_opt=module="gitee.com/wshadm/go11/devcloud-mini" cmdb/apps/*/pb/*.proto
pb.go文件中的go_package"gitee.com/wshadm/go11/devcloud-mini/mcenter/apps/token";
由于--go_out=.. --go-grpc_out=..都是用的"..",那么输出路径会往上一层输出,导致在上一层新建了目录:
mcenter/apps/token/xxx.pb.go

提问chatgpt:是不是可以简单理解为.proto文件中的go_package路径在哪,最终pb.go就会生成到哪里

是的,你的理解基本正确。在 Protocol Buffers 的 .proto 文件中,通过 go_package 选项指定 Go 代码生成的路径。这个路径包括了包名和生成的 .pb.go 文件的相对位置。

例如,如果你的 .proto 文件中有如下声明:
option go_package = "gitee.com/wshadm/go11/devcloud-mini/mcenter/apps/token";
这将指示 Protocol Buffers 编译器生成的 Go 代码的包名为 token,而且生成的 .pb.go 文件将被放置在 gitee.com/wshadm/go11/devcloud-mini/mcenter/apps/token 目录下。

这样的设计有助于将生成的代码与其他 Go 项目或模块进行隔离,同时也使得生成的代码的导入路径具有意义。在使用 protoc 编译命令时,通过 --go_out 选项指定的输出目录与 go_package 中指定的路径相关联。

在过程中经常遇到rpc.proto文件中不能正常import(例如meta.proto),最后修改为与学习项目结构一致D:/go11/devcloud-mini恢复了,要多练

再执行: protoc-go-inject-tag -input="cmdb/apps//.pb.go"

protobuf自定义标签

  1. 安装自定义proto 插件
go install google.golang.org/protobuf/cmdb/protoc-gen-go@latest
go install google.golang.org/grpc/cmdb/protoc-gen-go-grpc@latest
go install github.com/favadi/protoc-go-inject-tag@latest

补充Swagger文档接口

// API Doc
h.r.Add(apidoc.APIDocs(h.apiDocPath, swagger.Docs))
logger.L().Debug().Msgf("Swagger API Doc访问地址: http://%s%s", conf.C().Http.Address(), h.apiDocPath)

配置对象 1、单独的对象 mysql对象 http对象 Grpc对象 。。 2、对象的集合,封装到一个统一的配置对象当中 type Config struct { m *mysql h *http g *Grpc } 3、配置的初始化给一些默认配置,func NewConfig() *Config {} 读取配置 动态?还是? 不给路径就读默认,给了就赋值 修改配置时要有sycn.Mutex, 可以封装一个函数暴露全局供调用var config *Config , func C() *Config,其它不暴露。

日志库:定义日志的级别

protocol协议配置: [http配置]:创建httpserver对象,是用gin的,还是go-Restful的?协议配置, 当中定义httpserver的属性和配置(例如 是否需要跨域),读取config中http相关配置,如ip,port,超时时间等等 配置[start]和[stop]部分,当中可以加[swagger文档]的配置

Grpc配置:创建grpc.server对象和start、stop 同样也要读取config中的配置信息,ip port等

初始化

鉴权流程

权限最小化原则,流程 在 Go 语言中,接口权限最小化原则通常指的是在定义接口时,只包含必要的方法,以减少接口的复杂性和依赖性。这个原则与软件设计中的最小权限原则相似,目的是限制接口的暴露,使其只暴露出必要的行为,而不是暴露过多的细节。 内部服务实现interface接口就好,grpc或rpc则只暴露client端需要的接口方法就好,不必暴露过多

因此,确保内部服务实现的接口仅用于服务内部调用,并且只暴露给客户端需要的接口方法,是一个很好的设计原则,有助于提高系统的可维护性和安全性。

rpc、grpc 消息对象

使用 .proto 文件定义了要暴露给客户端的接口以及数据对象格式。这个文件定义了消息的结构和服务接口的方法。然后,使用 Protocol Buffers 的编译器(如 protoc)根据这个 .proto 文件生成相应语言的代码,例如 Go 语言的 .pb.go 文件。

生成的 .pb.go 文件中包含了客户端和服务端都可以使用的代码:

服务端代码:.pb.go 文件中包含了服务端需要实现的接口,这些接口定义了客户端可以调用的方法。服务端需要实现这些接口来提供具体的功能。

客户端代码:同样的 .pb.go 文件中也包含了客户端需要使用的代码,这些代码提供了对服务端定义的方法的调用接口。客户端可以使用这些方法来与服务端通信。

因此,.pb.go 文件是根据 .proto 文件生成的,其中包含了客户端和服务端所需的代码。这种方式使得定义接口和消息格式更加方便,并且通过自动生成代码,简化了客户端和服务端之间进行 RPC 或 gRPC 通信的过程。

rpc_grpc.pb.go) 文件通常包含 gRPC 协议相关的代码,其中包括根据 .proto 文件生成的 gRPC 服务接口的客户端和服务器端的代码,以及消息格式和序列化相关的代码。

rpc.pb.go 可能包含一些额外的业务逻辑代码,用于实现 .proto 文件中定义的 gRPC 服务接口中的方法。它也是根据 .proto 文件生成的,但可能包含了一些额外的业务逻辑,这取决于您是否在 .proto 文件中定义了自定义的方法或业务逻辑

impl控制器 init初始化时,用ioc注册业务的实现 显式的约束对象实现接口,以及实现Grpcserver和Ioc的接口,编写ioc的相关方法 注册Grpcserver和impl业务实现,给客户端用的, 这个注册过程意味着将 impl 中定义的远程过程调用(RPC)服务方法暴露给客户端, 使得客户端能够通过 gRPC 连接调用这些方法。 业务实现,token的颁发和删除

api当中都是在使用Grpc、rpc协议时使用的。做了权限最小化。只暴露必要的 api-http 当中同样有IOC注册,来获取业务的实现方法

api-token 通过绑定Handler和业务方法,来使用。当前使用的是GoRestful,需要符合框架签名。以及信息的自动脱敏。

cmd cobra命令行代码,启动http服务和Grpc服务,以及初始化业务部分的init方法

消息队列:kafka topic主题: 同一类消息在同一个topic中 partion分区: 一个topic可以分多个partion每个partition在存储层面是append log文件。任何发布到此partition的消息都会被直接追加到log文件的尾部

消费者组: img.png消费者组订阅一个主题,意味着主题下的所有分区都会被组中的消费者消费到, 并且主题下的每个分区只从属于组中的一个消费者,不可能出现组中的两个消费者负责同一个分区。 消费者从partition中消费数据,consumer有group的概念,每个group可以消费完整的一份topic中的数据。

如果分区数大于或者等于组中的消费者实例数,那么一个消费者会负责多个分区;如果消费者实例的数量大于分区数,有一些消费者是多余的,一直接不到消息而处于空闲状态。 即: 若consumer数量大于partition数量,会造成限制的consumer,产生浪费。 若consumer数量小于partition数量,会导致均衡失效,其中的某个或某些consumer会消费更多的任务。 消费分区是有策略的:https://cloud.tencent.com/developer/article/1953243

生产者: offset偏移量:每条消息在文件中的位置称为offset(偏移量),offset为一个long型数字,它是唯一标记一条消息。它唯一的标记一条消息。 kafka并没有提供其他额外的索引机制来存储offset,因为在kafka中几乎不允许对消息进行“随机读写”

v1: #!/bin/bash stop_application() { #process_name=ps -ef | grep start app_pid=$(lsof -ti tcp:8080) if [ -n "$app_pid" ]; then #kill -15 $app_pid lsof -ti tcp:8080 | xargs kill -15 wait $app_pid }

handle_sigterm() { stop_application exit 0 }

trap 'handle_sigterm' SIGTERM

#!/bin/bash stop_application() { process_name=ps -ef | grep start app_pid=$(ps -ef | grep $process_name | grep -v grep | awk '{print $2}')

if [ -n "$app_pid" ]; then

    kill -15 $app_pid

    wait $app_pid
else
    echo "Application process not found."
fi

}

handle_sigterm() { stop_application exit 0 }

trap 'handle_sigterm' SIGTERM

wait $app_pid

16:35

空文件

简介

暂无描述 展开 收起
Go 等 3 种语言
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
1
https://gitee.com/wshadm/go11.git
git@gitee.com:wshadm/go11.git
wshadm
go11
go11
master

搜索帮助