【go/实践】(二)http服务器上使用redis

文章目录

  • 说在前面
  • 实验要求
  • 安装Redis
  • 安装Redis Go插件
  • 代码
  • 实验结果

说在前面

  • 实验环境:【go/vscode】远程环境搭建(离线版/gopls版)
  • 客户端环境:chrome 84.0.4

实验要求

  • 在上一节的基础上,要求服务器能够存储客户请求的值,同时添加新增需求:
    1. /all:显示所有记录(包含用户的IP、请求时间、请求内容)
    2. /clean:清除所有记录

安装Redis

  • 详见Linux下Redis的安装和部署

安装Redis Go插件

  • 详见Redigo–Go连接Redis

代码

  • 关于连接池
    redigo连接池不入坑
  • 关于Request.FormValue
    这里
  • 关于信号
    这里
  • 关于channel,<-
    这里
package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/garyburd/redigo/redis"
)

var pool *redis.Pool
// redis List 用的key名
var listkey = "ListKey"

// 连接池
func newPool(server, password string) *redis.Pool {
	return &redis.Pool{
		MaxIdle:     64,
		MaxActive:   1000,
		IdleTimeout: 240 * time.Second,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", server)
			if err != nil {
				return nil, err
			}
			return c, err
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			if time.Since(t) < time.Minute {
				return nil
			}
			_, err := c.Do("PING")
			return err
		},
	}
}

func RecordHandler(w http.ResponseWriter, r *http.Request) {
    // 获取text的内容
	values := r.FormValue("text")
	if values == "" {
		fmt.Fprintf(w, "try to use \"/add?text=xxx!\"")
		return
	}
	// 返回text内容
	fmt.Fprintf(w, values)
	// 记录IP:时间:text
	temp_values := fmt.Sprintf("%s:%s:%s", r.RemoteAddr, GetDateFormat(), values)
	// 连接池不为空
	if pool != nil {
		// 获取连接
		conn := pool.Get()
		defer conn.Close()
		// 将该条记录放入redis list结构中
		conn.Do("rpush", listkey, temp_values)
	}
}

func EchoAllHandler(w http.ResponseWriter, r *http.Request) {
	if pool != nil {
		// 获取连接
		conn := pool.Get()
		defer conn.Close()

		// 使用LLEN 命令获取list长度
		listLen, err := redis.Int(conn.Do("LLEN", listkey))
		if err != nil {
			fmt.Println("Redis LLEN error!")
			return
		}

		// 获取list的所有数据
		values, err := redis.MultiBulk(conn.Do("LRANGE", listkey, 0, listLen))
		items, err := redis.Strings(values, nil)
		for _, s := range items {
			fmt.Fprintf(w, s+"\n")
		}

	}

}

func ClearAllHandler(w http.ResponseWriter, r *http.Request) {
	if pool != nil {
		conn := pool.Get()
		defer conn.Close()

		// 删除该key,即可删除所有记录
		_, err := conn.Do("DEL", listkey)
		if err != nil {
			fmt.Println("Redis DEL error!")
			return
		} else {
			fmt.Fprintf(w, "clear success!")
		}
	}
}

// 时间戳转年月日 时分秒
func GetDateFormat() string {
	return time.Now().Format("2006-01-02 15:04:05")
}

func main() {
	pool = newPool("localhost:6379", "")

	mux := http.NewServeMux()
	// 注册
	mux.HandleFunc("/add", RecordHandler)
	mux.HandleFunc("/all", EchoAllHandler)
	mux.HandleFunc("/clean", ClearAllHandler)

	server := &http.Server{
		Addr:    ":8081",
		Handler: mux,
	}

	// 创建系统信号接收器
	done := make(chan os.Signal, 1)
	signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
	go func() {
		<-done

		if err := server.Shutdown(context.Background()); err != nil {
			log.Fatal("Shutdown server:", err)
		}
	}()

	err := server.ListenAndServe()
	if err != nil {
		if err == http.ErrServerClosed {
			log.Print("Server closed under request")
		} else {
			log.Fatal("Server closed unexpected")
		}
	}
}

实验结果

【go/实践】(二)http服务器上使用redis_第1张图片
【go/实践】(二)http服务器上使用redis_第2张图片

你可能感兴趣的:(Go)