Golang实践:使用 Go+ 第 1 部分创建微服务
来自JavaScript的背景,我一直想学习一种静态类型的编程语言,今年早些时候,我拿起Golang后,阅读了有关语言的评论,Golang得到了谷歌的支持。哦, 当然, 流行的 Devops 工具, 如码头, 库伯内特, Terraform, 是用Golang建造的。在通过 freecodecamp 从这个令人敬畏的教程中选取基础知识后,我决定构建一个生产级别的微服务体系结构。该项目将具有单元测试、CI/CD 集成和健壮的体系结构,这些架构将来可以扩展。前端将写在React中。
这将是一个多部分博客,记录了整个体系结构的创建。代码将托管在这里:https://github.com/nandangrover/go-microservices。本系列的第一部分,这是这个博客文档可以在此分支找到。我会使用 Ubuntu 的系列, 但Golang坐在其他 Os 以及, 所以它不应该是一个问题。
我选择的代码编辑器是视觉工作室,我建议你使用它。它有许多开箱即用的好处。Visual Studio 代码支持"开箱即用"突出显示的 Go 语法。vscode-go插件提供了其他功能,该插件与十几种标准 Go 工具集成。如果您没有设置 GOPATH,插件将要求您在尝试编辑 Go 语言文件时尽快设置它;您可以为项目和/或系统环境设置它。如果您没有安装 Go 工具,插件将要求将它们安装在 GOPATH 确定的标准位置。
文件结构如何?
我的 go 工作区将转到二进制文件以及我的个人项目分开。在我看来,这让工作空间变得不那么杂乱无章。我们将利用 GOPATH 环境变量来形成这样的工作区。
如上图所示,go 库/二进制文件存储在 golib 文件夹中,而我们的个人项目将存储在 goCode 中。
现在,让我们看看 goCode 文件夹。它由一个 go-microservices 目录组成,该目录以相同的名称推送在 git 上。
它包含一个 main.go 文件和一个名为处理程序的文件夹。我们有我们的 gitgnore 和 README.md GitHub 的一个。
深入到代码中
让我们看看我们的 main.go 文件,它包含构建两个简单的微服务的逻辑 - 你好再见。
func main() { l := log.New(os.Stdout, “product-api”, log.LstdFlags) hh := handlers.NewHello(l) gh := handlers.NewGoodbye(l)sm := http.NewServeMux() sm.Handle("/", hh) sm.Handle("/goodbye", gh)s := &http.Server{ Addr: “:9090”, Handler: sm, IdleTimeout: 120 * time.Second, ReadTimeout: 1 * time.Second, WriteTimeout: 1 * time.Second, } // wrapping ListenAndServe in gofunc so it’s not going to block go func() { err := s.ListenAndServe() if err != nil { l.Fatal(err) } }()// make a new channel to notify on os interrupt of server (ctrl + C) sigChan := make(chan os.Signal) signal.Notify(sigChan, os.Interrupt) signal.Notify(sigChan, os.Kill)// This blocks the code until the channel receives some message sig := <-sigChan l.Println(“Received terminate, graceful shutdown”, sig) // Once message is consumed shut everything down // Gracefully shuts down all client requests. Makes server more reliable tc, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() s.Shutdown(tc) }
我们首先通过调用日志创建新记录器。新增功能。我们可以有多个记录器在未来,所以我们创建一个简单的记录器的名称产品api开始。
下一步是使用记录器初始化我们的处理程序。处理程序是我们的自定义方法,实现处理程序接口。在内部,在 http 模块中,Handler 接口实现 ServeHTTP 方法,该方法又接受 http。响应编写器和指向 *http 的指针。请求。Golang 很好地记录了 http 服务器,您可以查看其官方文档中的处理程序接口,以更好地了解 http 模块的内部工作。
运行我们的服务器和服务Mux
而不是使用 http 创建新服务器。ListenAndServe (“9090”),我们使用很少使用的 NewServeMux 函数与指向 http 的指针相结合。用于自定义服务器的服务器。名称描述的 NewServeMux 返回一个 ServeMux。
ServeMux 是 HTTP 请求多路复用器。它根据已注册模式的列表匹配每个传入请求的 URL,并调用与 URL 最匹配的模式的处理程序。你可以在官方文档中阅读更多关于它。
sm := http.NewServeMux() sm.Handle("/", hh) sm.Handle("/goodbye", gh)
s := &http.Server{ Addr: “:9090”, Handler: sm, IdleTimeout: 120 * time.Second, ReadTimeout: 1 * time.Second, WriteTimeout: 1 * time.Second, } // wrapping ListenAndServe in gofunc so it’s not going to block go func() { err := s.ListenAndServe() if err != nil { l.Fatal(err) } }()
服务器定义运行 HTTP 服务器的参数。使用初始参数初始化后,我们调用 ListenandServe 函数。这将在指定的端口中启动我们的 http 服务器,该端口目前为 9090。我们为什么要用一条古例来包装这个?ListenandServe 是一个阻塞代码。它阻止该过程,因此不会执行该行下方的任何东西。Go 程序本质上是非阻塞的。这样,服务器可以在单独的 CPU 进程中启动。这也是我们必须采取的第一步,以便在 Go 中运行多台服务器。
💡_与__方法调用__不同,方法调用不需要任何参数,因为服务器的配置存在于结构__本身中。函数__内部使用函数在__地址上__创建侦听器__,函数返回 和__函数一__起使用它,使用字段值__(ServeMux 对象)侦听传入连接。_
_http.ListenAndServe(addr string, handler Handler)_``````_server._[_ListenAndServe_](https://zshipu.com/t?url=https://golang.org/pkg/net/http/#Server.ListenAndServe)_()_``````_server_``````_server.ListenAndServe_``````_tcp_``````_addr_``````_net._[_Listen_](https://zshipu.com/t?url=https://golang.org/pkg/net/#Listen)``````_net._[_Listener_](https://zshipu.com/t?url=https://golang.org/pkg/net/#Listener)``````_server._[_Serve_](https://zshipu.com/t?url=https://golang.org/pkg/net/http/#Server.Serve)``````_server.Handler_
正常关闭服务器
为什么关闭服务器非常重要?假设客户端已发送请求以将其映像保存在数据库中。同时,我们必须做一些维护工作,我们关闭服务器。映像在后端应有多个调用来处理它。第一个是 aws, 以实际保存它, 并得到文件 ID 和链接。假设此部分已完成执行,但为了将映像注册为已保存,我们不必将 aws 数据保存在内部数据库中。此时,服务器将停止。因此,映像保存在 aws 中,但我们不知道,当服务器在执行客户端请求时停止时。
为了防止发生此类情况,我们必须正常关闭服务器,以便处理所有当前处于活动状态的客户端请求。
关闭正常关闭服务器,而不会中断任何活动连接。关闭的工作原理是首先关闭所有打开的侦听器,然后关闭所有空闲连接,然后无限期地等待连接返回到空闲状态,然后关闭。如果提供的上下文在关闭完成之前过期,则"关机"将返回上下文的错误,否则,它将返回关闭服务器的基础侦听器返回的任何错误。
为了触发关机,我们侦听来自 os 的中断信号。我们通过传递 os 创建一个 go 通道。信号。通知用于注册以中断和终止来自服务器的信号。
去通道是自然阻塞的。因此,如果我们从 out sigChan 读取消息,则它随后会阻止它下面的所有代码。收到中断信号后,我们将打印关机消息并创建 30 秒的超时上下文。我们将此传递给我们的服务器。关机功能。
关闭方法需要传入请求的基本上下文。如果尚未配置结构的字段,可以使用 ,因为它是该字段的默认值。[BaseContext](https://zshipu.com/t?url=https://golang.org/pkg/net/http/#Server.BaseContext)``````Server``````context.[Background](https://zshipu.com/t?url=https://golang.org/pkg/context/#Background)()``````BaseContext
// make a new channel to notify on os interrupt of server (ctrl + C) sigChan := make(chan os.Signal) signal.Notify(sigChan, os.Interrupt) signal.Notify(sigChan, os.Kill)// This blocks the code until the channel receives some message sig := <-sigChan l.Println(“Received terminate, graceful shutdown”, sig) // Once message is consumed shut everything down // Gracefully shuts down all client requests. Makes server more reliable tc, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() s.Shutdown(tc)
处理器
如前所述,处理程序是我们的自定义方法,实现处理程序接口。以下代码显示 Hello 处理程序的创建。当请求发送到本地主机:9090 时,将执行此命令。我们还可以发送数据。在 Linux 中,我们可以通过以下命令轻松做到这一点curl -v localhost:9090 -d "World"
// Hello handler type Hello struct { l *log.Logger }// NewHello Function which gives reference to Hello handler func NewHello(l *log.Logger) *Hello { return &Hello{l} }func (h *Hello) ServeHTTP(rw http.ResponseWriter, r *http.Request) { h.l.Println(“Hello world”) d, err := ioutil.ReadAll(r.Body)if err != nil { http.Error(rw, “Oops”, http.StatusBadRequest) return } fmt.Fprintf(rw, “Hello %s\n”, d) }
我们首先定义一个名为 Hello 的结构,其类型为*log。记录器(指向记录器模块的指针)。
ServeHTTP 是 Hello 处理程序上的方法,当我们向本地主机:9090 发送请求时,由 http/server 模块执行该方法。该方法当前仅在服务器日志中记录 Hello world。如果随一些数据一起发送**,则 ioutil会从请求正文和 http 读取数据。响应**编写器用于将数据打印为响应。
结论
我们创建了一个非常基本的 http 服务器,可用于以标准化格式进一步创建更多 API。使用 go 通道实现了正常关闭。我们可以期待在博客的下一部分创建 RESTful 服务。
引用
- 代码库: https://github.com/nandangrover/go-microservices
- 第 1 部分 github 链接: https://github.com/nandangrover/go-microservices/tree/microservices_basic_1
- Golang的自由代码营地教程: https://www.youtube.com/watch?v=YS4e4q9oBaU&ab_channel=freeCodeCamp.org
- Golang的服务器文档: https://golang.org/src/net/http/server.go
- 服务器Mux: https://golang.org/pkg/net/http/#ServeMux
- 原文作者:知识铺
- 原文链接:https://index.zshipu.com/geek/post/go/Golang%E5%AE%9E%E8%B7%B5%E4%BD%BF%E7%94%A8-Go+-%E7%AC%AC-1-%E9%83%A8%E5%88%86%E5%88%9B%E5%BB%BA%E5%BE%AE%E6%9C%8D%E5%8A%A1/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com