Fly.io部署go应用

前面讲解了 Fly.io 的初步入门使用,本文讲解在没有 docker 环境情况下部署 go 开发的应用。 项目 这里为了演示方便, 简单使用 go 编写一个: package main import ( "fmt" "log" "net/http" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w,"hello world") }) log.Println("listening on", 8080) log.Fatal(http.ListenAndServe(":"+"8080", nil)) } 安装 Flyctl 并登录 这个步骤上篇文章已经介绍过来,还不了解如何安装登录的可以参考前面的文章。 配置 Fly 应用程序 进入项目的根目录,执行 flyctl launch,它会根据你输入的配置(主要是应用名,部署区域,是否需要数据库和redis)来生成相应的配置文件,并帮你在远程构建器上打包镜像并部署,如果有 DOCKERFILE 文件就会使用你的进行构建,如果没有就会使用相应的官方文件进行构建镜像. 需要注意的是你的应用需要监听 8080 端口,否则部署时会报错 从日志可以看到打包好的镜像名是 registry.fly.io/cool-grass-2591:deployment-01GHPEDCXBC3K5NAGHNZWKT49H fly.toml 配置 我们来看看 flyctl 帮我们生成的 fly.toml 具体内容: # fly.toml file generated for cool-grass-2591 on 2022-11-13T01:32:35+08:00 app = "cool-grass-2591" kill_signal = "SIGINT" kill_timeout = 5 processes = [] [env] [experimental] allowed_public_ports = [] auto_rollback = true [[services]] http_checks = [] internal_port = 8080 processes = ["app"] protocol = "tcp" script_checks = [] [services.concurrency] hard_limit = 25 soft_limit = 20 type = "connections" [[services.ports]] force_https = true handlers = ["http"] port = 80 [[services.ports]] handlers = ["tls", "http"] port = 443 [[services.tcp_checks]] grace_period = "1s" interval = "15s" restart_limit = 0 timeout = "2s" 主要就是一些常规的服务端口配置等。 ...

十一月 12, 2022 · overstarry

前后端使用AES加密传输数据

最近遇到前后端传输数据需要进行加密的需求,本篇文章就分别介绍使用 Node.js 和 go 进行 AES 加密解密的方法, AES 有很多不同的算法,如aes192,aes-128-ecb,aes-256-cbc等,根据不同的密钥长度会使用不同的算法。 加密后的结果有两种表示方法:hex和base64,我们这里使用 hex. golang 使用 golang 实现 aes 加密,我使用标准库的方法实现,我使用的 CBC 模式。 加密 func AesEncrypt(encryptStr string, key []byte, iv string) (string, error) { encryptBytes := []byte(encryptStr) block, err := aes.NewCipher(key) if err != nil { return "", err } blockSize := block.BlockSize() encryptBytes = pkcs5Padding(encryptBytes, blockSize) blockMode := cipher.NewCBCEncrypter(block, []byte(iv)) encrypted := make([]byte, len(encryptBytes)) blockMode.CryptBlocks(encrypted, encryptBytes) return hex.EncodeToString(encrypted), nil } 解密 func AesDecrypt(decryptStr string, key []byte, iv string) (string, error) { decryptBytes, err := hex.DecodeString(decryptStr) if err != nil { return "", err } block, err := aes.NewCipher(key) if err != nil { return "", err } blockMode := cipher.NewCBCDecrypter(block, []byte(iv)) decrypted := make([]byte, len(decryptBytes)) blockMode.CryptBlocks(decrypted, decryptBytes) decrypted = pkcs5UnPadding(decrypted) return string(decrypted), nil } 运行加密解密例子 package main import ( "bytes" "crypto/aes" "crypto/cipher" "encoding/hex" "fmt" ) func AesEncrypt(encryptStr string, key []byte, iv string) (string, error) { encryptBytes := []byte(encryptStr) block, err := aes.NewCipher(key) if err != nil { return "", err } blockSize := block.BlockSize() encryptBytes = pkcs5Padding(encryptBytes, blockSize) blockMode := cipher.NewCBCEncrypter(block, []byte(iv)) encrypted := make([]byte, len(encryptBytes)) blockMode.CryptBlocks(encrypted, encryptBytes) return hex.EncodeToString(encrypted), nil } func AesDecrypt(decryptStr string, key []byte, iv string) (string, error) { decryptBytes, err := hex.DecodeString(decryptStr) if err != nil { return "", err } block, err := aes.NewCipher(key) if err != nil { return "", err } blockMode := cipher.NewCBCDecrypter(block, []byte(iv)) decrypted := make([]byte, len(decryptBytes)) blockMode.CryptBlocks(decrypted, decryptBytes) decrypted = pkcs5UnPadding(decrypted) return string(decrypted), nil } func pkcs5Padding(cipherText []byte, blockSize int) []byte { padding := blockSize - len(cipherText)%blockSize padText := bytes.Repeat([]byte{byte(padding)}, padding) return append(cipherText, padText...) } func pkcs5UnPadding(decrypted []byte) []byte { length := len(decrypted) unPadding := int(decrypted[length-1]) return decrypted[:(length - unPadding)] } func main() { data := "i am test data" key := []byte("1111111111111111") iv := "1111122211111111" encrypt, err := AesEncrypt(data, key, iv) if err != nil { panic(err) return } fmt.Println(encrypt) decrypt, err := AesDecrypt(encrypt, key, iv) if err != nil { panic(err) } fmt.Println(decrypt) } ...

十月 29, 2022 · overstarry

gRPC服务反射协议

本文主要介绍 gRPC 的服务反射协议和相关的应用。 介绍 gRPC 服务反射协议 (server reflection) 是在 gRPC 服务端定义的一个服务,它能提供该服务器端上可公开使用的 gRPC 服务的信息,简单的来说,就是服务反射向客户端提供了服务端注册的服务的信息。 因此客户端不需要预编译服务定义就能与服务端交互了。 客户端想要与服务端程序进行通信,必须要有所定义的服务信息,需要编译生产客户端存根,借助 gRPC 服务反射协议,我们就可以无需编译服务定义就能通信。 使用 该如何开启服务反射协议呢? 很简单,只需要通过一行代码即可开启: reflection.Register() package main import ( "context" "flag" "fmt" "log" "net" "google.golang.org/grpc" "google.golang.org/grpc/reflection" ecpb "google.golang.org/grpc/examples/features/proto/echo" hwpb "google.golang.org/grpc/examples/helloworld/helloworld" ) var port = flag.Int("port", 50051, "the port to serve on") // hwServer is used to implement helloworld.GreeterServer. type hwServer struct { hwpb.UnimplementedGreeterServer } // SayHello implements helloworld.GreeterServer func (s *hwServer) SayHello(ctx context.Context, in *hwpb.HelloRequest) (*hwpb.HelloReply, error) { return &hwpb.HelloReply{Message: "Hello " + in.Name}, nil } type ecServer struct { ecpb.UnimplementedEchoServer } func (s *ecServer) UnaryEcho(ctx context.Context, req *ecpb.EchoRequest) (*ecpb.EchoResponse, error) { return &ecpb.EchoResponse{Message: req.Message}, nil } func main() { flag.Parse() lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port)) if err != nil { log.Fatalf("failed to listen: %v", err) } fmt.Printf("server listening at %v\n", lis.Addr()) s := grpc.NewServer() // Register Greeter on the server. hwpb.RegisterGreeterServer(s, &hwServer{}) // Register RouteGuide on the same server. ecpb.RegisterEchoServer(s, &ecServer{}) // Register reflection service on gRPC server. reflection.Register(s) if err := s.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) } } 服务端开启服务反射协议后,就可以通过 gRPC CLI 工具来检查服务端了。这里就不多介绍了,接下来我们来看看服务反射协议在 kratos 中的使用。 ...

八月 27, 2022 · overstarry

Go发送邮件

介绍 电子邮件是一种用电子手段提供信息交换的通信方式,是互联网应用最广的服务。通过网络的电子邮件系统,用户可以以非常低廉的价格(不管发送到哪里,都只需负担网费)、非常快速的方式(几秒钟之内可以发送到世界上任何指定的目的地),与世界上任何一个角落的网络用户联系。 电子邮件在网络中的传输需要遵从一定的协议的,常用的电子邮件协议包括 SMTP,POP3,IMAP。电子邮件的创建和发送只涉及到 SMTP 协议,本文主要就是介绍 go 使用 SMTP 协议发生邮件。 使用 我们这里使用 https://github.com/jordan-wright/email 这个 pkg 来创建和发送邮件。 pkg 的安装这里就不过多介绍了。 我们知道邮箱使用SMTP/POP3/IMAP等协议从邮件服务器上拉取邮件。邮件并不是直接发送到邮箱的,而是邮箱请求拉取的。所以,我们需要配置SMTP/POP3/IMAP服务器。从头搭建固然可行,而且也有现成的开源库,但是比较麻烦。这里我使用 gmail ,配置流程就不过多介绍了(ps: Google 的安全性还是比较强的,设置了好久。 代码: package main import ( "log" "net/smtp" "github.com/jordan-wright/email" ) func main() { e := email.NewEmail() e.From = "[email protected]" e.To = []string{"[email protected]"} e.Subject = "这是主题" e.Text = []byte("测试邮件发送") err := e.Send("smtp.gmail.com:587", smtp.PlainAuth("", "[email protected]", "xx", "smtp.gmail.com")) if err != nil { log.Fatal(err) } } 过一会就顺利收到邮件了,有时候邮件会被当作垃圾邮件收入垃圾箱里,收不到时可以去垃圾箱看看。 参考 https://baike.baidu.com/item/%E7%94%B5%E5%AD%90%E9%82%AE%E4%BB%B6/111106

七月 16, 2022 · overstarry

Go模糊测试

本篇文章主要讲解在 go 语言中进行模糊测试的基础知识。通过模糊测试,随机数据会针对您的测试运行,以尝试找出漏洞或导致崩溃的输入。可以通过模糊测试发现的一些漏洞示例包括 SQL 注入、buffer overflow、拒绝服务和 cross-site scripting 攻击。 想要在 go 中使用模糊测试,需要安装 go1.18beta1 以上版本,具体的安装就不过多叙述了。 1 创建项目文件夹 我们创建一个名叫 fuzz-demo 的文件夹,并在其中创建一个名叫 main.go 的文件。 2 输入代码 在 main.go 中输入如下代码: package main import "fmt" func Reverse(s string) string { b := []byte(s) for i, j := 0, len(b)-1; i < len(b)/2; i, j = i+1, j-1 { b[i], b[j] = b[j], b[i] } return string(b) } func main() { input := "quick quick brown fox jumped over the lazy dog" rev := Reverse(input) doubleRev := Reverse(rev) fmt.Printf("原来: %q\n", input) fmt.Printf("反转: %q\n", rev) fmt.Printf("再反转: %q\n", doubleRev) } Reverse 函数的作用就是对字符串进行反转。 ...

三月 6, 2022 · overstarry