美文网首页
iris 抽奖实例4

iris 抽奖实例4

作者: 码农工号9527 | 来源:发表于2021-08-09 21:23 被阅读0次

    支付宝集福卡

    • 奖品是虚拟的5个福字,没数量限制
    • 先识别图片,确定福字的获得概率
    • 不存在线程安全问题
      在测试项目目录下创建main.go文件,内容如下:
    package main
    
    import (
        "fmt"
        "github.com/kataras/iris/v12"
        "github.com/kataras/iris/v12/mvc"
        "log"
        "math/rand"
        "os"
        "strconv"
        "strings"
        "time"
    )
    
    // 奖品对象
    type gift struct {
        id       int      //奖品标识
        name     string   //奖品名称
        pic      string   //奖品图片
        link     string   //奖品链接
        inuse    bool     // 是否使用中
        rate     int      //中将概率,万分之N,0~9999
        rateMin  int      //大于等于最小中奖编码
        rateMax  int      //小于等于最大中奖编码
    }
    
    // 最大号码
    const rateMax = 10
    
    var logger *log.Logger
    
    type lotterController struct {
        Ctx iris.Context
    }
    
    func main() {
        app := newApp()
        app.Run(iris.Addr(":8080"))
    }
    
    // 初始化奖品列表信息(管理后台来维护)
    func newGift() *[5]gift {
        /**
         * 表达式new(T)将创建一个T类型的匿名变量,所做的是为T类型的新值分配并清零一块内存空间,
         * 然后将这块内存空间的地址作为结果返回,而这个结果就是指向这个新的T类型值的指针值,
         * 返回的指针类型为*T。
         *
         * 我们只需使用new()函数,无需担心其内存的生命周期或怎样将其删除,因为Go语言的内存管理系统会帮我们打理一切。
         */
        giftlist := new([5]gift)
        // 1 实物大奖
        g1 := gift{
            id:      1,
            name:    "富强福",
            pic:     "富强福.jpg",
            link:    "",
            inuse:   true,
            rate:    4,
            rateMin: 0,
            rateMax: 0,
        }
        giftlist[0] = g1
        // 2 实物小奖
        g2 := gift{
            id:      2,
            name:    "和谐福",
            pic:     "和谐福.jpg",
            link:    "",
            inuse:   true,
            rate:    3,
            rateMin: 0,
            rateMax: 0,
        }
        giftlist[1] = g2
        // 3 虚拟券,相同的编码
        g3 := gift{
            id:      3,
            name:    "友善福",
            pic:     "友善福.jpg",
            link:    "",
            inuse:   true,
            rate:    2,
            rateMin: 0,
            rateMax: 0,
        }
        giftlist[2] = g3
        // 4 虚拟券,不相同的编码
        g4 := gift{
            id:      4,
            name:    "爱国福",
            pic:     "爱国福.jpg",
            link:    "",
            inuse:   true,
            rate:    1,
            rateMin: 0,
            rateMax: 0,
        }
        giftlist[3] = g4
        // 5 虚拟币
        g5 := gift{
            id:      5,
            name:    "敬业福",
            pic:     "敬业福.jpg",
            link:    "",
            inuse:   true,
            rate:    0,
            rateMin: 0,
            rateMax: 0,
        }
        giftlist[4] = g5
        return giftlist
    }
    
    // 根据概率,计算好的奖品信息列表
    func giftRate(rate string) *[5]gift {
        giftlist := newGift()
        rates := strings.Split(rate, ",")
        ratesLen := len(rates)
        // 整理奖品数据,把rateMin,rateMax根据rate进行编排
        rateStart := 0
        for i, data := range giftlist {
            if !data.inuse {
                continue
            }
            grate := 0
            if i < ratesLen { // 避免数组越界
                grate, _ = strconv.Atoi(rates[i])
            }
            giftlist[i].rate = grate
            giftlist[i].rateMin = rateStart
            giftlist[i].rateMax = rateStart + grate
            if giftlist[i].rateMax >= rateMax {
                // 号码达到最大值,分配的范围重头再来
                giftlist[i].rateMax = rateMax
                rateStart = 0
            } else {
                rateStart += grate
            }
        }
        fmt.Printf("giftlist=%v\n", giftlist)
        return giftlist
    }
    
    // 初始化日志信息
    func initLog() {
        f, _ := os.Create("/var/log/lottery_demo.log")
        logger = log.New(f, "", log.Ldate|log.Lmicroseconds)
    }
    
    func newApp() *iris.Application {
        app := iris.New()
        mvc.New(app.Party("/")).Handle(&lotteryController{})
        // 初始化日志信息
        initLog()
        return app
    }
    
    // 抽奖的控制器
    type lotteryController struct {
        Ctx iris.Context
    }
    
    // GET http://localhost:8080/?rate=4,3,2,1,0
    func (c *lotteryController) Get() string {
        rate := c.Ctx.URLParamDefault("rate", "4,3,2,1,0")
        giftlist := giftRate(rate)
        return fmt.Sprintf("%v\n", giftlist)
    }
    
    // GET http://localhost:8080/lucky?uid=1&rate=4,3,2,1,0
    func (c *lotteryController) GetLucky() map[string]interface{} {
        uid, _ := c.Ctx.URLParamInt("uid")
        rate := c.Ctx.URLParamDefault("rate", "4,3,2,1,0")
        code := luckyCode()
        fmt.Printf("code=%v\n", code)
        ok := false
        result := make(map[string]interface{})
        result["success"] = ok
        giftlist := giftRate(rate)
        for _, data := range giftlist {
            if !data.inuse {
                continue
            }
            if data.rateMin <= int(code) && data.rateMax >= int(code) {
                // 中奖了,抽奖编码在奖品中奖编码范围内
                ok = true
                sendData := data.pic
    
                if ok {
                    // 中奖后,成功得到奖品(发奖成功)
                    // 生成中奖纪录
                    saveLuckyData(uid, code, data.id, data.name, data.link, sendData)
                    result["success"] = ok
                    result["uid"] = uid
                    result["id"] = data.id
                    result["name"] = data.name
                    result["link"] = data.link
                    result["data"] = sendData
                    break
                }
            }
        }
    
        return result
    }
    
    // 抽奖编码
    func luckyCode() int32 {
        seed := time.Now().UnixNano()                                 // rand内部运算的随机数
        code := rand.New(rand.NewSource(seed)).Int31n(int32(rateMax)) // rand计算得到的随机数
        return code
    }
    
    // 记录用户的获奖记录
    func saveLuckyData(uid int, code int32, id int, name, link, sendData string) {
        logger.Printf("lucky, uid=%d, code=%d, gift=%d, name=%s, link=%s, data=%s ", uid, code, id, name, link, sendData)
    }
    

    首页:


    抽奖:


    压力测试:

    [root@localhost wrk]# > /var/log/lottery_demo.log 
    [root@localhost wrk]# wc -l /var/log/lottery_demo.log 
    0 /var/log/lottery_demo.log
    [root@localhost wrk]# /usr/local/bin/wrk -t15 -c15 -d10 http://localhost:8080/lucky
    Running 10s test @ http://localhost:8080/lucky
      15 threads and 15 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     2.73ms    2.38ms  25.83ms   83.99%
        Req/Sec   422.48     61.82   700.00     68.93%
      63603 requests in 10.10s, 13.83MB read
    Requests/sec:   6297.95
    Transfer/sec:      1.37MB
    [root@localhost wrk]# /usr/local/bin/wrk -t15 -c15 -d10 http://localhost:8080/lucky
    Running 10s test @ http://localhost:8080/lucky
      15 threads and 15 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     2.59ms    2.23ms  28.49ms   83.08%
        Req/Sec   440.23     58.14   673.00     69.73%
      66240 requests in 10.08s, 14.40MB read
    Requests/sec:   6569.48
    Transfer/sec:      1.43MB
    

    发现qps比上一个抽奖低了一倍多,是因为每一次都要进入到抽奖里面的指针逻辑,开销比较大,而没有线程安全性问题是因为没有共享变量,也没有库存,操作的giftlist每次都是从内存中开辟出来的新的空间,然后返回的。

    相关文章

      网友评论

          本文标题:iris 抽奖实例4

          本文链接:https://www.haomeiwen.com/subject/ctqtbltx.html