天天看點

不要網上亂拷貝代碼了!一段網上找的代碼把公司伺服器崩了!

雲栖号資訊:【 點選檢視更多行業資訊

在這裡您可以找到不同行業的第一手的上雲資訊,還在等什麼,快來!

碰到一個需求,給服某些要求的玩家的發送道具獎勵,獎勵的數量根據離線的天數計算。

這個需求實作起來很簡單,隻需要在玩家上線的時候計算上次離線時間和目前時間間隔的天數,然後根據策劃的算法,計算出道具種類與數量,發一封郵件給玩家就可以了。

計算兩個時間間隔天數的函數沒有現成的,自己又懶得寫,就上谷歌搜了下,選了第一條結果,代碼如下

public static int differentDays(Date date1,Date date2)
    {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
       int day1= cal1.get(Calendar.DAY_OF_YEAR);
        int day2 = cal2.get(Calendar.DAY_OF_YEAR);

        int year1 = cal1.get(Calendar.YEAR);
        int year2 = cal2.get(Calendar.YEAR);
        if(year1 != year2)   //同一年
        {
            int timeDistance = 0 ;
            for(int i = year1 ; i < year2 ; i ++)
            {
                if(i%4==0 && i%100!=0 || i%400==0)    //閏年
                {
                    timeDistance += 366;
                }
                else    //不是閏年
                {
                    timeDistance += 365;
                }
            }

            return timeDistance + (day2-day1) ;
        }
        else    //不同年
        {
            System.out.println("判斷day2 - day1 : " + (day2-day1));
            return day2-day1;
        }
    }           

代碼來源:

https://www.cnblogs.com/0201zcr/p/5000977.html

把代碼複制到項目裡,調試下,發現沒問題就直接用了,畢竟谷歌結果第一名,放心。

這段代碼跑了幾個月一直沒問題,但是到了2020-1-1日那天,有玩家回報收到了幾百封獎勵郵件,高興壞了,但是出于對遊戲的熱愛,還是通知了營運人員。

營運把bug回報到伺服器這邊後我開始排查,百思不得其解的是最近幾天都沒有更新伺服器, 而前幾天伺服器都穩穩地,怎麼突然就出BUG了呢。

接下來就是分析玩家資料,結合代碼邏輯确定問題所在,最終根據BUG的表現排除了所有可能性後,發現唯一可能出問題的地方就是那個網上複制過來的計算天數差的函數。

根據調試發現,這個函數在兩個日期參數是不同的年份并且第一個日期大于第二個日期的時候,會傳回一個錯誤的結果

比如

differentDays("2020-1-1","2019-12-25")           

理論上這麼調用正确的結果是 -7,但是因為函數有bug,調用結果是 358

于是本來不用發獎勵,因為這種特殊情況一下子發出去358份,嚴重影響了遊戲某類道具的平衡性。

至于補救方式就是統計名單,把發出去但還沒有用掉的道具回收,用掉的就當福利,然後再發公告道歉,再送些其他物品彌補。

也幸好補救的及時,要是這些道具收不回來,遊戲營運的政策都要大變了,我特麼肯定沒好果子吃了。

是以千萬别在網上複制來路不明的代碼亂用,如果真的要用,必須反複測試,否則哪一天突然暴雷有你受的。

改用Java8的日期庫修複了BUG

public static int differentDays(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            throw new RuntimeException("日期不能為空");
        }
        LocalDate localDate1 = date2LocalDate(date1);
        LocalDate localDate2 = date2LocalDate(date2);
        return Generic.long2int(localDate1.until(localDate2, ChronoUnit.DAYS));
    }

    public static LocalDate date2LocalDate(Date date) {
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDate localDate = instant.atZone(zoneId).toLocalDate();
        return localDate;
    }           

【雲栖号線上課堂】每天都有産品技術專家分享!

課程位址:

https://yqh.aliyun.com/zhibo

立即加入社群,與專家面對面,及時了解課程最新動态!

【雲栖号線上課堂 社群】

https://c.tb.cn/F3.Z8gvnK

原文釋出時間:2020-05-22

本文作者:陳宏鴻

本文來自:“

網際網路架構師 微信公衆号

”,了解相關資訊可以關注“

網際網路架構師