open-falcon

Open-falcon是小米運(yùn)維團(tuán)隊從互聯(lián)網(wǎng)公司的需求出發(fā),根據(jù)多年的運(yùn)維經(jīng)驗瞻坝,結(jié)合SRE钧椰、SA粹断、DEVS的使用經(jīng)驗和反饋,開發(fā)的一套面向互聯(lián)網(wǎng)的企業(yè)級開源監(jiān)控產(chǎn)品嫡霞。

官方手冊

架構(gòu)圖

image

組件介紹

  • agent

    agent用于采集機(jī)器負(fù)載監(jiān)控指標(biāo)瓶埋,比如cpu.idle、load.1min诊沪、disk.io.util等等养筒,每隔60秒push給Transfer。agent與Transfer建立了長連接端姚,數(shù)據(jù)發(fā)送速度比較快晕粪,agent提供了一個http接口/v1/push用于接收用戶手工push的一些數(shù)據(jù),然后通過長連接迅速轉(zhuǎn)發(fā)給Transfer渐裸。

    配置說明

      {
          "debug": true, # 控制一些debug信息的輸出巫湘,生產(chǎn)環(huán)境通常設(shè)置為false
          "hostname": "", # agent采集了數(shù)據(jù)發(fā)給transfer,endpoint就設(shè)置為了hostname昏鹃,默認(rèn)通過`hostname`獲取尚氛,如果配置中配置了hostname,就用配置中的
          "ip": "", # agent與hbs心跳的時候會把自己的ip地址發(fā)給hbs盆顾,agent會自動探測本機(jī)ip怠褐,如果不想讓agent自動探測畏梆,可以手工修改該配置
          "plugin": {
              "enabled": false, # 默認(rèn)不開啟插件機(jī)制
              "dir": "./plugin", # 把放置插件腳本的git repo clone到這個目錄
              "git": "https://github.com/open-falcon/plugin.git", # 放置插件腳本的git repo地址
              "logs": "./logs" # 插件執(zhí)行的log您宪,如果插件執(zhí)行有問題,可以去這個目錄看log
          },
          "heartbeat": {
              "enabled": true, # 此處enabled要設(shè)置為true
              "addr": "127.0.0.1:6030", # hbs的地址奠涌,端口是hbs的rpc端口
              "interval": 60, # 心跳周期宪巨,單位是秒
              "timeout": 1000 # 連接hbs的超時時間,單位是毫秒
          },
          "transfer": {
              "enabled": true, # 此處enabled要設(shè)置為true
              "addrs": [
                  "127.0.0.1:8433",
                  "127.0.0.1:8433"
              ], # transfer的地址溜畅,端口是transfer的rpc端口, 可以支持寫多個transfer的地址捏卓,agent會保證HA
              "interval": 60, # 采集周期,單位是秒,即agent一分鐘采集一次數(shù)據(jù)發(fā)給transfer
              "timeout": 1000 # 連接transfer的超時時間怠晴,單位是毫秒
          },
          "http": {
              "enabled": true, # 是否要監(jiān)聽http端口
              "listen": ":1988" # 如果監(jiān)聽的話遥金,監(jiān)聽的地址
          },
          "collector": {
              "ifacePrefix": ["eth", "em"] # 默認(rèn)配置只會采集網(wǎng)卡名稱前綴是eth、em的網(wǎng)卡流量蒜田,配置為空就會采集所有的稿械,lo的也會采集〕逶粒可以從/proc/net/dev看到各個網(wǎng)卡的流量信息
          },
          "ignore": { # 默認(rèn)采集了200多個metric美莫,可以通過ignore設(shè)置為不采集
              "cpu.busy": true,
              "mem.swapfree": true
          }
      }
    
  • hbs(Heartbeat Server)
    心跳服務(wù)器,公司所有agent都會連到HBS梯捕,每分鐘發(fā)一次心跳請求厢呵。

    agent會定期從hbs中拉取配置,比如:需要運(yùn)行plugins的目錄傀顾;

    judge模塊也會定期從hbs去獲取告警策略襟铭;

  • transfer
    transfer是數(shù)據(jù)轉(zhuǎn)發(fā)服務(wù)。它接收agent上報的數(shù)據(jù)短曾,然后按照哈希規(guī)則進(jìn)行數(shù)據(jù)分片蝌矛、并將分片后的數(shù)據(jù)分別push給graph&judge等組件。

    配置說明

      debug: true/false, 如果為true错英,日志中會打印debug信息
    
      http
          - enable: true/false, 表示是否開啟該http端口入撒,該端口為控制端口,主要用來對transfer發(fā)送控制命令椭岩、統(tǒng)計命令茅逮、debug命令等
          - listen: 表示監(jiān)聽的http端口
    
      rpc
          - enable: true/false, 表示是否開啟該jsonrpc數(shù)據(jù)接收端口, Agent發(fā)送數(shù)據(jù)使用的就是該端口
          - listen: 表示監(jiān)聽的http端口
    
      socket #即將被廢棄,請避免使用
          - enable: true/false, 表示是否開啟該telnet方式的數(shù)據(jù)接收端口,這是為了方便用戶一行行的發(fā)送數(shù)據(jù)給transfer
          - listen: 表示監(jiān)聽的http端口
    
      judge
          - enable: true/false, 表示是否開啟向judge發(fā)送數(shù)據(jù)
          - batch: 數(shù)據(jù)轉(zhuǎn)發(fā)的批量大小判哥,可以加快發(fā)送速度献雅,建議保持默認(rèn)值
          - connTimeout: 單位是毫秒,與后端建立連接的超時時間塌计,可以根據(jù)網(wǎng)絡(luò)質(zhì)量微調(diào)挺身,建議保持默認(rèn)
          - callTimeout: 單位是毫秒,發(fā)送數(shù)據(jù)給后端的超時時間锌仅,可以根據(jù)網(wǎng)絡(luò)質(zhì)量微調(diào)章钾,建議保持默認(rèn)
          - pingMethod: 后端提供的ping接口,用來探測連接是否可用热芹,必須保持默認(rèn)
          - maxConns: 連接池相關(guān)配置贱傀,最大連接數(shù),建議保持默認(rèn)
          - maxIdle: 連接池相關(guān)配置伊脓,最大空閑連接數(shù)府寒,建議保持默認(rèn)
          - replicas: 這是一致性hash算法需要的節(jié)點副本數(shù)量,建議不要變更,保持默認(rèn)即可
          - cluster: key-value形式的字典株搔,表示后端的judge列表剖淀,其中key代表后端judge名字,value代表的是具體的ip:port
    
      graph
          - enable: true/false, 表示是否開啟向graph發(fā)送數(shù)據(jù)
          - batch: 數(shù)據(jù)轉(zhuǎn)發(fā)的批量大小纤房,可以加快發(fā)送速度祷蝌,建議保持默認(rèn)值
          - connTimeout: 單位是毫秒,與后端建立連接的超時時間帆卓,可以根據(jù)網(wǎng)絡(luò)質(zhì)量微調(diào)巨朦,建議保持默認(rèn)
          - callTimeout: 單位是毫秒,發(fā)送數(shù)據(jù)給后端的超時時間剑令,可以根據(jù)網(wǎng)絡(luò)質(zhì)量微調(diào)糊啡,建議保持默認(rèn)
          - pingMethod: 后端提供的ping接口,用來探測連接是否可用吁津,必須保持默認(rèn)
          - maxConns: 連接池相關(guān)配置棚蓄,最大連接數(shù),建議保持默認(rèn)
          - maxIdle: 連接池相關(guān)配置碍脏,最大空閑連接數(shù)梭依,建議保持默認(rèn)
          - replicas: 這是一致性hash算法需要的節(jié)點副本數(shù)量,建議不要變更典尾,保持默認(rèn)即可
          - cluster: key-value形式的字典役拴,表示后端的graph列表,其中key代表后端graph名字钾埂,value代表的是具體的ip:port(多個地址用逗號隔開, transfer會將同一份數(shù)據(jù)發(fā)送至各個地址河闰,利用這個特性可以實現(xiàn)數(shù)據(jù)的多重備份)
    
      tsdb
          - enabled: true/false, 表示是否開啟向open tsdb發(fā)送數(shù)據(jù)
          - batch: 數(shù)據(jù)轉(zhuǎn)發(fā)的批量大小,可以加快發(fā)送速度
          - connTimeout: 單位是毫秒褥紫,與后端建立連接的超時時間姜性,可以根據(jù)網(wǎng)絡(luò)質(zhì)量微調(diào),建議保持默認(rèn)
          - callTimeout: 單位是毫秒髓考,發(fā)送數(shù)據(jù)給后端的超時時間部念,可以根據(jù)網(wǎng)絡(luò)質(zhì)量微調(diào),建議保持默認(rèn)
          - maxConns: 連接池相關(guān)配置氨菇,最大連接數(shù)儡炼,建議保持默認(rèn)
          - maxIdle: 連接池相關(guān)配置,最大空閑連接數(shù)门驾,建議保持默認(rèn)
          - retry: 連接后端的重試次數(shù)和發(fā)送數(shù)據(jù)的重試次數(shù)
          - address: tsdb地址或者tsdb集群vip地址, 通過tcp連接tsdb.
    
  • judge
    Judge用于告警判斷射赛,agent將數(shù)據(jù)push給Transfer,Transfer不但會轉(zhuǎn)發(fā)給Graph組件來繪圖,還會轉(zhuǎn)發(fā)給Judge用于判斷是否觸發(fā)告警。

    Judge監(jiān)聽了一個http端口笋轨,提供了一個http接口:/count,訪問之秆麸,可以得悉當(dāng)前Judge實例處理了多少數(shù)據(jù)量。

  • graph
    graph是存儲繪圖數(shù)據(jù)的組件及汉。graph組件 接收transfer組件推送上來的監(jiān)控數(shù)據(jù)沮趣,同時處理query組件的查詢請求、返回繪圖數(shù)據(jù)坷随。

  • gateway
    站在client端的角度房铭,gateway和transfer提供了完全一致的功能和接口。只有遇到網(wǎng)絡(luò)分區(qū)的情況時温眉,才有必要使用gateway組件缸匪。

    image

  • alarm
    alarm模塊是處理報警event的,judge產(chǎn)生的報警event寫入redis类溢,alarm從redis讀取處理;

  • aggregator
    集群聚合模塊凌蔬。聚合某集群下的所有機(jī)器的某個指標(biāo)的值,提供一種集群視角的監(jiān)控體驗闯冷。

    配置說明

    {
      "debug": true,
      "http": {
          "enabled": true,
          "listen": "0.0.0.0:6055"
      },
      "database": {
          "addr": "root:@tcp(127.0.0.1:3306)/falcon_portal?loc=Local&parseTime=true",
          "idle": 10,
          "ids": [1,-1], # aggregator模塊可以部署多個實例砂心,這個配置表示當(dāng)前實例要處理的數(shù)據(jù)庫中cluster表的id范圍
          "interval": 55
      },
      "api": {
          "hostnames": "http://127.0.0.1:5050/api/group/%s/hosts.json", # 注意修改為你的portal的ip:port
          "push": "http://127.0.0.1:6060/api/push", # 注意修改為你的transfer的ip:port
          "graphLast": "http://127.0.0.1:9966/graph/last" # 注意修改為你的query的ip:port
      }
    }
    
  • nodata
    nodata用于檢測監(jiān)控數(shù)據(jù)的上報異常。nodata和實時報警judge模塊協(xié)同工作蛇耀,過程為: 配置了nodata的采集項超時未上報數(shù)據(jù)辩诞,nodata生成一條默認(rèn)的模擬數(shù)據(jù);用戶配置相應(yīng)的報警策略纺涤,收到mock數(shù)據(jù)就產(chǎn)生報警躁倒。采集項上報異常檢測,作為judge模塊的一個必要補(bǔ)充洒琢,能夠使judge的實時報警功能更加可靠秧秉、完善。

部署

  • open-falcon plus

    安裝redis, mysql

    yum install -y redis
    yum install -y mysql-server
    

    編譯各個模塊

    mkdir -p $GOPATH/src/github.com/open-falcon
    cd $GOPATH/src/github.com/open-falcon
    git clone https://github.com/open-falcon/falcon-plus.git
    
    cd $GOPATH/src/github.com/open-falcon/falcon-plus/scripts/mysql/db_schema/
    mysql -h 127.0.0.1 -u root -p < uic-db-schema.sql
    mysql -h 127.0.0.1 -u root -p < portal-db-schema.sql
    mysql -h 127.0.0.1 -u root -p < graph-db-schema.sql
    mysql -h 127.0.0.1 -u root -p < dashboard-db-schema.sql
    mysql -h 127.0.0.1 -u root -p < alarms-db-schema.sql
    
    cd $GOPATH/src/github.com/open-falcon/falcon-plus/
    
    # make all modules
    make all
    
    # make specified module
    make agent
    
    # pack all modules
    make pack
    
    export WorkDir="$HOME/open-falcon"
    mkdir -p $WorkDir
    tar -xzvf open-falcon-vx.x.x.tar.gz -C $WorkDir
    cd $WorkDir
    
    cd $WorkDir
    ./open-falcon start
    
    # check modules status
    ./open-falcon check
    
  • dashboard

    通過http://xx:8081/訪問

    git clone https://github.com/open-falcon/dashboard.git
    
    docker build -t falcon-dashboard:v1.0 .
    
    docker run -itd --name falcon-dashboard --net host \
        -e API_ADDR=http://127.0.0.1:8080/api/v1 \
        -e PORTAL_DB_HOST=127.0.0.1 \
        -e PORTAL_DB_PORT=3306 \
        -e PORTAL_DB_USER=root \
        -e PORTAL_DB_PASS=xx\
        -e PORTAL_DB_NAME=falcon_portal \
        -e ALARM_DB_PASS=xx \
        -e ALARM_DB_HOST=127.0.0.1 \
        -e ALARM_DB_PORT=3306 \
        -e ALARM_DB_USER=root \
        -e ALARM_DB_NAME=alarms \
        falcon-dashboard:v1.0
    
  • 郵件發(fā)送接口(可選)

    git clone https://github.com/open-falcon/mail-provider.git
    
    cd $GOPATH/src/github.com/open-falcon/nodata
    go get ./...
    ./control build
    ./contorl pack
    

    使用方法:

    curl http://$ip:4000/sender/mail -d "tos=a@a.com,b@b.com&subject=xx&content=yy"
    

open-falcon的設(shè)計理念

  • 數(shù)據(jù)模型

    Open-Falcon衰抑,采用和OpenTSDB相似的數(shù)據(jù)格式:metric象迎、endpoint加多組key value tags,舉兩個例子:

      {
          metric: load.1min,
          endpoint: open-falcon-host,
          tags: srv=falcon,idc=aws-sgp,group=az1,
          value: 1.5,
          timestamp: `date +%s`,
          counterType: GAUGE,
          step: 60
      }
      {
          metric: net.port.listen,
          endpoint: open-falcon-host,
          tags: port=3306,
          value: 1,
          timestamp: `date +%s`,
          counterType: GAUGE,
          step: 60
      }
    
    • metric: 最核心的字段呛踊,代表這個采集項具體度量的是什么, 比如是cpu_idle呢砾淌,還是memory_free, 還是qps

    • endpoint: 標(biāo)明Metric的主體(屬主),比如metric是cpu_idle谭网,那么Endpoint就表示這是哪臺機(jī)器的cpu_idle

    • timestamp: 表示匯報該數(shù)據(jù)時的unix時間戳汪厨,注意是整數(shù),代表的是秒

    • value: 代表該metric在當(dāng)前時間點的值愉择,float64

    • step: 表示該數(shù)據(jù)采集項的匯報周期劫乱,這對于后續(xù)的配置監(jiān)控策略很重要织中,必須明確指定。

    • counterType: 只能是COUNTER或者GAUGE二選一衷戈,前者表示該數(shù)據(jù)采集項為計時器類型狭吼,后者表示其為原值 (注意大小寫)

      • GAUGE:即用戶上傳什么樣的值,就原封不動的存儲
      • COUNTER:指標(biāo)在存儲和展現(xiàn)的時候殖妇,會被計算為speed刁笙,即(當(dāng)前值 - 上次值)/ 時間間隔
    • tags: 一組逗號分割的鍵值對, 對metric進(jìn)一步描述和細(xì)化, 可以是空字符串. 比如idc=lg,比如service=xbox等谦趣,多個tag之間用逗號

  • 數(shù)據(jù)采集

    服務(wù)監(jiān)控數(shù)據(jù)

    服務(wù)的監(jiān)控指標(biāo)采集腳本疲吸,通常都是跟著服務(wù)的code走的,服務(wù)上線或者擴(kuò)容前鹅,這個腳本也跟著上線或者擴(kuò)容摘悴,服務(wù)下線,這個采集腳本也要相應(yīng)下線嫡纠。公司里Java的項目有不少烦租,研發(fā)那邊就提供了一個通用jar包,只要引入這個jar包除盏,就可以自動采集接口的調(diào)用次數(shù)叉橱、延遲時間等數(shù)據(jù)。然后將采集到的數(shù)據(jù)push給監(jiān)控者蠕,一分鐘push一次窃祝。目前falcon的agent提供了一個簡單的http接口,這個jar包采集到數(shù)據(jù)之后是post給本機(jī)agent踱侣。向agent推送數(shù)據(jù)的一個簡單例子粪小,如下:

    curl -X POST -d '[{"metric": "qps", "endpoint": "open-falcon-graph01.bj", "timestamp": 1431347802, "step": 60,"value": 9,"counterType": "GAUGE","tags": "project=falcon,module=graph"}]' http://127.0.0.1:1988/v1/push
    
    

    各種開源軟件的監(jiān)控

    這都是大用戶,比如DBA自己寫一些采集腳本抡句,連到各個MySQL實例上去采集數(shù)據(jù)探膊,完事直接調(diào)用server端的jsonrpc(transfer 提供接口)匯報數(shù)據(jù),一分鐘一次待榔,每次甚至push幾十萬條數(shù)據(jù)逞壁,比較好的發(fā)送方式是500條數(shù)據(jù)做一個batch,別幾十萬數(shù)據(jù)一次性發(fā)送锐锣。

  • plugin

    Plugin可以看做是對agent功能的擴(kuò)充腌闯。對于業(yè)務(wù)系統(tǒng)的監(jiān)控指標(biāo)采集,最好不要做成plugin雕憔,而是把采集腳本放到業(yè)務(wù)程序發(fā)布包中姿骏,隨著業(yè)務(wù)代碼上線而上線,隨著業(yè)務(wù)代碼升級而升級斤彼,這樣會比較容易管理分瘦。

    編寫采集腳本

    用什么語言寫沒關(guān)系蘸泻,只要目標(biāo)機(jī)器上有運(yùn)行環(huán)境就行,腳本本身要有可執(zhí)行權(quán)限擅腰。采集到數(shù)據(jù)之后直接打印到stdout即可蟋恬,agent會截獲并push給server翁潘。

    使用

    1. 先將腳本push到git
    2. curl下agent的接口去獲取plugins
    curl http://ip:1988/plugin/update
    
    1. 在dashborad的HostGroup中綁定plugins目錄趁冈,因為不是所有的plugins都需要在該機(jī)器上執(zhí)行,這里通過目錄來區(qū)分拜马;agent會通過hbs的接口去獲取配置渗勘;
  • Tag和HostGroup

    tag其實是一種分組方式,當(dāng)push的數(shù)據(jù)無法標(biāo)記tag(比如:我們agent采集的cpu, memory, net等信息)俩莽,那我們就要將這些數(shù)據(jù)手工分組了旺坠,這就是HostGroup;

    HostGroup實際上是對endpoint的一種分組;

    想象一下扮超,一條數(shù)據(jù)push上來取刃,我們應(yīng)該怎么判斷這條數(shù)據(jù)是否該報警呢?首先我們需要找到這條數(shù)據(jù)的expression,無非就是看expression中的tag是否是當(dāng)前push上來數(shù)據(jù)的子集;當(dāng)沒有tag的數(shù)據(jù)呢出刷? push上來的數(shù)據(jù)肯定有endpoint, 我們可以根據(jù)endpoint查看是哪個HostGroup, HostGroup又是跟template綁定璧疗,template中又會配置告警策略;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末馁龟,一起剝皮案震驚了整個濱河市崩侠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌坷檩,老刑警劉巖却音,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異矢炼,居然都是意外死亡系瓢,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門句灌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來夷陋,“玉大人,你說我怎么就攤上這事涯塔〖〉荆” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵匕荸,是天一觀的道長爹谭。 經(jīng)常有香客問我,道長榛搔,這世上最難降的妖魔是什么诺凡? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任东揣,我火速辦了婚禮,結(jié)果婚禮上腹泌,老公的妹妹穿的比我還像新娘嘶卧。我一直安慰自己,他們只是感情好凉袱,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布芥吟。 她就那樣靜靜地躺著,像睡著了一般专甩。 火紅的嫁衣襯著肌膚如雪钟鸵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天涤躲,我揣著相機(jī)與錄音棺耍,去河邊找鬼。 笑死种樱,一個胖子當(dāng)著我的面吹牛蒙袍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播嫩挤,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼害幅,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了俐镐?” 一聲冷哼從身側(cè)響起矫限,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎佩抹,沒想到半個月后叼风,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡棍苹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年无宿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片枢里。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡孽鸡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出栏豺,到底是詐尸還是另有隱情彬碱,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布奥洼,位于F島的核電站巷疼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏灵奖。R本人自食惡果不足惜嚼沿,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一估盘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧骡尽,春花似錦遣妥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至辨图,卻和暖如春班套,著一層夾襖步出監(jiān)牢的瞬間肢藐,已是汗流浹背故河。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留吆豹,地道東北人鱼的。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像痘煤,于是被迫代替她去往敵國和親凑阶。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容