使用Sentry错误监控实践

官网及文档

https://sentry.io/welcome/

https://docs.sentry.io

https://docs.sentry.io/guides/

安装教程
https://github.com/getsentry/self-hosted/tree/cd13427aa9a231b2b27c9fd14017d183cca52c1e

Sentry 是一款开源的应用监控产品,使用 Python、JavaScript、HTML、CSS 打造。在 GitHub 上有 29k Stars,是应用监控领域 Stars 数排行最高的开源项目,其官网宣称有 1 百万名开发者和 7 万个组织在使用 Sentry。除了提供开源产品外,其幕后的公司也提供付费的 SaaS 服务:sentry.io。2021 年该公司宣布获得了 6000 万美元的 D 轮融资,该轮融资使 Sentry 的总资金达到 1.27 亿美元,融资后估值为 10 亿美元。确实是一款值得关注的产品。

Sentry 原理图

image.png

概念

Event: 事件。
每次产生的日志记录,每个event有很多元信息,包括事件级别,项目信息,环境等。可通过点击具体事件对应的“JSON”数据进行查看

Issue:问题。
相同的地方产生的一个异常称为一个Issue(是同一类问题的聚合)。假如在同一个位置发生了两次报错,那么会产生两个Event事件,但是只有一个Issue。

DSN:客户端(具体项目)密钥。
DSN是一个url,包含相关密钥信息,客户端与服务端(sentry服务器)就是通过这个DSN进行通信,上报错误信息的。

Auth Token:授权令牌。
授权令牌允许基于你的账户使用Sentry API,我们主要用到使用@sentry/cli进行上传sourceMap文件等操作时,sentry/cli会基于Auth Token进行调用相应API方法。

Org:组织名称。
对应公司部署的sentry服务器上的组织名称。
Release:版本号。
Project:客户端名称。(接入sentry的具体项目名)

Tag:标签。

本地搭建sentry服务

Sentry服务依赖比较多,官方推荐使用docker方式进行部署

硬件要求

image.png

安装python3.9

这里建议还是下载3.9的,因为笔者在第一次安装的时候是3.6.5版本的,但是报错如下


1642145651652_0902477D-7B83-4422-A992-7113CB6B9FBB.png

明显3.6对应的pip安装出现一些问题,这里还是更新高一些的版本。

1、下载python3.9安装包
a、下载:

cd /usr/download
wget https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tgz
b、解压文件:

tar -xvf Python-3.9.0.tgz
2、移除旧版本

a、 删除旧版本的软链接

rm -rf ./python3

rm -rf ./pip3
b、清空旧版本的存放内容
rm -rf /usr/local/python3/*
3、执行安装
a、编译文件,运行脚本configure
configure是一个shell脚本,根据平台的特性生成Makefile文件,为下一步的编译做准备。可以通过在 configure 后加上参数来对安装进行控制,比如下面就是指定安装目录/usr/local/python3。如果没有用这个选项,安装过程结束后,该软件所需的软件被复制到不同的系统目录下,比较混乱。编译文件 时间大概有1-3分钟

cd Python-3.9.0
sudo ./configure --prefix=/usr/local/python3

如果前面没有移除就版本,安装完会提示 ./configure --enable-optimizations,但是建议不要执行。有可能会出错。直接安装即可。如果执行后报错,只能重新清楚编译文件make distclean,然后再重新执行一遍编译安装。

image.png

b、make编译&make install安装

sudo make && sudo make altinstall

image.png

执行命令:

// export PATH=${PATH}:/usr/bin/python3
注意: 正常情况这里需要将黄色警告部分提示的路径复制添加在 export PATH= 后面的,(我的是 /usr/local/python3/bin/,但是为什么写/usr/bin/python3,因为后面要创建一个软连接,先跳过这一步).
source /etc/profile
4、创建软链接
cd /usr/local/python3/bin/
ls

注意下面的命令是python3.9和pip3.9,一不小心写错了就
sudo ln -s /usr/local/python3/bin/python3.9 /usr/bin/python3

sudo ln -s /usr/local/python3/bin/pip3.9 /usr/bin/pip3
如果提示存在,则先sudo rm -rf 文件然后再创建软连接。

export PATH=${PATH}:/usr/bin/python3

5、检查版本

python3 -V

-bash: python3: command not found
alias python3='/usr/bin/python3'

如果执行过下面的添加之后还是报错没有文件,检查第4点软链接是否设置错误
export PATH=${PATH}:/usr/bin/python3

pip3 -V
如果没有安装,执行下面命令
sudo yum update
sudo yum install python3-pip

ll /usr/bin/python*

image.png

安装docker

卸载旧的docker

# 停止 docker 服务
systemctl stop docker

sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

其他方式移除

sudo apt-get remove docker-compose
sudo rm /usr/local/bin/docker-compose
pip3 uninstall docker-compose

建立仓库

sudo yum install -y yum-utils
sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

安装docker engine

sudo yum install docker-ce docker-ce-cli containerd.io

启动docker

# 在容量最大的目录下创建文件夹
mkdir -p /data/var/lib/

# 将 docker 的默认数据复制到新路径下,删除旧数据并创建软连接,即使得存储实际占用磁盘为新路径 
/bin/cp -a /var/lib/docker /data/var/lib/docker && rm -rf /var/lib/docker && ln -s /data/var/lib/docker /var/lib/docker

sudo systemctl start docker

测试hello-world

sudo docker run hello-world

设置开机自启动

systemctl enable docker

通过修改daemon配置文件/etc/docker/daemon.json来使用加速器

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://djqpokpz.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

测试配置是否成功
docker search nginx


image.png

查看版本信息

docker info
或者
docker -v

docker system df 命令,类似于 Linux上的 df 命令,用于查看 Docker 的磁盘使用情况:

TYPE列出了 Docker 使用磁盘的 4 种类型:
Images :所有镜像占用的空间,包括拉取下来的镜像,和本地构建的。
Containers :运行的容器占用的空间,表示每个容器的读写层的空间。
Local Volumes :容器挂载本地数据卷的空间。
Build Cache :镜像构建过程中产生的缓存空间(只有在使用 BuildKit 时才有,Docker 18.09 以后可用)。
最后的 RECLAIMABLE 是可回收大小

容器清理
docker container prune : 仅删除停止运行的容器。
docker rm -f (docker ps -aq) : 删除所有容器(包括停止的、正在运行的)。 docker container rm -f(docker container ls -aq) : 同上。
镜像清理
docker rmi <image id> :通过镜像的id来删除指定镜像。

有一些镜像是隐形的:

子镜像,就是被其他镜像引用的中间镜像,不能被删除。
悬挂状态的镜像,就是不会再被使用的镜像,可以被删除。
其他命令:

docker image ls -f dangling=true : 可以列出所有悬挂状态的镜像
并使用命令 docker image rm (docker image ls -f dangling=true -q) 或 docker image prune进行删除。 docker image rm(docker image ls -q) :删除所有镜像。但正在被容器使用的镜像无法删除。
数据卷清理
docker volume rm $(docker volume ls -q) :删除不再使用的数据卷。
docker volume prune :同上。
缓存清理
Docker 18.09 引入了 BuildKit ,提升了构建过程的性能、安全、存储管理等能力。

docker builder prune :删除 build cache。

docker system prune : 可以用于清理磁盘,删除关闭的容器、无用的数据卷和网络,以及 dangling 镜像(即无 tag 的镜像)。
docker system prune -a : 清理得更加彻底,可以将没有容器使用 Docker镜像都删掉。
注意,这两个命令会把你暂时关闭的容器,以及暂时没有用到的 Docker 镜像都删掉了。

安装 docker-compose

指定版本1.29.2

sudo curl -L https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose  

sudo chmod +x /usr/local/bin/docker-compose

安装最新版本

compose_version=$(curl https://api.github.com/repos/docker/compose/releases/latest | jq .name -r)
output='/usr/local/bin/docker-compose'
curl -L https://github.com/docker/compose/releases/download/$compose_version/docker-compose-$(uname -s)-$(uname -m) -o $output
chmod +x $output
echo $(docker-compose --version)

查看docker-compose 版本

docker-compose version

安装redis

linux 服务器出现redis exceptions ConnectionError Error 113 connecting to 你的ip No route to host
运行命令 sudo iptables -F

下载Sentry仓库

yum install -y git

git clone https://github.com/getsentry/onpremise.git
cd onpremise
ls
image.png

最新版本的
git clone https://github.com/getsentry/self-hosted.git --depth=1

fatal: unable to access 'https://github.com/getsentry/self-hosted.git/': Encountered end of file

yum update nss curl git -y

git pull --unshallow #或者 git fetch --unshallow

切换需要安装的分支,这里必须切换分支,因为master分支上有很多无用的容器,启动的时候会报错

git checkout 21.12.0

文件结构与作用

image.png

要对部署和运行进行修改的话,需要找到对应的配置文件,先看下 onpremise 部署实现的主要文件结构和作用:

clickhouse/config.xml:clickhouse 配置文件
cron/:定时任务的镜像构建配置和启动脚本
nginx/nginx.conf:nginx 配置
relay/config.example.yml:relay 服务配置文件
sentry/:sentry-onpremise-local 镜像的构建和基于此镜像启动的主服务的配置都在这个文件夹下

Dockerfile:sentry-onpremise-local 的镜像构建配置,会以此启动很多服务
requirements.example.txt:由此生成 requirements.txt,需要额外安装的 Django 插件需要被写在这里面
.dockerignore:Docker 的忽略配置,初始忽略了 requirements.txt 之外的所有文件,如果构建新镜像时需要 COPY 新东西则需要修改此文件
config.example.yml:由此生成 config.yml,一般放运行时不能通过管理后台修改的配置
sentry.conf.example.py:由此生成 sentry.conf.py,为 python 代码,覆盖或合并至 sentry 服务中,从而影响 sentry 运行。
.env:镜像版本、数据保留天数、端口等配置
docker-compose.yml:Compose 工具配置,多 docker 的批量配置和启动设置
install.sh:Sentry 一键部署流程脚本
同时需要注意的是,一旦部署过之后,install.sh 脚本就会根据 xx.example.xx 生成实际生效的文件,而且,再次执行 install.sh 脚本时会检测这些文件存不存在,存在则不会再次生成,所以需要修改配置后重新部署的情况下,我们最好将生成的文件删除,在 xx.example.xx 文件中修改配置。

根据服务组成和运行机制得知,主服务是基于 sentry-onpremise-local 镜像启动的,而 sentry-onpremise-local 镜像中的 sentry 配置会合并 sentry.conf.py,此文件又是由 sentry.conf.example.py 生成,所以后续定制化服务时,会重点修改 sentry.conf.example.py 配置模板文件。

直接 ./install.sh执行安装,可是各种错误,并没有像网上教程那样顺利安装。比如postgres的错误。其实由于服务器是新配置的,很多基础配置都没有,这里需要先安装对应的依赖。

1、docker volume create --name=sentry-data && docker volume create --name=sentry-postgres

  • Make our local database and sentry volumes Docker volumes have to be created manually, as they are declared as external to be more durable.

2、 cp -n .env .env.custom

  • create env config file

3、docker-compose build

  • Build and tag the Docker services

4、docker-compose run --rm web config generate-secret-key

  • Generate a secret key. Add it to .env as SENTRY_SECRET_KEY.

5、docker-compose run --rm web upgrade

  • Build the database. Use the interactive prompts to create a user account.

6、docker-compose up -d

  • Lift all services (detached/background mode).

Access your instance at localhost:9000!
如果需要通过服务器ip访问,则需要将服务器防火墙开放该端口的访问权限,这里注意一点如果是腾讯云,通过宝塔面板放行的端口并没有真正生效,还需要服务器上再开放一下

If you're upgrading from < 21.12.0 then be sure to stop your old containers with this command before installing:

COMPOSE_PROJECT_NAME=sentry-self-hosted docker-compose down --rmi local --remove-orphans

Without this you may run into errors about snuba-api being unhealthy. This is because of we finished renaming from onpremise to self-hosted in 21.12.0 including the project name. We put the above code under install.sh in #1384, but it didn't make it into 22.3.0, sorry. <g-emoji class="g-emoji" alias="confused" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f615.png" style="box-sizing: border-box; display: inline-block; min-width: 1ch; font-family: "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 1.25em; font-weight: 400; line-height: 1; vertical-align: -0.075em; font-style: normal !important;">😕</g-emoji> It will be in 22.4.0.

还是不行
for id in (docker ps --format {{.ID}}); do docker stopid; done
./install.sh --skip-commit-check

image.png

docker-compose --env-file /usr/local/self-hosted/.env.custom up -d

运行部署脚本:

cd onpremise 
./install.sh
#安装指定版本
SENTRY_IMAGE=getsentry/sentry:21.12.0 ./install.sh

中间会要求输入初始管理员邮箱账号密码,输入y


image.png

启动服务

最后出现You're all done,并让你输入docker-compose up -d启动服务


image.png
image.png

记得需要在onpremise 目录底下运行

docker-compose up -d

安装过程并没有那么顺利,各种问题,比如下面,主要是网络不稳定造成的,重新执行一次即可解决。


image.png

然后又报了下面的错误,明显是端口地址被占用,需要更改配置

image.png

修改端口映射

查看端口 必须用sudo

sudo netstat -pna | grep 9000
查看是什么程序占用端口


image.png

如果知道php-fpm这个进程没用,直接kill掉前面的id即可,比如7992

sudo kill 7992

再次重启

docker start 41xxxxxxxad0 #前提是知道容器id
或者
docker-compose up -d

明显笔者这个是不能关闭的,因此需要修改配置端口了。

sudo vi sentry/sentry.config.py

SENTRY_WEB_PORT = 9090

image.png

主要更改.env文件,这里需要注意的是.开头的是隐藏文件,ls需要增加-a显示所有文件

ls -a
image.png

vi编辑文件,按 i 进入编辑模式

vi .env

SENTRY_EVENT_RETENTION_DAYS 将90更改未15,表示保存15天事件数据,视自己情况而定
SENTRY_BIND 将9000改为9090

image.png

HEALTHCHECK_INTERVAL=30s
HEALTHCHECK_TIMEOUT=60s
HEALTHCHECK_RETRIES=5

编辑config
sudo vi /sentry/config.yml

image.png

sudo vi nginx/nginx.conf


image.png

sudo vi relay/config.yml


image.png

docker-compose logs -f

...

Got errors as above: error trying to connect: dns error: no record found for name: web. type: AAAA

docker-compose restart relay
docker-compose logs -f

如果使用到kafka集群,可以在文件最后可添加 “限制 Kafka 磁盘使用量” 的配置,新版 Sentry 使用的 Kafka 会大量的写入日志信息,特别容易导致磁盘跑满,具体限制额度根据自己的磁盘情况而定。具体可常见 Sentry disk cleanup [kafka]

KAFKA_LOG_RETENTION_HOURS=24
KAFKA_LOG_RETENTION_BYTES=53687091200
KAFKA_LOG_SEGMENT_BYTES=1073741824
KAFKA_LOG_RETENTION_CHECK_INTERVAL_MS=300000
KAFKA_LOG_SEGMENT_DELETE_DELAY_MS=60000

编辑完成后,按 esc 退出编辑模式,然后按 shift + : 输入 wq 后回车。如果没有编辑可输入 q 或 q! 退出。
再次执行

sudo docker-compose down
sudo docker-compose build
sudo docker-compose up -d
image.png

检查安装镜像

全部是done,没有错误产生,执行检查镜像命令,查看env指定的镜像都有了。

docker images
image.png

查看Sentry 启动服务容器

通过 docker ps 命令,我们可以查看 Sentry 容器 服务状态信息


image.png

创建项目的superuser

Web 服务

docker-compose run --rm web upgrade

修改Sentry配置

进入sentry文件夹,可以发现有config.yml和sentry.conf.py


image.png
cd sentry/
ls
vi config.yml

部署Sentry,以后如果添加新的插件支持或者修改参数都得重新build

docker-compose build --pull # Build the services again after updating, and make sure we're up to date on patch version

docker-compose run --rm web upgrade # Run new migrations

docker-compose up -d # Recreate the services

启动后docker-compose ps看到的结果

首先我们修改一下映射端口。因为默认绑定端口是9000,因为我这台电脑启动了php-fpm服务绑定了9000端口,所以我这里需要将9000改成10000。具体相关配置如下:

docker-compose.yml

web:
<<: *defaults
ports:
- '9090:9000' # 修改位置

grep -rn '9000' ./

修改完Sentry配置,重启服务

sudo docker-compose restart web worker cron sentry-cleanup

重启所有所有服务

sudo docker-compose restart
image.png

本地简单测试

curl 127.0.0.1:9090

使用netstat命令查询端口状态:
netstat -ntlp | grep 9090

sudo lsof -i -P -n | grep LISTEN

Sentry 的邮件配置

安装邮箱 ssl 钉钉等插件

默认情况下,在Sentry控制台的插件列表里是没有钉钉的,使用钉钉需要先安装这个插件,编辑目录下的 requirements.txt 文件

# Add plugins here  
django-smtp-ssl==1.0  
redis-py-cluster==2.1.0
sentry-gitlab

修改邮箱配置

Sentry 支持邮件发送的功能很是重要,当 Sentry 捕获事件以后,能够将此捕获的事件发送到你的我的邮箱(针对 Sentry 管理员帐号)。要修改目前的邮件配置是不能在界面上操做的,须要进行如下步骤:

image.png

修改 sentry/config.yml

###############
# Mail Server #
###############

# mail.backend: 'smtp'  # Use dummy if you want to disable email entirely
mail.host: 'smtp.qq.com'
mail.port: 587
mail.username: '894266648@qq.com'
mail.password: '换成你的授权码'
mail.use-tls: true

# The email address to send on behalf of
mail.from: '894266648@qq.com'

上面记得更改mail.from,之前这里没改,默认的是sentry@localhost,下面发送邮件就报错了。


image.png

解决sentry禁用qq邮箱的问题

查看docker容器id

docker ps


image.png
进入web容器

docker exec -it 68f013b00894 bash

修改配置文件

vi /usr/local/lib/python3.9/site-packages/sentry/conf/server.py
注意有的是Python3.8 查看/usr/local/lib/ 底下即可知道
vi /usr/local/lib/python3.8/site-packages/sentry/conf/server.py
如果没有vi编辑器,去安装一个:

apt-get update
apt-get install vim -y

定位到1570行,vi编辑器使用 :1570

# block domains which are generally used by spammers -- keep this configurable in case an onpremise
# install wants to allow it
INVALID_EMAIL_ADDRESS_PATTERN = re.compile(r'\@qq\.com$', re.I)

https://github.com/getsentry/sentry/issues/13541

注意有的是Python3.8 并且源码不一定在1570,不同版本不一样,最新版本在2195,代码80%多位置


image.png

直接注释掉即可,如果container 重新创建之后,就会被覆盖
或者换成 INVALID_EMAIL_ADDRESS_PATTERN = re.compile(r'@xxxxxx.com$', re.I)
于是顺便提交了一个合并
https://github.com/getsentry/sentry/pull/32982/commits/6f29e6a5d65b7cf02e9b791cd0913c8ded506d01

输入“exit”或者按键“Ctrl + C”退出container

iptables failed: iptables --wait -t nat -I DOCKER

重新启动Docker sudo systemctl restart docker

修改 docker-compose.yml ,注释掉 SENTRY_EMAIL_HOST 配置,由于这个配置默认为 smtp ,会致使 .env 文件中的相同配置失效。

docker-compose down  
docker-compose run --rm web upgrade
docker-compose up -d  

重启后查看web端网页在左上角头像菜单下出现管理选项,进入email中可以发送测试邮件,验证是否配置正确。

保存后执行docker-compose build会下载安装插件。然后重新启动docker服务。

访问WEB端网页项目下的legacy integrations,可以看到钉钉的插件选项了

开启插件后,在钉钉的群组里创建自定义机器人,会生成一个带token的url,将其填写进项目设置里的dingtalk robot url中。保存后项目中产生BUG就会在钉钉群组收到通知。

避免 Sentry 引发雪崩
引入新的技术或者工具,或多或少都会增加系统的复杂度和运行风险。
我们之前出过一次严重问题:某个日均三千万接口请求量的服务发生故障,大量的错误信息涌向 Sentry 服务器,导致 Sentry 响应严重延迟,其 Redis 队列内存容量接近占满,而 Nginx 也全都响应 504 Gateway Timeout。恰好该故障的服务由于请求 Sentry 服务端未设置超时时间,导致 HTTP 请求同步阻塞,反倒拖垮了服务本身。
为了规避此类问题,有以下做法:

保障 Sentry 服务端高可用
这点最重要,但实际我们并未做好。目前我们自部署的 Sentry 是一个单点,并没有集群或冗余。如果要实现高可用,那么付出的金钱成本会较高,甚至可能超过了使用 Sentry SaaS 付费服务的成本。由于 Sentry 官方并未提供中国区的服务,HTTP 请求到国外的速度并不理想,使用官方 SaaS 服务也不见得是太好的选择。

设置 timeout
使用 Sentry SDK 时,一定要设置向 Sentry 服务器发送请求的超时时间,建议 3 秒以下。

设置 sample_rate
使用 Sentry SDK 时,可以设置采样率,0.00 表示拒绝发送任何事件,1.00 表示发送全部事件。建议前期设置较小的值,然后视应用的 PV 大小进行调整。使用采样率可能会带来这样的负面影响:零星的错误可能未上报,导致一直未被发现。

及时熔断
假如当 Sentry 服务器不堪重负时,应该避免应用继续请求 Sentry 了。比如:可以手动将采样率设置为 0.00。

使用异步方式(async)发送请求
如果 SDK 支持异步发送请求,那就使用,避免同步阻塞。

隔离生产环境的 Sentry
运维同事隔离部署了两套 Sentry,一套是体验环境,供开发环境/测试环境/预发布环境的应用接入使用;另外一套是正式环境,供生产环境/私有化环境的应用接入使用。如果要试验 Sentry 的功能或调整 Sentry 的配置,那我们会先在体验环境的 Sentry 中进行,确认没有问题后,才会调整生产环境的 Sentry,借此保障生产环境 Sentry 的稳定性。

通过队列来缓冲请求至 Sentry 的并发压力
假设应用的请求量和并发量都巨大,当出现严重故障时每个请求处理都发生错误,那么即使在 SDK 中设置了较低的采样率(比如:0.01),可能请求到 Sentry 的并发量依旧超过其有限承载。为了避免这个问题,我们在流量最大的服务中做了如下尝试:我们增加了一个队列,将服务的错误事件先入列,启动了少量的消费进程去消费该队列缓缓上报错误至 Sentry 服务端。并且应用程序中做了处理,即使该队列容量占满也不会影响正常业务(只是丢弃错误事件)。实践证明,这种中转缓冲的方式非常有效,不过也增加了接入 Sentry 工作量,大家可自行取舍。

image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容