RocketMQ 入門:(整合 springboot) 單機部署 & 集群部署

springBoot+RocketMQ 示例

創建 springboot 項目或者在自己的項目中的 pom 文件中引入依賴

<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-spring-boot</artifactId>
    <version>2.2.0</version>
</dependency>

引入依賴之后我們需要配置一下 rocketmq 的配置信息,打開我們的 application.yml

rocketmq:
 name-server: 8.***.***.**:9876;  #nameserver IP地址
 producer:
   group: TEST_GROUP # 指定group
   send-message-timeout: 3000 # 消息發送超時時長,默認3s
   retry-times-when-send-failed: 3 # 同步發送消息失敗重試次數,默認2
   retry-times-when-send-async-failed: 3 # 異步發送消息失敗重試次數,默認2

定義生產者

首先自定義一個生產者。用來投遞消息。

@Slf4j
@Component
public class MQProducerService {

   // 直接注入使用,用于發送消息到broker服務器
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

   /**
     * 普通發送
     */
    public void send(String body,String topic) {
        rocketMQTemplate.convertAndSend(topic , body);
//        rocketMQTemplate.send(topic + ":tag1", MessageBuilder.withPayload(user).build()); // 等價于上面一行
    }

    /**
     * 發送同步消息(阻塞當前線程,等待broker響應發送結果,這樣不太容易丟失消息)
     * (msgBody也可以是對象,sendResult為返回的發送結果)
     */
    public SendResult sendMsg(String body,String topic) {
        SendResult sendResult = rocketMQTemplate.syncSend(topic, MessageBuilder.withPayload(body).build());
        log.info("【sendMsg】sendResult={}", JSON.toJSONString(sendResult));
        return sendResult;
    }

   /**
     * 發送異步消息(通過線程池執行發送到broker的消息任務,執行完后回調:在SendCallback中可處理相關成功失敗時的邏輯)
     * (適合對響應時間敏感的業務場景)
     */
    public void sendAsyncMsg(String body,String topic) {

        rocketMQTemplate.asyncSend(topic, MessageBuilder.withPayload(body).build(), new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                //發送成功處理...
            }
            @Override
            public void onException(Throwable throwable) {
              //發送失敗處理...
        
            }
        });
    }
    
   /**
     * 發送延時消息(上面的發送同步消息,delayLevel的值就為0,因為不延時)
     * 在start版本中 延時消息一共分為18個等級分別為:1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
     */
    public void sendDelayMsg(String body,String topic, int delayLevel) {
        rocketMQTemplate.syncSend(topic, MessageBuilder.withPayload(body).build(), 3000, delayLevel);
    }

    /**
     * 發送單向消息(只負責發送消息,不等待應答,不關心發送結果,如日志)
     */
    public void sendOneWayMsg(String body,String topic) {
        rocketMQTemplate.sendOneWay(topic, MessageBuilder.withPayload(body).build());
    }
    
   /**
     * 發送帶tag的消息,直接在topic后面加上":tag"
     */
    public SendResult sendTagMsg(String body,String topic) {
        return rocketMQTemplate.syncSend(topic, MessageBuilder.withPayload(body).build());
    }

}

代碼中 body 就是消息體,如果你發消息之前是一個/一組對象,可以轉換成 json 格式,當然也可以把上面的 body 修改成自己要傳的對象比如 User。 topic 就是要發送到那個主題上。

 public void sendOneWayMsg(User user,String topic) {
        rocketMQTemplate.sendOneWay(topic, MessageBuilder.withPayload(user).build());
    }

上面就是一個 Producer 示例,里面包含了多種發送消息的模式,當然 RocketMQ 給我們提供的不止這些,大家可以去官方文檔看一下。

定義消費者

@Slf4j
// MessageExt:是一個消息接收通配符,不管發送的是String還是對象,都可接收,當然也可以像上面明確指定類型(我建議還是指定類型較方便)
//,messageModel = MessageModel.BROADCASTING
@Service
@RocketMQMessageListener(topic = "TEST_TOPIC", consumerGroup = "TEST_Group")
public class TaxInfoConsumerService implements RocketMQListener<MessageExt> {
   
    @Override
    public void onMessage(MessageExt message) {
        System.out.println("線程" + Thread.currentThread() + "內容為:"
                + new String(message.getBody()) +
                "隊列序號:" + message.getQueueId());
        //這里消費的消息可以寫自己的業務邏輯代碼,比如插入,刪除,上傳。。。

    }

這個就是簡單的消費者示例。

@RocketMQMessageListener(topic = "TEST_TOPIC", consumerGroup = "Test_Group")

這行代碼表示當前消費者監聽了 TEST_TOPIC 上的信息,消費者組的名字就叫做 Test_Group. 如果有生產者往 TEST_TOPIC 上投遞消息,就會被當前消費者感知,并且去消費指定 Topic 上的信息。

發送消息

//使用之前先注入我們剛創建的MQProducerService
@Inject
private MQProducerService mqProducerService;



......
//我自己有一個類TaxInfoBean,里面封裝了我要傳的數據:
TaxInfoBean taxInfoBean = new TaxInfoBean();
taxInfoBean.setSn(taxInfoSn.nextNo());
taxInfoBean.setOutTxNo(outTxNo);
taxInfoBean.setNotifyTimes(0);
taxInfoBean.setAmount(amount);
taxInfoBean.setIdCardNo(idCardNo);
taxInfoBean.setTaxNo(taxNo);
taxInfoBean.setInvoiceCode(invoiceCode);
taxInfoBean.setBankReceiptFiles(bankReceiptFiles);
taxInfoBean.setProofFiles(proofFiles);
taxInfoBean.setTaxProjectName(taxProjectName);
String taxInfoData = JSON.toJSONString(taxInfoBean);

//重點:使用剛剛創建的mqProducerService的異步發送方式發送消息。
//taxinfoData是投遞的消息,TEST_TOPIC代表我要投遞到這個topic中
mqProducerService.sendAsyncMsg(taxInfoData, “TEST_TOPIC”);

大家可以自己創建一個測試類,測試一下,我這里只截取了部分代碼。

啟動測試方法,發送消息,我們打開控制臺就會看到輸出了:

線 程 Thread[ConsumeMessageThread_14,5,main]內 容 為 :
{
    "amount":999.99,
    "idCardNo":"410425128710026151",
    "invoiceCode":"304990000123400000001014",
    "invoiceType":1,
    "notifyTimes":0,
    "outTxNo":"BZD44V5Dh_V_vQ7h9fEXa",
    "settlementType":0,
    "sn":"1123041202077",
    "taskStatus":"PROCESSING",
    "taxNo":"91110105MA01R54K8A2",
    "taxProjectName":"20230491110105MA01R54K8A2"
}
隊 列 序 號 :8

沒錯,這就是消費者已經成功消費了,并把整個 message 打印了出來,我們的消息內容是 message.getBody()的所有內容。

我們可以在消費者里面加上自己業務代碼。

springboot+rocketmq 單機部署(centos7+docker)

想了一下還是跟大家一起用 docker 先單機部署一下 熟悉流程之后,后面的集群部署也就非常簡單了。

首先打開我們的 Linux 環境,啟動 docker(沒有安裝 docker 的可以搜一下,直接安裝就行。)

啟動 doker: systemctl start docker
搜索鏡像
docker search rocketmq
b2338ab32ac71550882fefe9a424ae5d.png
拉取鏡像
docker pull rocketmqinc/rocketmq

一般情況下拉取的就是最新版本。

這個時候 rocketmq 已經準備好了,我們回憶下上一節的啟動過程,這里有些類似的地方,我們創建一個存放 nameserver 的數據目錄:

mkdir -p /docker/rocketmq/nameserver/logs /docker/rocketmq/nameserver/store

同理,我們也提前創建存放 broker 配置信息目錄,我們需要單獨創建一個存放 broker 配置信息的文件目錄

mkdir -p /docker/rocketmq/data/broker-master/confmkdir -p /docker/rocketmq/data/broker-slave/conf

能看出來,這兩個文件夾就是代表 broker 的一主一從。除了這個 conf 文件夾,我們還要另外創建兩個文件夾

一主一從: 前面大家都知道了 broker 可以配置主從節點,一個 master 一個 slave,master 節點會進行異步/同步刷盤到 slave 上,這也保證了如果某個 broker 掛了,slave 能夠迅速頂上。

RocketMQ 支持兩種刷盤方式:同步刷盤和異步刷盤。同步刷盤是指在消息發送的同時將消息寫入磁盤,確保消息不會丟失,但是會降低消息發送的速度。異步刷盤是指將消息先寫入內存緩存,然后再定時或者觸發條件下將緩存中的消息寫入磁盤,這樣可以提高消息發送的速度,但是可能會造成消息丟失的風險。

mkdir -p /docker/rocketmq/data/broker-master/store 
mkdir -p /docker/rocketmq/data/broker-master/logs  
mkdir -p /docker/rocketmq/data/broker-slave/store 
mkdir -p /docker/rocketmq/data/broker-slave/logs

整體的架構就是:

?  docker/rockermq
.
├── data
│   ├── broker-master
│       ├── conf
│       ├── store
│       └── logs
│   ├── beoker-slave
│       ├── conf
│       ├── store
│       └── logs
└── nameserver
    ├── store
    └── logs

初始的文件夾已經創建好了,我們要先啟動 nameserver.

docker run -d --restart=always --name rmqnamesrv --privileged=true -p 9876:9876  -v /docker/rocketmq/nameserver/logs:/root/logs -v /docker/rocketmq/nameserver/store:/root/store -e "MAX_POSSIBLE_HEAP=100000000" rocketmqinc/rocketmq sh mqnamesrv

參數說明
[圖片上傳失敗...(image-723cc7-1688441580784)]

配置 broker

我們有關 broker 的文件夾之前已經創建好了,但是缺少配置文件 broker.conf

創建 master 的 broker.conf
brokerName = brokera-master
brokerId = 0   #id為0代表當前是主節點(master)
deleteWhen = 04
fileReservedTime = 48
namesrvAddr = 8.*.*.*:9876;  #你的nameserver地址
brokerRole = ASYNC_MASTER  
flushDiskType = ASYNC_FLUSH
autoCreateTopicEnable = false  #這個強烈建議設置成false
brokerIP1 = 當前服務器ip地址

然后把這個文件放到 data/broker-master/conf 里面

創建 slave 的 broker.conf
brokerName = brokera-slave
brokerId = 1
deleteWhen = 04
fileReservedTime = 48
namesrvAddr = 8.*.*.*:9876;
brokerRole = SLAVE
flushDiskType = ASYNC_FLUSH
autoCreateTopicEnable = false
brokerIP1 = 當前服務器ip地址

然后把這個文件放到 data/broker-slave/conf 里面

autoCreateTopicEnable 代表是否開啟自動創建 topic,這里大家設置成 false 就行,如果只是自己測試一下那就無所謂,發不到線上的話為了避免創建無用的 topic,浪費資源,建議還是關掉。

整體目錄架構
?  docker/rockermq
.
├── data
│   ├── broker-master
│       ├── conf
│           ├──broker.conf
│       ├── store
│       └── logs
│   ├── beoker-slave
│       ├── conf
│           ├──broker.conf
│       ├── store
│       └── logs
└── nameserver
    ├── store
    └── logs

啟動 broker

這里大家一定要謹慎,這里最容易出錯,大家啟動的時候一定提前看看自己的命令是否正確 我們要啟動兩次 broker(一主一從) 啟動 brokera-master

docker run -d --restart=always --name brokera-master --link rmqnamesrv:namesrv -p 10911:10911 -p 10909:10909 --privileged=true -v /docker/rocketmq/data/broker-master/logs:/root/logs -v /docker/rocketmq/data/broker-master/store:/root/store -v /docker/rocketmq/data/broker-master/conf/broker.conf:/opt/docker/rocketmq/data/broker-master/conf/broker.conf -e "NAMESRV_ADDR=8.***:9876" -e "MAX_POSSIBLE_HEAP=200000000" rocketmqinc/rocketmq sh mqbroker -c /opt/docker/rocketmq/data/broker-master/conf/broker.conf

大家把 NAMESRV_ADDR=8.*:9876",改成自己的 nameserver 地址。

如果前面的所有步驟都跟我的一樣,正常情況下是沒問題的,如果前面創建文件夾那里并沒有跟我的一模一樣,那你就要把命令改一下,文件目錄做一下修改才行。

完事之后輸入

docker ps -a 查看所有的已經啟動的容器。
e79f5e4a990c19f9ecf3fbee07f877e7.png

可以看到 STATUS 那里是啟動成功的 那么 master 節點的 broker 就已經啟動成功了,接下來啟動 slave

docker run -d --restart=always --name brokera-slave --link rmqnamesrv:namesrv -p 10124:10911 -p 10623:10909 --privileged=true -v /docker/rocketmq/data/broker-slave/logs:/root/logs -v /docker/rocketmq/data/broker-slave/store:/root/store -v /docker/rocketmq/data/broker-slave/conf/broker.conf:/opt/docker/rocketmq/data/broker-slave/conf/broker.conf -e "NAMESRV_ADDR=8.*:9876" -e "MAX_POSSIBLE_HEAP=200000000" rocketmqinc/rocketmq sh mqbroker -c /opt/docker/rocketmq/data/broker-slave/conf/broker.conf

把 NAMESRV_ADDR 的地址換成自己的 nameserver 地址。


ea9cb6e2b241f301bc7f9782ded9abac.png

可以看到一主一從都已經啟動成功了

安裝可視化控制臺

啟動完 broker 和 nameserver 之后,我們啟動可視化控制臺。

拉取鏡像

docker pull pangliang/rocketmq-console-ng

直接啟動控制臺 啟動之前大家把 nameserv.addr 的地址改成自己的 nameserver 的 IP 地址

docker run -d --restart=always --name rmqadmin -e "JAVA_OPTS=-Drocketmq.namesrv.addr=122.*.*.*:9876 -Dcom.rocketmq.sendMessageWithVIPChannel=false" -p 8080:8080 pangliang/rocketmq-console-ng
91119b87834c5e1159119d2274a24db5.png

完事之后直接打開服務器 ip:8080 直接啟動就能看到熟悉的頁面


88244125d6b487ff268e63dd27018d0d.png

可以看到一主一從,我的名字是 brokera-master-a,brokera-slave-a

如果沒有這兩條 broker 記錄大家一定要檢查自己的 nameserver 地址有沒有配置,著重檢查 broker.conf,和啟動容器命令,容器命令有多個文件目錄,一定要跟自己創建的對的上。

springboot 使用

整合 Springboot 和上面的過程一模一樣 ,application.yml 的 namesrv-addr 可能要改成自己 Linux 配置之后的地址, 其他代碼不用改。

springboot+rocketmq 集群部署(centos7+docker)

趁熱打鐵,上面完成了單機部署,我這里有兩臺服務器,我采用的是 2 個 nameserver,broker 是 2 主 2 從。 每臺服務器上是 1 個 nameserver 和 broker(一主一從)

我們按照上面的步驟每臺服務器上都重復創建好存放 nameserver 和 broker 的文件目錄,兩臺服務器都是如此
?  docker/rockermq
.
├── data
│   ├── broker-master
│       ├── conf
│           ├──broker.conf
│       ├── store
│       └── logs
│   ├── beoker-slave
│       ├── conf
│           ├──broker.conf
│       ├── store
│       └── logs
└── nameserver
    ├── store
    └── logs

兩臺服務器都拉取 rocketmq 鏡像,然后依次啟動容器(兩臺服務器命令一樣)

docker run -d --restart=always --name rmqnamesrv --privileged=true -p 9876:9876 -v /docker/rocketmq/nameserver/logs:/root/logs -v /docker/rocketmq/nameserver/store:/root/store -e "MAX_POSSIBLE_HEAP=100000000" rocketmqinc/rocketmq sh mqnamesrv
這樣就啟動了 2 臺 nameserver
接下來配置 broker.conf
第一臺服務器上的一主一從 broker.conf
brokerClusterName = XgshDefaultCluster
brokerName = broker-master-a
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
namesrvAddr = 8.*.*.*:9876;8.*.*.*:9876 #大家可以看到這里有兩個nameserver IP地址,用分號隔開。
brokerRole = ASYNC_MASTER  
flushDiskType = ASYNC_FLUSH
autoCreateTopicEnable = false  #關閉自動創建Topic
brokerIP1 = 本機服務器IP
brokerClusterName = XgshDefaultCluster
brokerName = broker-slave-a
brokerId = 1 
deleteWhen = 04
fileReservedTime = 48
namesrvAddr = 8.*.*.*:9876;8.*.*.*:9876
brokerRole = SLAVE
flushDiskType = ASYNC_FLUSH
autoCreateTopicEnable = false
brokerIP1 = 本機服務器IP
第二臺服務器上的一主一從 broker.conf
brokerClusterName = XgshDefaultCluster
brokerName = broker-master-b
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
namesrvAddr = 8.*.*.*:9876;8.*.*.*:9876 #大家可以看到這里有兩個nameserver IP地址,用分號隔開。
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH
autoCreateTopicEnable = false
brokerIP1 = 本機服務器IP


brokerClusterName = XgshDefaultCluster
brokerName = broker-slave-b
brokerId = 1
deleteWhen = 04
fileReservedTime = 48
namesrvAddr = 8.*.*.*:9876;8.*.*.*:9876 #大家可以看到這里有兩個nameserver IP地址,用分號隔開。
brokerRole = SLAVE
flushDiskType = ASYNC_FLUSH
autoCreateTopicEnable = false
brokerIP1 = 本機服務器IP

參數說明
[圖片上傳失敗...(image-f0dbc-1688441580784)]

啟動 broker

第一臺服務器(命令中的 NAMESRV_ADDR 改成自己服務器啟動的 2 個,中間用分號隔開)

docker run -d --restart=always --name broker-master01 --link rmqnamesrv:namesrv -p 10911:10911 -p 10909:10909 --privileged=true -v /docker/rocketmq/data/broker-master/logs:/root/logs -v /docker/rocketmq/data/broker-master/store:/root/store -v /docker/rocketmq/data/broker-master/conf/broker.conf:/opt/docker/rocketmq/data/broker-master/conf/broker.conf -e "NAMESRV_ADDR=8.*.*.*:9876;8.*.*.*:9876" -e "MAX_POSSIBLE_HEAP=200000000" rocketmqinc/rocketmq sh mqbroker -c /opt/docker/rocketmq/data/broker-master/conf/broker.conf

docker run -d --restart=always --name broker-slave01 --link rmqnamesrv:namesrv -p 10124:10911 -p 10623:10909 --privileged=true -v /docker/rocketmq/data/broker-slave/logs:/root/logs -v /docker/rocketmq/data/broker-slave/store:/root/store -v /docker/rocketmq/data/broker-slave/conf/broker.conf:/opt/docker/rocketmq/data/broker-slave/conf/broker.conf -e "NAMESRV_ADDR=8.*.*.*:9876;8.*.*.*:9876" -e "MAX_POSSIBLE_HEAP=200000000" rocketmqinc/rocketmq sh mqbroker -c /opt/docker/rocketmq/data/broker-slave/conf/broker.conf

第二臺服務器(命令中的 NAMESRV_ADDR 改成自己服務器啟動的 2 個,中間用分號隔開)

docker run -d --restart=always --name broker-master02 --link rmqnamesrv:namesrv -p 10911:10911 -p 10909:10909 --privileged=true -v /docker/rocketmq/data/broker-master/logs:/root/logs -v /docker/rocketmq/data/broker-master/store:/root/store -v /docker/rocketmq/data/broker-master/conf/broker.conf:/opt/docker/rocketmq/data/broker-master/conf/broker.conf -e "NAMESRV_ADDR=8.*.*.*:9876;8.*.*.*:9876" -e "MAX_POSSIBLE_HEAP=200000000" rocketmqinc/rocketmq sh mqbroker -c /opt/docker/rocketmq/data/broker-master/conf/broker.conf 

docker run -d --restart=always --name broker-slave02 --link rmqnamesrv:namesrv -p 10124:10911 -p 10623:10909 --privileged=true -v /docker/rocketmq/data/broker-slave/logs:/root/logs -v /docker/rocketmq/data/broker-slave/store:/root/store -v /docker/rocketmq/data/broker-slave/conf/broker.conf:/opt/docker/rocketmq/data/broker-slave/conf/broker.conf -e "NAMESRV_ADDR=8.*.*.*:9876;8.*.*.*:9876" -e "MAX_POSSIBLE_HEAP=200000000" rocketmqinc/rocketmq sh mqbroker -c /opt/docker/rocketmq/data/broker-slave/conf/broker.conf

broker 啟動成功,我們通過命令看一下(2 臺服務器都看一下)

docker ps -a
第一臺服務器:
cd0c7a92394f48fea8aef826cfd22c1f.png
第二臺服務器:
1cc4428af97ec8941403501db17fe221.png

大家看一下 STATUS 是都啟動成功。

啟動控制臺

在其中一臺服務器拉取可視化界面鏡像(只用在其中一臺啟動就可以了)

docker run -d --restart=always --name rmqadmin -e "JAVA_OPTS=-Drocketmq.namesrv.addr=122.*.*.*:9876;122.*.*.*:9876 -Dcom.rocketmq.sendMessageWithVIPChannel=false" -p 8080:8080 pangliang/rocketmq-console-ng

訪問服務器 IP:8080 能看到下面的就代表成功了!!


ba98e38fbe0fec96cd75246638db62b4.png

整合 springboot

我們只需要在 applicatiom.yml 文件中修改為 2 個 nameserver 地址用分號隔開

rocketmq:
  name-server: 8.*.*.*:9876;8.*.*.*:9876 # 兩個nameserver訪問地址
  producer:
    group: Pro_Group # 必須指定group
    send-message-timeout: 3000 # 消息發送超時時長,默認3s
    retry-times-when-send-failed: 3 # 同步發送消息失敗重試次數,默認2
    retry-times-when-send-async-failed: 3 # 異步發送消息失敗重試次數,默認2
啟動項目,我們根據自己的需要去創建 Topic,然后通過開篇的示例去發送消息到消費者消費消息過程是不變的。

問題:

1.可視化界面一直加載不出來
2.因為我用的是阿里云服務器,所以訪問不了大概率是 8080 這個端口號沒有加安全組,大家進入到阿里云找到服務器,添加安全組,端口號 8080,建議大家設置一下授權對象,然后把自己本機 ip 輸入進去,返回瀏覽器刷新。就能訪問了。
3.老問題,(2 主 2 從)broker 不顯示
4.首先我們使用 docker ps -a 查看所有啟動的容器,大家可以看下自己啟動的 broker,看一下 STATUS 如果不是 Up 6 hours 這種的,而是很長一串,那就是 broker 啟動失敗了,還是一定要看啟動命令和 broker.conf 每一行配置是否正確,nameserver 地址是否正確!

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內容