AWS Lambda筆記-內(nèi)容分發(fā)(CDN)-7

本章使用CloudFormation來實現(xiàn)自定義域名并且使用AWS的SSL證書饱狂。同時利用AWS的CloudFront(AWS的CDN服務(wù))讓API網(wǎng)關(guān)實現(xiàn)多點接入过咬,讓用戶在最近的CDN節(jié)點連接,從而加快用戶和API之間的通訊速度查乒。

  1. 配置CloudFront
  2. 配置自定義域名
  3. 關(guān)聯(lián)SSL證書

工程說明

  1. 工程目錄結(jié)構(gòu)及java,build.gradle文件與AWS Lambda教程-自動部署-5 差不多唯一區(qū)別是build.gradle中將us-east-2改成us-east-1魂毁,本章主要是 cloudformation.tempalte 增加幾段json塊僚祷。
  2. 這邊使用自定義域名尺锚,并且使用ACM證書(AWS Certificate Manager (ACM) )目前支持的地區(qū)僅us-east-1(弗吉尼亞北部)

cloudformation.tempalte中AWS組件關(guān)聯(lián)關(guān)系,完整配置筆記的最后部分讶凉。


cloudformation.tempalte各AWS組件關(guān)聯(lián)關(guān)系圖

1. 配置CloudFront(CDN)

CloudFront都是例行公事的配置染乌,這里主要有HTTP的版本,原站信息懂讯,緩存方式荷憋,是否支持壓縮,被允許的HttpMethod類型褐望,具體Forward信息等勒庄,詳細看以下配置及具體備注串前。

"CloudformationDistribution": {
      //CDN配置分發(fā),它告知CloudFront 從何處傳輸內(nèi)容实蔽,并如何跟蹤和管理內(nèi)容傳輸?shù)脑敿毿畔ⅰ?      "Type": "AWS::CloudFront::Distribution",
      "Properties": {
          "Enabled": "true",  //啟用該資源
          "HttpVersion": "http2", //支持版本
          //此分配的源信息的復雜類型荡碾。用于描述CloudFront從中獲取文件的S3 存儲桶、
          //HTTP服務(wù)器局装、或其他服務(wù)器玩荠。
          "Origins": [  
            {
              "DomainName": { //允許開發(fā)者使用內(nèi)建函數(shù)Fn::Sub和其他資源變量合成域名
                "Fn::Sub": "${RestApi}.execute-api.${AWS::Region}.amazonaws.com"
              },
              "OriginPath": "/production",  //源中的目錄請求內(nèi)容
              "Id": "APIGATEWAY", //源或源組的唯一標識符。
              "CustomOriginConfig": { //配置為網(wǎng)站終端節(jié)點的自定義源或S3存儲桶
                "OriginProtocolPolicy": "https-only"  //要應(yīng)用至源的源協(xié)議策略
              }
            }
          ],
          //描述緩存行為
          "DefaultCacheBehavior": {
            //當請求使用默認緩存行為時贼邓,CloudFront將請求路由到的源的ID值
            "TargetOriginId": "APIGATEWAY", 
            "Compress": true, //自動壓縮此緩存行為的某些文件
            "AllowedMethods": [ //被允許的方法
              "DELETE",
              "GET",
              "HEAD",
              "OPTIONS",
              "PATCH",
              "POST",
              "PUT"
            ],
            "ForwardedValues": {  //處理查詢字符串阶冈、Cookie 和 HTTP 標頭
              //如果為 QueryString 指定 true,并且沒有為 QueryStringCacheKeys 
              //指定任何值塑径,CloudFront 會將所有查詢字符串參數(shù)轉(zhuǎn)發(fā)到來源女坑,
              //并基于所有查詢字符串參數(shù)進行緩存。根據(jù)擁有的查詢字符串參數(shù)的個數(shù)和值统舀,
              //這可能對性能產(chǎn)生不利影響匆骗,因為 CloudFront 必須將更多的請求轉(zhuǎn)發(fā)到源。
              "QueryString": "true",
              "Cookies": {  //Cookie 轉(zhuǎn)發(fā)到源
                "Forward": "none" //指定希望將哪些 Cookie 轉(zhuǎn)發(fā)到此緩存行為的來源
              },
              //轉(zhuǎn)發(fā)到此緩存行為的源的 Headers(如有)誉简。對于您指定的標頭碉就,
              //CloudFront 還將緩存基于查看器請求中的標頭值的指定對象的各個版本。
              "Headers": [  
                "Accept",
                "Content-Type",
                "Authorization"
              ]
            },
            "DefaultTTL": 0,  //TTL值
            "MaxTTL": 0,  //保留的最長時間
            "MinTTL": 0,  //如配置為將所有標頭轉(zhuǎn)發(fā)到源則必須為MinTTL指定0闷串。
            //當請求與 TargetOriginId 中的路徑模式匹配時瓮钥,
            //查看器可用于訪問 PathPattern 指定的來源中的文件的協(xié)議
            //redirect-to-https如果查看器提交HTTP請求,則CloudFront將向查看器返回 
            //HTTP 狀態(tài)代碼 301(永久移動)以及 HTTPS URL烹吵。然后碉熄,查看器會使用新的 
            //URL 重新提交請求。
            "ViewerProtocolPolicy": "redirect-to-https" 
          }
        }
      }
    }

以上配置好肋拔,我們可以部署(./gradlew deploy), 可以登陸CloudFront的控制臺
锈津,獲取域名(d3se3kgs51ey11.cloudfront.net),可以dig測試下凉蜂,我們的域名是否已經(jīng)全球解析琼梆。第一個是國內(nèi)dig的結(jié)果,域名解析到日本IP窿吩。第二個代理到美國域名解析的是美國IP茎杂。可以看出域名已經(jīng)成功解析到各個區(qū)域爆存。我們訪問:https://d3se3kgs51ey11.cloudfront.net/test?value=hello+world蛉顽,(d3se3kgs51ey11.cloudfront.net替換成你自己在CloudFront中域名)會相對會快一點點蝗砾。

CloudFront的控制臺

dig域名的結(jié)果:

dig d3se3kgs51ey11.cloudfront.net
;; ANSWER SECTION:
d3se3kgs51ey5f.cloudfront.net. 36 IN A 13.225.157.24
d3se3kgs51ey5f.cloudfront.net. 36 IN A 13.225.157.84
d3se3kgs51ey5f.cloudfront.net. 36 IN A 13.225.157.145
d3se3kgs51ey5f.cloudfront.net. 36 IN A 13.225.157.197

dig d3se3kgs51ey11.cloudfront.net
;; ANSWER SECTION:
d3se3kgs51ey5f.cloudfront.net. 300 IN A 13.227.53.123
d3se3kgs51ey5f.cloudfront.net. 300 IN A 13.227.53.231
d3se3kgs51ey5f.cloudfront.net. 300 IN A 13.227.53.49
d3se3kgs51ey5f.cloudfront.net. 300 IN A 13.227.53.61

2. 配置自定義域名

CloudFront配置成功后先较,我需要手動配置自定義域名的NS記錄和SSL證書的認證携冤。這些也可以通過CloudFormation模版自動化,不過這些操作都是一次性的闲勺,所有就不增加CloudFormation內(nèi)容的復雜度曾棕,同時該域名沒有配置郵箱,也不方面在申請SSL證書時通過郵件認證菜循。

1)配置域名NS記錄

進入AWS Route 53 管理頁面https://console.aws.amazon.com/route53/home翘地,點擊左側(cè)菜單“托管區(qū)域”。
重點:這邊我們需要保存下癌幕, 托管區(qū)域:Z09377931HZWDHZB7ST9N衙耕,在后續(xù)配置中需要使用到。

創(chuàng)建托管區(qū)域

點擊域名勺远,可以看到該域名的NS橙喘,SOA記錄。


NS記錄

在自己的域名解析管理中增加NS記錄


添加NS記錄

配置生效后胶逢,我們?yōu)楸U舷乱徊巾樌瓿商梗炞C下NS記錄是否生效。
//dig ns 確認解析出來的為剛才配置的ns記錄
dig ns serverless.kkkkkk.com
2)申請SSL證書并通過DNS認證

進入AWS Certificate Manger 頁面 https://us-east-2.console.aws.amazon.com/acm/home 初坠,點擊“請求證書” 和簸,按照提示
步驟 1: 添加域名
步驟 2:選擇驗證方法 (選擇DNS驗證)
步驟 3: 添加標簽 (可以不操作)
步驟 4:審核并請求
步驟 5:驗證
按步驟操作完成,回到“證書管理”頁面碟刺,查看申請證書的域名锁保,點擊“在Route 53中創(chuàng)建記錄” 這時會自動創(chuàng)建一個NS記錄,等待一會兒域名狀態(tài)從“等待審核” 變成 “已頒發(fā)”半沽。

證書管理

成功之后身诺,我們需要記錄下ACM的ARN記錄,如圖:
image.png

接下來我們需要繼續(xù)在cloudformation.template文件添加配置域名的A記錄抄囚。

 "DNSRecord": {
      //可選注釋霉赡、要更改的托管區(qū)域的名稱和 ID,以及要創(chuàng)建的記錄的值
      "Type": "AWS::Route53::RecordSetGroup",
      "Properties": {
        "Comment": "Z09377931HZWDHZB7ST9N在Route53上創(chuàng)建托管區(qū)域",
        ////要在其中創(chuàng)建記錄的托管區(qū)域的ID幔托,在“配置域名NS記錄”中重點說明過
        "HostedZoneId": "Z09377931HZWDHZB7ST9N",
        "RecordSets": [ //一條記錄的信息
          {
            "Name": {
              "Ref": "DomainName"
            },
            "Type": "A",  //DNS記錄類型
            //僅限別名記錄:有關(guān)您要將流量路由到的 AWS 資源
            //例如 CloudFront 分配或 Amazon S3 存儲桶的信息穴亏。
            "AliasTarget": {  //CloudFront 分配
              //CloudFront分配,指定Z2FDTNDATAQYW2。
              //在創(chuàng)建將流量路由到CloudFront 分配的別名記錄時重挑,它始終是托管區(qū)域ID嗓化。
              "HostedZoneId": "Z2FDTNDATAQYW2", 
              "DNSName": {
                "Fn::GetAtt": [
                  "CloudformationDistribution",
                  "DomainName"
                ]
              }
            }
          }
        ]
      }
    }

Alias(別名)是Route53提供的強大功能之一,相比CName記錄谬哀,別名記錄可以直接指向AWS資源刺覆,例如ELB,CloudFront史煎。別名在DNS中沒有對應(yīng)的概念谦屑,使用別名免費驳糯,而CName是付費服務(wù)。另外一個有點是Alias比CName少一步獲取最終IP地址氢橙,減少解析的負擔酝枢,繼續(xù)發(fā)布工程(./gradlew deploy)發(fā)布成功后,我dig配置的域名可以發(fā)現(xiàn)解析的A記錄多很多悍手,到此自定義域名配置成功帘睦。但是使用http訪問http://serverless.kkkkkk.com//test?value=hello+world,將放回403信息坦康,提醒:The request could not be satisfied. 接下來我們將繼續(xù)SSL證書配置竣付。

dig serverlessbook.kkkkkk.com

; <<>> DiG 9.10.6 <<>> serverlessbook.kkkkkk.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29231
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;serverlessbook.kkkkkk.com. IN A

;; ANSWER SECTION:
serverlessbook.kkkkkk.com. 59 IN A 13.225.157.197
serverlessbook.kkkkkk.com. 59 IN A 13.225.157.84
serverlessbook.kkkkkk.com. 59 IN A 13.225.157.24
serverlessbook.kkkkkk.com. 59 IN A 13.225.157.145

;; Query time: 2468 msec
;; SERVER: 114.114.114.114#53(114.114.114.114)
;; WHEN: Sun Jun 07 15:33:07 CST 2020
;; MSG SIZE rcvd: 107

3. 關(guān)聯(lián)SSL證書

這里只需要在 AWS::CloudFront::Distribution 的 Properties 增加:

"Aliases": [  //分配的 CNAME(備用域名)
{
  "Ref": "DomainName"
}
],
"ViewerCertificate": {  // SSL/TLS 配置
 //指定 ACM 證書 ARN,必須指定 MinimumProtocolVersion 和 SslSupportMethod 的值滞欠。 
 //使用 Aliases(備用域名或 CNAME)卑笨,請指定分配接受來自哪些查看器的 HTTPS 連接.
 //分為sni-only(免費,到部分瀏覽器都支持仑撞,推薦) 和 vip(付費且需要單獨申請)
"SslSupportMethod": "sni-only",
  //SSL證書申請中的ARN
"AcmCertificateArn": "arn:aws:acm:us-east-1:083845954160:certificate/0cc193a9-9489-47ce-b7b3-8213a4c434d1"
},

執(zhí)行

~/.gradlew deploy

發(fā)布成功后赤兴,我們訪問API就變成:https://serverless.kkkkkk.com/test?value=hello+world
現(xiàn)在這個API使用自定義域名且配置SSL,但是還沒有權(quán)限控制隧哮,后續(xù)我們需要對該方法進行權(quán)限控制桶良。



發(fā)布異常一

FAILURE: Build failed with an exception.

  • What went wrong:
    Execution failed for task ':awsCfnWaitStackComplete'.
    Status of stack serverlessbook is UPDATE_ROLLBACK_COMPLETE. It seems to be failed.

查看CloudFormation
]的“事件”提示具體的錯誤信息:

Property validation failure: [Encountered unsupported properties in {/DistributionConfig/ViewerCertificate}: [ACMCertificateArn]]
這個原因是ACMCertificateArn數(shù)名名的正確寫法AcmCertificateArn,這說明CloudFormtion嚴格區(qū)分大小寫沮翔。



cloudformation.tempalte 完整配置

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Parameters": {
        "DeploymentBucket": {
            "Type": "String",
            "Description": "S3 bucket name where built artifacts are deployed"
        },
        "ProjectVersion": {
            "Type": "String",
            "Description": "Project Version"
        },
        "DeploymentTime": {
            "Type": "String",
            "Description": "It is a timestamp value which shows the deployment time. Used to rotate sources."
        },
        "DomainName": {
            "Type": "String",
            "Description": "Domain Name to serve the application"
        }
    },
    "Resources": {
        "DeploymentLambdaRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "lambda.amazonaws.com"
                                ]
                            },
                            "Action": [
                                "sts:AssumeRole"
                            ]
                        }
                    ]
                },
                "Path": "/",
                "ManagedPolicyArns": [
                    "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
                ],
                "Policies": [
                    {
                        "PolicyName": "LambdaExecutionPolicy",
                        "PolicyDocument": {
                            "Version": "2012-10-17",
                            "Statement": [
                                {
                                    "Effect": "Allow",
                                    "Action": [
                                        "lambda:PublishVersion",
                                        "apigateway:POST"
                                    ],
                                    "Resource": [
                                        "*"
                                    ]
                                }
                            ]
                        }
                    }
                ]
            }
        },
        "DeploymentLambda": {
            "Type": "AWS::Lambda::Function",
            "Properties": {
                "Role": {
                    "Fn::GetAtt": [
                        "DeploymentLambdaRole",
                        "Arn"
                    ]
                },
                "Handler": "serverless.handler",
                "Runtime": "nodejs12.x",
                "Code": {
                    "S3Bucket": {
                        "Fn::Sub": "serverless-arch-${AWS::Region}"
                    },
                    "S3Key": "serverless.zip"
                }
            }
        },
        "ApiGatewayCloudwatchRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "apigateway.amazonaws.com"
                                ]
                            },
                            "Action": "sts:AssumeRole"
                        }
                    ]
                },
                "Path": "/",
                "ManagedPolicyArns": [
                    "arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs"
                ]
            }
        },
        "ApiGatewayAccount": {
            "Type": "AWS::ApiGateway::Account",
            "Properties": {
                "CloudWatchRoleArn": {
                    "Fn::GetAtt": [
                        "ApiGatewayCloudwatchRole",
                        "Arn"
                    ]
                }
            }
        },
        "RestApi": {
            "Type": "AWS::ApiGateway::RestApi",
            "Properties": {
                "Name": {
                    "Ref": "AWS::StackName"
                }
            }
        },
        "LambdaExecutionRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "Path": "/",
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "lambda.amazonaws.com"
                                ]
                            },
                            "Action": [
                                "sts:AssumeRole"
                            ]
                        }
                    ]
                },
                "ManagedPolicyArns": [
                    "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
                ]
            }
        },
        "LambdaCustomPolicy": {
            "Type": "AWS::IAM::Policy",
            "Properties": {
                "PolicyName": "LambdaCustomPolicy",
                "PolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Action": [
                                "s3:ListBuckets"
                            ],
                            "Resource": "*"
                        }
                    ]
                },
                "Roles": [
                    {
                        "Ref": "LambdaExecutionRole"
                    }
                ]
            }
        },
        "TestLambda": {
            "Type": "AWS::Lambda::Function",
            "Properties": {
                "Handler": "com.serverlessbook.lambda.test.Handler",
                "Runtime": "java8",
                "Timeout": "300",
                "MemorySize": "1024",
                "Description": "Test lambda",
                "Role": {
                    "Fn::GetAtt": [
                        "LambdaExecutionRole",
                        "Arn"
                    ]
                },
                "Code": {
                    "S3Bucket": {
                        "Ref": "DeploymentBucket"
                    },
                    "S3Key": {
                        "Fn::Sub": "artifacts/lambda-test/${ProjectVersion}/${DeploymentTime}.jar"
                    }
                }
            }
        },
        "TestResource": {
            "Type": "AWS::ApiGateway::Resource",
            "Properties": {
                "PathPart": "test",
                "RestApiId": {
                    "Ref": "RestApi"
                },
                "ParentId": {
                    "Fn::GetAtt": [
                        "RestApi",
                        "RootResourceId"
                    ]
                }
            }
        },
        "TestGetMethod": {
            "Type": "AWS::ApiGateway::Method",
            "Properties": {
                "HttpMethod": "GET",
                "RestApiId": {
                    "Ref": "RestApi"
                },
                "ResourceId": {
                    "Ref": "TestResource"
                },
                "AuthorizationType": "NONE",
                "RequestParameters": {
                    "method.request.querystring.value": "True",
                    "method.request.header.Accept": "True"
                },
                "MethodResponses": [
                    {
                        "StatusCode": "200"
                    }
                ],
                "Integration": {
                    "Type": "AWS",
                    "Uri": {
                        "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${TestLambda.Arn}/invocations"
                    },
                    "IntegrationHttpMethod": "POST",
                    "RequestParameters": {
                        "integration.request.querystring.value": "method.request.querystring.value",
                        "integration.request.header.Accept": "method.request.header.Accept"
                    },
                    "RequestTemplates": {
                        "application/json": "{\"value\":\"$input.params('value')\"}"
                    },
                    "PassthroughBehavior": "NEVER",
                    "IntegrationResponses": [
                        {
                            "SelectionPattern": ".*",
                            "StatusCode": "200"
                        }
                    ]
                }
            }
        },
        "TestLambdaPermission": {
            "Type": "AWS::Lambda::Permission",
            "Properties": {
                "Action": "lambda:InvokeFunction",
                "FunctionName": {
                    "Ref": "TestLambda"
                },
                "Principal": "apigateway.amazonaws.com",
                "SourceArn": {
                    "Fn::Sub": "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*"
                }
            }
        },
        "ApiDeployment": {
            "DependsOn": [
                "TestGetMethod"
            ],
            "Type": "Custom::ApiDeployment",
            "Properties": {
                "ServiceToken": {
                    "Fn::GetAtt": [
                        "DeploymentLambda",
                        "Arn"
                    ]
                },
                "RestApiId": {
                    "Ref": "RestApi"
                },
                "StageName": "production",
                "DeploymentTime": {
                    "Ref": "DeploymentTime"
                }
            }
        },
        "CloudformationDistribution": {
            "Type": "AWS::CloudFront::Distribution",
            "Properties": {
                "DistributionConfig": {
                    "Aliases": [
                        {
                            "Ref": "DomainName"
                        }
                    ],
                    "ViewerCertificate": {
                        "SslSupportMethod": "sni-only",
                        "AcmCertificateArn": "arn:aws:acm:us-east-1:083845954160:certificate/0cc193a9-9489-47ce-b7b3-8213a4c434d1"
                    },
                    "Enabled": "true",
                    "HttpVersion": "http2",
                    "Origins": [
                        {
                            "DomainName": {
                                "Fn::Sub": "${RestApi}.execute-api.${AWS::Region}.amazonaws.com"
                            },
                            "OriginPath": "/production",
                            "Id": "APIGATEWAY",
                            "CustomOriginConfig": {
                                "OriginProtocolPolicy": "https-only"
                            }
                        }
                    ],
                    "DefaultCacheBehavior": {
                        "TargetOriginId": "APIGATEWAY",
                        "Compress": true,
                        "AllowedMethods": [
                            "DELETE",
                            "GET",
                            "HEAD",
                            "OPTIONS",
                            "PATCH",
                            "POST",
                            "PUT"
                        ],
                        "ForwardedValues": {
                            "QueryString": "true",
                            "Cookies": {
                                "Forward": "none"
                            },
                            "Headers": [
                                "Accept",
                                "Content-Type",
                                "Authorization"
                            ]
                        },
                        "DefaultTTL": 0,
                        "MaxTTL": 0,
                        "MinTTL": 0,
                        "ViewerProtocolPolicy": "redirect-to-https"
                    }
                }
            }
        },
        "DNSRecord": {
            "Type": "AWS::Route53::RecordSetGroup",
            "Properties": {
                "Comment": "Z09377931HZWDHZB7ST9N在Route53上創(chuàng)建托管區(qū)域",
                "HostedZoneId": "Z09377931HZWDHZB7ST9N",
                "RecordSets": [
                    {
                        "Name": {
                            "Ref": "DomainName"
                        },
                        "Type": "A",
                        "AliasTarget": {
                            "HostedZoneId": "Z2FDTNDATAQYW2",
                            "DNSName": {
                                "Fn::GetAtt": [
                                    "CloudformationDistribution",
                                    "DomainName"
                                ]
                            }
                        }
                    }
                ]
            }
        } 
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末陨帆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子采蚀,更是在濱河造成了極大的恐慌疲牵,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件榆鼠,死亡現(xiàn)場離奇詭異纲爸,居然都是意外死亡,警方通過查閱死者的電腦和手機妆够,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進店門识啦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人神妹,你說我怎么就攤上這事颓哮。” “怎么了鸵荠?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵冕茅,是天一觀的道長。 經(jīng)常有香客問我,道長姨伤,這世上最難降的妖魔是什么哨坪? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮姜挺,結(jié)果婚禮上齿税,老公的妹妹穿的比我還像新娘彼硫。我一直安慰自己炊豪,他們只是感情好,可當我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布拧篮。 她就那樣靜靜地躺著词渤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪串绩。 梳的紋絲不亂的頭發(fā)上缺虐,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天,我揣著相機與錄音礁凡,去河邊找鬼高氮。 笑死,一個胖子當著我的面吹牛顷牌,可吹牛的內(nèi)容都是我干的剪芍。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼窟蓝,長吁一口氣:“原來是場噩夢啊……” “哼罪裹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起运挫,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤状共,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后谁帕,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體峡继,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年匈挖,在試婚紗的時候發(fā)現(xiàn)自己被綠了鬓椭。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡关划,死狀恐怖小染,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情贮折,我是刑警寧澤裤翩,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響踊赠,放射性物質(zhì)發(fā)生泄漏呵扛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一筐带、第九天 我趴在偏房一處隱蔽的房頂上張望今穿。 院中可真熱鬧,春花似錦伦籍、人聲如沸蓝晒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽芝薇。三九已至,卻和暖如春作儿,著一層夾襖步出監(jiān)牢的瞬間洛二,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工攻锰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留晾嘶,地道東北人。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓娶吞,卻偏偏與公主長得像垒迂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子寝志,可洞房花燭夜當晚...
    茶點故事閱讀 43,543評論 2 349