tomcat的總結

classLoader

commonLoader:加載的jar可以提供給tomcat本身和其下面各個項目使用
catalinaLoader:加載的jar只能提供給tomcat本身
sharedLoader:加載的jar包可以給各個項目使用
他們三個都是urlclassloader類型

在bootStrap啟動期間 將線程上下文的classloader設置為catalinaLoader鸣皂,
并使用catalinaLoader加載我們的catalina這個類寞缝,這就意味著這個類不會被我們項目中使用
然后后期都是調用catalina方法的load和start方法來啟動tomcat,此外我們還將catalina的parentClassLoader設置為sharedLoader
這是為了后期設置weappclassloader的父類埋下伏筆

相關名詞解釋

catalina.home:tomcat產品的安裝目錄被啼,bin 和 lib 目錄被多個tomcat示例公用
catalina.base:是tomcat啟動過程中需要讀取的各種配置及日志的根目錄泡挺,其它目錄conf娄猫、logs媳溺、temp、webapps和work 每個Tomcat實例必須擁有其自己獨立的備份碍讯。
實現在一臺機器上運行多個tomcat實例的目的悬蔽。
主要就是利用catalina.base,因為它是Tomcat啟動過程中讀取各自配置的根目錄
java.io.tmpdir:獲取操作系統緩存的臨時目錄捉兴,不同操作系統的緩存臨時目錄不一樣蝎困。
user.dir:則是獲取當前tomcat容器啟動的位置

SystemLogHandler:

startCapture方法:首先從resume(stack)中獲取一個captureLog對象,如果該stack為空則new一個captureLog對象然后從logs(threadLocal)獲取stack<caputure>對象轴术,如果為空則創(chuàng)建一個
stopCapture方法:從threadlocal獲取stack<caputure>难衰,然后彈出一個CaptureLog 然后寫出期間的打印信息
重置CaptureLog存入reuse钦无。
這個SystemLogHanlder彼宠,可以收集一段代碼內的打印信息摧冀,然后統一輸出且不影響性能。

appBase和docBase的區(qū)別

 <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
<Context path="" docBase="D:\WebContent" sessionCookiePath="/" sessionCookieName="JSESSIONID" />

appBase:

1.appBase是host的屬性潮罪,其會自動部署appbase指定的目錄的項目

docBase

1.docBase是context的屬性月洛,指定這個項目的路徑(絕對或相對路徑)
2.訪問路徑我們可以通過path指定

外置的Tomcat的啟動過程:

一隔崎、bootStrap的靜態(tài)代碼塊和初始化:

1.靜態(tài)代碼塊:主要就是設置catalina.home和catalina.base,其中獲取了user.dir 作為上述2個參數未設置時候的備選方案
2.init方法:初始化三個主要的classloader撵彻,設置線程上下文的classloader為catalinaLoader生成catalina對象,并將sharedLoader設置為其parentClassLoader

二、調用catalina的load方法

1.初始化工作時候的temp目錄-java.io.tmpdir
2.初始化jndi相關的目錄
3.創(chuàng)建Digester對象,并使用該對象解析server.xml文件,最終創(chuàng)建Server對象
4.設置server的屬性督弓,catalina蒜危,catalinaHome和catalinaBase
5.優(yōu)化system.out和system.error
6.調用server的init方法

三、調用catalina的start方法

1.server的start方法調用
2.如果需要使用鉤子則注冊一個CatalinaShutdownHook纵刘,該鉤子會在觸發(fā)的時候調用catalina的stop方法
惧蛹,該方法會先刪除鉤子(因為有可能不是鉤子線程調用的stop方法,這樣會導致stop調用兩次)然后調用server的stop和destory方法双抽。
3.然后調用await和stop方法
4.await方法主要就是根據通過循環(huán)判斷標識位來判斷是否需要結束tomcat或者通過socket監(jiān)聽關閉端口來判斷

內置的Tomcat啟動過程

一睬棚、創(chuàng)建WebServer(內部包含tomcat類篱瞎,所以這個webServer類似于Facade)

1.創(chuàng)建tomcat類。該類主要是服務于內置或者測試的starter竖慧,包含我們基礎配置信息,也是用來啟動我們的server服務,并且可以添加container的類角溃。
2.設置tomcat的baseDir
3.設置connector左冬,默認協議是Http11NioProtocol類
4.創(chuàng)建一個standardserver,設置catalina.home和catalina.base
5.創(chuàng)建一個standardService,將connector和service互相綁定板鬓。
6.調整connector屬性悟耘,比如端口鹰服,還有就是如果我們配置了地址屠尊,則協議需要綁定該地址,還有就是給connector
設置uriEncoding,ssl摇予。還有是給協議設置compression。
7.我們也可以通過實現TomcatConnectorCustomizer接口來優(yōu)化connector或者其內部協議隆圆,比如修改adpter或者endpoint
8.當然還有這個TomcatContextCustomizer接口 我們可以優(yōu)化我們的context
9.上述的兩個customizer秃踩,我們可以寫個BeanPostProcessor台谢,在TomcatServletWebServerFactory初始化之后筋夏,調用其add方法添加
10.將被自定義修改后的connector和service中的connector進行對比丢烘,如果對象被替換了 就將新的connector加入到service中否則就不用添加
11.禁止host自動部署犀暑,在設置engine的是設置了該engine的默認的host為localhost和realm
12.配置engine,首先設置backGroupProcessorDelay時長洪唐,這個會啟動一個線程每隔一段時間執(zhí)行后臺任務
13.給engine設置valve
14.我們還可以給該service添加我們額外寫的connector
15.設置我們context=TomcatEmbeddedContext枯怖,設置name和path,displayName,指定docBase
16.添加lifeCycleListeners和parentClassloader捌治,設置webApploader(我們的webappclassLoader的創(chuàng)建者)县袱,以及webappclassLoader的類型TomcatEmbeddedWebappClassLoader
17.將webApploader的加載模式設置為true,這就代表我們的這邊webappclassLoader采用的是雙親加載模式
18.注冊DefaultServlet鲸沮,將tomcatStarter和context綁定,配置context的valve憎亚,修改我們的context
19.最終將tomcat和port包裝成tomcatWebServer返回驴剔,在tomcatWebServer的構造函數中好友初始化方法
20.該初始化方法主要是:啟動tomcat的container,但是會刪除connector這樣就可以避免connector也被啟動,啟動一個后臺線程每隔一段時間去檢測是否關閉標識奄抽。

二抑胎、啟動webServer

1.添加我們上述被刪除的connector
2.啟動我們的connector

tomcat啟動過程就是 調用Server的init方法和start方法,所以我們著重分析這兩個方法

一诵闭、server的init:

1.standardserver的init方法

  • 設置JMX相關類
  • 設置全局的字符串緩存
  • 初始化globalNamingResources
  • 從我們的sharedLoader中獲取jar包資源時報包含MANIFEST晤郑,如果包含則添加到容器的集合中
  • 初始化service的init方法

2.service的init方法

  • engine的初始化
  • 線程池的初始化
  • mapperlistener的初始化
  • connector的初始化

3.engine的初始化(少了host,context晰绎,wrapper的初始化陨簇,他們的初始化都是在各自start的時候先進行進行的)

  • 創(chuàng)建Realm
  • 重新配置startStopExecutor蔓涧,其主要是幫忙啟動和關閉子容器

4.host的初始化

  • 配置startStopExecutor

5.context的初始化

  • 配置startStopExecutor
  • namingResources初始化

6.wrapper的初始化

  • 配置startStopExecutor

7.connector的初始化

  • 創(chuàng)建adapter并和protocolhandler綁定件已,其主要是用來獲取httpServeletRequest和httpServeletResponse
  • 設置默認的解析bodymethod==post
  • protocolHandler的初始化

8.protocolHandler的初始化

  • 判斷是否需要升級協議
  • 創(chuàng)建endpoint并初始化
  • enpoint可以理解為專門負責處理socket,類似于netty的服務端或者客戶端boostrap
  1. Nioendpoint的初始化-實際是調用bind方法
  • 創(chuàng)建socket并給socket設置相關屬性元暴,比如接受和發(fā)送的緩沖區(qū)大小篷扩,超時,拒絕連接的地址等
  • 讓該socket綁定我們設置好的地址和端口昨寞,同時還設置了backlog=accpetAccount瞻惋,也就是說最大可以有一定數目的
    即將要連接的該socket,超過就拒絕援岩。這個backlog對應的accept queue
  • 設置該通道為非阻塞模式
  • 設置acceptorThreadCount(也就是acceptor線程默其專門獲取socket連接)認為1歼狼,其對應我們的acceptor線程大小類似于nioeventloop,根據我們對netty的了解就算設置多了意義也不大
  • 設置pollerThreadCount最小為1享怀,其是專門接受acceptor線程傳遞過來的socket羽峰,然后將該scoekt注冊到selector上面
  • 初始化ssl
  • 創(chuàng)建共享selector,然后創(chuàng)建一個NioBlockingSelector去包裹該selector
  • NioBlockingSelector包含一個共享的多路復用器,BlockPoller線程
  • BlockPoller線程的作用:專門處理ssl的channel上面注冊的blocking的socket,其他的非ssl裁員poller線程去注冊

二梅屉、server的start:

1.server的start方法

  • 激活configure_start監(jiān)聽事件
  • 設置狀態(tài)為start
  • 調用globalNamingResources的start方法
  • 調用service的start方法

2.service的start方法

  • 設置start啟動標識
  • 啟動engine
  • 啟動線程池
  • 啟動mapperListener
  • 啟動connector
  1. engine的start

啟動realm

  • 迭代啟動子容器
  • 啟動pipeline,設置啟動標識值纱,也就是給pipeline添加基本的vavle,并啟動vavle(也就是設置啟動標識)
  • 每個容器都有一個starnardpipeline,每個容器都有一個baiscvavlve--standardXXvalve坯汤,他們的主要任務是
    連接當前容器的子容器
  • 啟動ContainerBackgroundProcessor線程執(zhí)行后臺任務(目前只有engine容器可以啟動該線程虐唠,其他子類沒有)
  • ContainerBackgroundProcessor的處理邏輯:對于container為context的容器 先調用其bind方法
  • 調用所有container的backgroundProcess方法,而各個container的backgroundProcess內部還包含其他組建的backgroundProcess
    比如cluster,realm,valve,Loader,Manager,WebResourceRoot,InstanceManager等
  • 而context容器的bind方法的作用就是就是確保我們的webApploader中的webAppClassLoader與線程上下文的classloader一致
    不一致的話就設置為一樣的惰聂。這樣的話我們熱部署的時候classloader的變更 進而可以進行體會線程上下文中的classloader
  1. host的start方法
  • 配置errorValve
  • start子容器
  • start我們的pipeline
  1. context的start方法
  • 給該項目設置工作目錄
  • 設置WebResourceRoot并調用其start方法 主要是將這個context中的文件比如class和配置文件變成WebResource
    留給classloader去加載
  • 創(chuàng)建WebappLoader,并設置其內部的WebappClassLoader的加載模式為非雙親加載模式
  • 檢測context中的mainest文件疆偿,設置NamingContextListener
  • 啟動WebappLoader的start方法主要就是創(chuàng)建WebAppClassLoader,設置加載模式 classPaths搓幌,將classes和lib下面的
    資源放入到localRepositories中
  • 設置WebAppClassLoader的屬性杆故,然后將該classloader放入到線程上下文后期只要碰到任何需要加載的類都采用我們的classloader
  • 啟動子容器
  • 啟動pipeline
  • 將sources,jarScanner放入到servletContext
  • 執(zhí)行ServletContainerInitializer的onStarup方法
  • 啟動filter和servlet
  • 將webAppClassLoader替換為原始的classloader
    -通過監(jiān)聽者ContextConfig的webConfig和applicationAnnotationsConfig方法加載項目 首先生成對應的web.xml文件(先從項目中尋找溉愁,沒有在獲取全局的) 然后獲取利用spi機制去各個jar包中尋找META-INF/services/javax.servlet.ServletContainerInitializer 文件獲取ServletContainerInitializer处铛,這邊使用webappclassloader去加載。 然后加載所有的/WEB-INF/classes的class拐揭,主要是處理這些class中的annotation/WebServlet 撤蟆,annotation/WebFilter,annotation/WebListener投队。 然后在處理所有的lib目錄的jar包枫疆,最后添加我們ServletContainerInitializer
  • 回收resouce中的資源
  1. wrapper的start方法
  • 啟動器內部的cluster ,realm敷鸦,pipeline和子容器的start方法
  • 設置available=0代表可用

7.connector的start方法

  • 檢測端口是否符合要求
  • 啟動protocolHandler的start方法

8.protocolHandler的start方法

  • 啟動endpoint的start方法
  • 啟動一個異步線程AsyncTimeout,每隔1秒去檢測我們的異步處理的Processor是否超時寝贡,如果超時則執(zhí)行超時操作
  • 該線程的優(yōu)先級被設置為normal扒披,且是后臺線程
  1. Nioendpoint的start方法
  • 設置nioendpoint的啟動標識
  • 設置processorCache,EventCache,nioChannels三個緩存
  • 如果我們的tomcat沒有設置線程池 則我們自己創(chuàng)建worker線程池
  • 線程池的屬性有minspareThreads圃泡,maxThreads
  • 設置maxConnection的大小默認是1萬
  • 創(chuàng)建poller線程碟案,數量可以設置
  • 每個poller包含獨立的多路復用器,他們從acceptor線程獲取socket注冊到自己的多路復用器颇蜡,其類似于nioeventloop
  • 開啟acceptor線程

三价说、tomcat接受處理請求的全流程

-一、Acceptor線程攜帶endpoint风秤,不斷的循環(huán)獲取socketChannel

  • 1.首先判斷endPoint是否還在running鳖目,如果不是則跳出循環(huán)
  • 2.如果當前endpoint是暫停且還在running狀態(tài)則現場沉睡50毫秒
  • 3.在正式獲取socketChannel的時候需要先去獲取connection(通過maxConnection限制)
  • 4.socketChannel是一個channel,獲取的過程中如果發(fā)生io異常需要設置下errorDelay缤弦,即讓主線程沉睡一會
  • 5.當我們獲取到socketchannel則需要綁定到poller線程上领迈,綁定失敗或者acceptor線程暫停或者關閉 則需要關閉該通道

-二、將socketChannel包裝成Niochannel交給poller線程

  • 1.將socketChannel設置為非阻塞
  • 2.將socket的屬性填充=超時狸捅,接受和發(fā)送buffer(屬于socket的buffer)衷蜓,ReuseAddress ,tcpNoDelay等
  • 3.嘗試從緩存獲取niochannel尘喝,并創(chuàng)建了一個SocketBufferHandler磁浇,其實作為applicaiton的buffer(包含發(fā)送,接受和堆外的buffer)
  • 4.最終我們將SocketBufferHandler和socketchannel包裝成niochannel注冊到poller線程上
  • 5.注冊過程就是講我們的niochannel和nioendpoint包裝成NioSocketWrapper
  • 6.然后給NioSocketWrapper設置poller線程朽褪,timeout扯夭,alive,ssl等屬性,并注冊read事件
    1. 從eventCache緩存中獲取pollerEvent鞍匾,并集成niochannel交洗,NioSocketWrapper和注冊事件。
  • 8.然后將該pollerEvent放入poller線程的events內部集合橡淑,如果wakeupCounter=-1 則代表當前poller線程在沉睡我們需要喚醒

-三构拳、Poller線程的run方法-將后續(xù)獲取到的事件(鏈接事件)交給SocketProcessorBase處理

  • 1.從我們的events集合中循環(huán)的執(zhí)行PollerEvent的run和reset方法 然后將PollerEvent放入eventCache
  • 2.run方法:第一次執(zhí)行都是將我們的channel注冊到該poller內部的多路復用器
  • 3.reset方法:情況pollerEvent內部對象
  • 4.設置wakeupCounter為-1 如果之前的值是大于0代表已經有其他的event加入進來 我們直接selectNow否則阻塞獲取事件
  • 5.設置wakeupCounter為0 然后判斷是否該線程已經關閉如果是的話則cancel 所有已經發(fā)生的SelectionKey然后關閉多路復用器再跳出循環(huán)
  • 6.否則判斷是否有對應的SelectionKey或者其他的event加入
  • 7.先處理SelectionKey,然后在查看是否超時
  • 8.只有處理以下幾種情況的timeout:nextExpiration已經過了梁棠,沒有selectionKey或者其他event加入 或者socket已經開始clsoe
  • 9.處理selectionkey的邏輯是:如果已經close了 則直接cancel置森,否則檢測sk是否有效且需要攜帶附件,只處理讀寫事件
  • 10.如果附件攜帶文件符糊,則調用filechannel的transTo方法進行處理凫海,其他事件則當成socket進行處理。
  • 11.在處理sk中攜帶文件之前需要先取消之前該channel注冊的事件男娄,等待處理完成在且是支持keepalive的則重新注冊該channel否則直接關閉
  • 12.對于attacheMent是非文件的則先取消之前該channel注冊的事件行贪,并不會重新注冊 因為事件已經處理完畢
  • 13.上述attacheMent是非文件是先處理read在處理write,如果處理失敗就直接cancel
  • 14.然后從processorCache獲取SocketProcessorBase模闲,根據是否支持dispatch以及是否存在線程池來決定剩余的處理
    是否在poller線程中做還是交給cotainer的線程池

-四建瘫、SocketProcessorBase的處理流程

  • 1.首先進行ssl握手
  • 2.獲取對應的handler進行處理
  • 3.對應的handler獲取合適的Processor
  • 4.調用Processor的process進行處理,最終交給service方法
  • 五尸折、Processor的service方法邏輯
  • 1.獲取requestIno啰脚,設置請求的stage,設置input和output的buffer
  • 2.默認是支持keepAlive实夹,讀取請求的數據
  • 3.最終通過adapter的service方法傳遞我們的原始request和response
  • 六橄浓、然后將在第五步得到request和response交給Adapter(CoyoteAdapter),調用其service方法處理
  • 1.首先將request和response轉換成HttpServletRequest和HttpServletResponse
  • 2.獲取connector 通過connector得到container的vavle亮航,然后交給他們執(zhí)行
  • 七荸实、最終一層層調用到我們的standardWrapperValve的invoke方法
  • 1.獲取對應的servlet,這邊就是我們的dispatchServlet
  • 2.執(zhí)行dispatchServlet的service方法塞赂,在此之前先執(zhí)行過濾器
  • 3.我們的controller方法被映射成地址和我們的請求地址匹配泪勒,最終可以得到method 進而反射執(zhí)行方法完成調用

server.xml文件的各個標簽的意義

我們的engine標簽會配置一個默認的host
名稱一般都是localhost昼蛀,當我們用localhost去請求的時候
我們本地的系統有hosts配置文件可以將我們的localhost解析為實際的ip
默認都是127.0.0.1,當然我們也可以配置localhost1等127.0.0.1

MANIFEST

一般編寫MANIFEST.MF文件只需要用到Manifest-Version(MF文件版本號)
圆存、Main-Class(包含main方法的類)叼旋、Class-Path(執(zhí)行這個jar包時的ClassPath,第三方依賴)
比如下面:
Manifest-Version: 1.0
Main-Class: test.Main
Class-Path: ./ ./lib/commons-collections-3.2.jar ./lib/commons-dbcp-1.2.2.jar ./lib/commons-lang-2.3.jar ./lib/commons-logging-1.1.jar

Tomcat中的backlog參數

在linux 2.2以前沦辙,backlog大小包括了半連接狀態(tài)和全連接狀態(tài)兩種隊列大小夫植。
linux 2.2以后,分離為兩個backlog來分別限制半連接SYN_RCVD狀態(tài)的未完成連接隊列大小
跟全連接ESTABLISHED狀態(tài)的已完成連接隊列大小油讯。
當服務端接受到客戶端的syn請求后放入syns的隊列中详民,然后服務端回復syn+ack,等客戶端收到ack后 再回復ack給服務端
則服務的就把sync中的半連接放入到accpet queue陌兑。一般backlog=完全隊列
我們完全隊列大小取值=min(backlog,somaxconn)
我們半完全隊列大小=
table_entries = min(min(somaxconn沈跨,backlog),tcp_max_syn_backlog)
roundup_pow_of_two(table_entries + 1)
roundup_pow_of_two表示取最近的2的n次方的值,舉例來說:假設somaxconn為128兔综,backlog值為50饿凛,tcp_max_syn_backlog值為4096,則第一步計算出來的為50软驰,
然后roundup_pow_of_two(50 + 1),找到比51大的2的n次方的數為64涧窒,所以最終半連接隊列的長度是64。

connector容易混淆的名詞解釋

acceptorThreadCount:代表從socket的完全隊列獲取socket連接的線程數锭亏,其socket連接交給poller
pollerThreadCount:將該socket注冊到selector上面纠吴,然后捕捉到后續(xù)的讀寫事件交給worker線程處理
maxThreads:則是指worker線程--真正去處理這些socket請求的線程個數
acceptCount: 代表acceptor線程從tcp完全隊列里面取connection的限制(因為acceptorCount限制了隊列大小)
maxConnections:每當獲取到一個socket就代表得到一個connection慧瘤,然后該connection只有在完成或者某些異常情況下才釋放
戴已,從這個角度來說如果不限制connection我們不停的拿socket處理也是不行的,這就是從java層面控制

Tomcat的reload機制

  • 1.WebappLoader的backgroundProcess方法
  • 2.首先檢測是否支持熱部署碑隆,其次檢測項目是否有變化
  • 3.變化的依據是檢測jar包和我們的其他文件的變更時間恭陡,如果不一致則將當前的線程上下文中的classloader替換為加載
    webApploader的classloader 也就是我們的sharedLoader
  • 4.然后調用standardContext的reload方法去加載
  • 5.加載完成后將線程上下文的加載器設置為webAppclassloader

reload方法的主要邏輯

  • 設置暫停標識,可以讓request請求休息1秒
  • 獲取老的classloader 關閉后臺線程(由于context沒有后臺線程所以不用關閉)
  • 獲取context的子容器進行stop
  • 關閉過濾器和manager 等等
  • 然后重新調用start方法 上煤,設置paused為false
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市著淆,隨后出現的幾起案子劫狠,更是在濱河造成了極大的恐慌,老刑警劉巖永部,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件独泞,死亡現場離奇詭異,居然都是意外死亡苔埋,警方通過查閱死者的電腦和手機懦砂,發(fā)現死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人荞膘,你說我怎么就攤上這事罚随。” “怎么了羽资?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵淘菩,是天一觀的道長。 經常有香客問我屠升,道長潮改,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任腹暖,我火速辦了婚禮汇在,結果婚禮上,老公的妹妹穿的比我還像新娘脏答。我一直安慰自己糕殉,他們只是感情好,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布以蕴。 她就那樣靜靜地躺著糙麦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪丛肮。 梳的紋絲不亂的頭發(fā)上赡磅,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天,我揣著相機與錄音宝与,去河邊找鬼焚廊。 笑死,一個胖子當著我的面吹牛习劫,可吹牛的內容都是我干的咆瘟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼诽里,長吁一口氣:“原來是場噩夢啊……” “哼袒餐!你這毒婦竟也來了?” 一聲冷哼從身側響起谤狡,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤灸眼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后墓懂,有當地人在樹林里發(fā)現了一具尸體焰宣,經...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年捕仔,在試婚紗的時候發(fā)現自己被綠了匕积。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盈罐。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖闪唆,靈堂內的尸體忽然破棺而出盅粪,到底是詐尸還是另有隱情,我是刑警寧澤苞氮,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布湾揽,位于F島的核電站,受9級特大地震影響笼吟,放射性物質發(fā)生泄漏库物。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一贷帮、第九天 我趴在偏房一處隱蔽的房頂上張望戚揭。 院中可真熱鬧,春花似錦撵枢、人聲如沸民晒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽潜必。三九已至,卻和暖如春沃但,著一層夾襖步出監(jiān)牢的瞬間磁滚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工宵晚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留垂攘,地道東北人。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓淤刃,卻偏偏與公主長得像晒他,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子逸贾,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內容

  • 從三月份找實習到現在陨仅,面了一些公司,掛了不少铝侵,但最終還是拿到小米掂名、百度、阿里哟沫、京東、新浪锌介、CVTE嗜诀、樂視家的研發(fā)崗...
    時芥藍閱讀 42,253評論 11 349
  • 概念 Java Web猾警,是基于Java語言實現web服務的技術總和。介于現在Java在web客戶端應用的比較少隆敢,我...
    胥垣閱讀 1,444評論 0 8
  • 這是我們分析tomcat的第八篇文章发皿,這次我們分析連接器,我們早就想分析連接器了拂蝎,因為各種原因拖了好久穴墅。不過也確實...
    莫那一魯道閱讀 1,993評論 0 7
  • 沉默揮別了過往 寒露氤氳閑情萬種 不愿回首 夢境臆想的虛無 窗欞隔絕了歡暢 夢醒相約佳話 于塵世中流連 情意何來始...
    白從嬰閱讀 516評論 0 2
  • 感恩今天丫豆姐和培培姐今天給我做身體,練手法温自,相信你們可以越來越好玄货,因為你們本來就很棒,相信自己悼泌,我們一起...
    enhui1994閱讀 214評論 0 1