AWS EC2+Docker+JMeter構(gòu)建分布式負(fù)載測試基礎(chǔ)架構(gòu)

歡迎關(guān)注微信公眾號 軟測小生 (←直接點擊)

原文鏈接

概述及范圍

本文介紹有關(guān)如何使用AWS EC2+Docker+JMeter創(chuàng)建分布式負(fù)載測試基礎(chǔ)架構(gòu)蚜枢。
完成所有步驟后,得到的基礎(chǔ)結(jié)構(gòu)如下:


AWS EC2+Docker+JMeter基礎(chǔ)架構(gòu)

Part 1中鉴未,我們將按照所需的步驟進(jìn)行操作,以創(chuàng)建適合你需求的自定義JMeter Dockerfiles和映像。
然后,在Part 2中辟犀,我們將在AWS EC2設(shè)置中使用這些元素。
接下來開始第一步:

前提條件

為了能夠順利的逐步進(jìn)行配置和操作绸硕,你需要上述每個系統(tǒng)(EC2堂竟,Docker和JMeter)的一些基本知識。
此外玻佩,還需要一個活動的AWS賬戶才能執(zhí)行所有步驟出嘹。

Part 1: Local setup—本地配置

Step 1: 從Dockerfile創(chuàng)建映像

dockerfile是開始使用docker所需的基本元素或“ cookbook”,因此我們將從此開始咬崔。
我們需要建立2層:
1税稼、一是基礎(chǔ)層,該層創(chuàng)建運行JMeter實例所需的基本設(shè)置;
2娶聘、二是邏輯層闻镶,它是一個JMeter實例,可以是主節(jié)點或從節(jié)點丸升;

JMeter base映像的Dockerfile和entrypoint.sh腳本如下所示:
Dockerfile:

# Use Java 11 JDK Oracle Linux
FROM openjdk:11-jdk-oracle
MAINTAINER Dragos
# Set the JMeter version you want to use
ARG JMETER_VERSION="5.1.1"
# Set JMeter related environment variables
ENV JMETER_HOME /opt/apache-jmeter-${JMETER_VERSION}
ENV JMETER_BIN ${JMETER_HOME}/bin
ENV JMETER_DOWNLOAD_URL https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-${JMETER_VERSION}.tgz
# Set default values for allocation of system resources (memory) which will be used by JMeter
ENV Xms 256m
ENV Xmx 512m
ENV MaxMetaspaceSize 1024m
# Change timezone to local time
ENV TZ="Europe/Bucharest"
RUN export TZ=$TZ
# Install jmeter
RUN yum -y install curl \
&& mkdir -p /tmp/dependencies \
&& curl -L --silent ${JMETER_DOWNLOAD_URL} >  /tmp/dependencies/apache-jmeter-${JMETER_VERSION}.tgz \
&& mkdir -p /opt \
&& tar -xzf /tmp/dependencies/apache-jmeter-${JMETER_VERSION}.tgz -C /opt \
&& rm -rf /tmp/dependencies
# Set JMeter home
ENV PATH $PATH:$JMETER_BIN
# copy our entrypoint
COPY entrypoint.sh /
RUN chmod +x ./entrypoint.sh
# Run command to allocate the default system resources to JMeter at 'docker run'
ENTRYPOINT ["/entrypoint.sh"

Entrypoint.sh:

#!/bin/bash
# Run command to allocate the default or custom system resources (memory) to JMeter at 'docker run'
sed -i 's/\("${HEAP:="\)\(.*\)\("}"\)/\1-Xms'${Xms}' -Xmx'${Xmx}' -XX:MaxMetaspaceSize='${MaxMetaspaceSize}'\3/' ${JMETER_BIN}/jmeter
exec "$@"

在基礎(chǔ)層之上铆农,可以創(chuàng)建一個Master層和一個Slave層。這些Dockerfile可以根據(jù)你的特定要求進(jìn)行自定義狡耻。
現(xiàn)在讓我們看一下我們的邏輯層:
Master層的Dockerfile:

# Use my custom base image defined above
FROM dragoscampean/testrepo:jmetrubase
MAINTAINER Dragos
# Expose port for JMeter Master
EXPOSE 60000

Slave層的Dockerfile:


# Use my custom base image defined above
FROM dragoscampean/testrepo:jmetrubase
MAINTAINER Dragos
# Expose ports for JMeter Slave
EXPOSE 1099 50000
COPY entrypoint.sh /
RUN chmod +x ./entrypoint.sh
# Run command to allocate the default system resources to JMeter at 'docker run' and start jmeter-server with all required parameters
ENTRYPOINT ["/entrypoint.sh"]

Slave層的Entrypoint.sh:

#!/bin/bash
# Run command to allocate the default system resources to JMeter at 'docker run'
sed -i 's/\("${HEAP:="\)\(.*\)\("}"\)/\1-Xms'${Xms}' -Xmx'${Xmx}' -XX:MaxMetaspaceSize='${MaxMetaspaceSize}'\3/' ${JMETER_BIN}/jmeter &&
$JMETER_HOME/bin/jmeter-server \
-Dserver.rmi.localport=50000 \
-Dserver_port=1099 \
-Dserver.rmi.ssl.disable=true \
-Djava.rmi.server.hostname=$HostIP
exec "$@"

我們不會詳細(xì)討論dockerfiles中的所有內(nèi)容的含義墩剖,在網(wǎng)上有很多這樣的文檔。不過值得一提的是與Dockerfiles綁定在一起的entrypoint shell腳本夷狰。

docker entrypoints的作用是在運行時將數(shù)據(jù)初始化或者配置到容器中岭皂。在我們的例子中,我們需要它們來指定JMeter允許使用多少內(nèi)存沼头,并使用一些自定義配置來啟動JMeter服務(wù)器爷绘,這些配置是基礎(chǔ)設(shè)施工作所必需的。這將在“Step 2”部分中舉例說明进倍。

現(xiàn)在土至,讓我們看一下創(chuàng)建Docker映像所需的命令。順便說一下猾昆,Docker圖像表示一組很好地集成在一起的層陶因,是我們需要的環(huán)境的穩(wěn)定快照。
從這樣一個映像開始垂蜗,我們可以生成N個容器楷扬,這正是我們在這個特定場景中所需要的,這取決于我們想要模擬的負(fù)載贴见。

創(chuàng)建一個簡單的docker映像的命令:
docker build /path/to/dockerfile

為docker映像創(chuàng)建一個標(biāo)簽:
docker tag imageId username/reponame:imageTag

同時創(chuàng)建docker映像和標(biāo)簽:
docker build -t username/reponame:imageTag /path/to/dockerfile

Step 2: 從一個映像創(chuàng)建一個容器

現(xiàn)在我們已經(jīng)準(zhǔn)備好映像烘苹,可以開始從中創(chuàng)建容器,在其中可以實際運行性能測試腳本蝇刀。
創(chuàng)建一個新的容器:
sudo docker run -dit --name containername repository:tag or imageId /bin/bash

啟動/停止容器:
docker start containerId
docker stop containerId

訪問正在運行的容器:
docker exec -it containerId or containerName /bin/bash

到目前為止螟加,如果你一直使用類似于Step 1中提供的Dockerfile,那么您應(yīng)該擁有一個完全可用的Java + JMeter容器吞琐。 你可以通過檢查工具版本來測試它捆探,看看是否有任何錯誤,甚至可以嘗試運行你計劃在AWS中擴展的腳本(所有這些都應(yīng)該在運行的容器中完成):
Jmeter -v
Java -version
Jmeter -n -t -J numberOfThreads=1 /path/to/script.jmx -l /path/to/logfile.jtl

Step 3: 將映像Push/Pull到Dockerhub或任何私有的Docker倉庫(docker登錄CLI后)

測試創(chuàng)建的圖像是否符合要求的標(biāo)準(zhǔn)(容器內(nèi)的所有內(nèi)容),通常站粟,最好將此圖像保存到存儲庫中黍图。然后,你可以在后續(xù)隨時從那里提取它奴烙,而不必每次都從Dockerfile構(gòu)建它助被。

Push映像到dockerhub:
docker push username/reponame:imageTag

從dockerhub中Pull已存在的映像(例如jdk映像):
docker pull openjdk:version

到此為止剖张,這意味著您已經(jīng)為cloud setup準(zhǔn)備好了一組功能強大的JMeter從屬映像和主映像。

Part 2: Cloud端基礎(chǔ)架構(gòu)——Infrastructure

可以使用EC2免費層實例揩环,最多750小時/月搔弄,持續(xù)1年,因此有很多時間進(jìn)行試驗丰滑。
注意:對于下面提供的示例顾犹,我使用了Ubuntu Server 18.04 LTS實例,因此提供的命令可能無法在其他Linux發(fā)行版上使用褒墨。

Step 4: 創(chuàng)建安全組——Security Group

使容器內(nèi)的JMeter實例(master實例或slave實例)能夠通信炫刷,自定義安全組已定義并將其附加到每個主機:

入站規(guī)則(Inbound rules):

Security group inbound rules

出站規(guī)則(Outbound rules):
Security group outbound rules

注意:確保將要成為負(fù)載測試基礎(chǔ)結(jié)構(gòu)部分的所有實例分配給此安全組,否則它們可能無法相互通信郁妈。

Step 5: 創(chuàng)建一個IAM策略(可選)

假設(shè)您只需要一個由1個JMeter主節(jié)點和2個從節(jié)點組成的基礎(chǔ)架構(gòu)浑玛。在這種情況下,訪問每個實例并對其進(jìn)行配置(安裝docker +啟動容器)相對容易噩咪。

但是顾彰,如果需要處理的實例超過3個,會發(fā)生什么情況呢?

手動逐個配置變得極其乏味剧腻,手動并不是一個好主意拘央。
這時,你將需要一個系統(tǒng)书在,能夠管理你正在使用的大量容器。一些著名的工具拆又,如谷歌的Kubernetes儒旬,或者Rancher等工具。

由于當(dāng)前使用的是AWS帖族,因此這兩種解決方案似乎過于龐大了栈源,因為亞馬遜針對這一點提供了一個開箱即用的解決方案:
Run Command”功能使我們可以同時在多個EC2實例上執(zhí)行Shell腳本。因此竖般,我們不必訪問每個實例甚垦,安裝docker并一次一個實例地啟動容器。

能夠通過“Run Command”功能在EC2實例上執(zhí)行命令的唯一要求是涣雕,適當(dāng)?shù)腎AM角色已與該實例相關(guān)聯(lián)艰亮。我將IAM策略命名為“ EC2Command”,并為每個新創(chuàng)建的實例選擇了該策略(但是稍后可以通過“attach/replace role”功能將該角色分配給該實例):

為現(xiàn)有實例設(shè)置IAM策略

在實例創(chuàng)建時關(guān)聯(lián)IAM策略

當(dāng)您創(chuàng)建角色時挣郭,請確保將“AmazonEC2RoleforSSM”策略附加到您的角色上迄埃,這樣就可以了。
將權(quán)限關(guān)聯(lián)到IAM角色

現(xiàn)在您可以使用“Run command”功能對多個實例批量執(zhí)行腳本兑障。
這將我們帶入流程的下一步蕉汪。

Step 6: 在測試機器上安裝Docker

現(xiàn)在,你需要在EC2主機上安裝docker逞怨,以便可以啟動容器并將它們連接在一起以進(jìn)行分布式負(fù)載測試者疤。
直接使用命令(直接在Ubuntu上的實例終端中執(zhí)行):

sudo apt-get install  curl  apt-transport-https ca-certificates software-properties-common \
&& curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add \
&& sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
&& sudo apt-get update \
&& sudo apt-get install -y docker-ce \
&& sudo usermod -aG docker $USER \
&& sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \
&& sudo chmod +x /usr/local/bin/docker-compose \
&& sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

通過“Run command”執(zhí)行的Shell腳本:

#!/bin/bash
sudo apt-get install  curl  apt-transport-https ca-certificates software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install -y docker-ce
USER_DOCKER=$(getent passwd {1000..60000} | grep "/bin/bash" | awk -F: '{ print $1}')
sudo usermod -aG docker $USER_DOCKER

理想情況下,您將在多個EC2實例上運行第二個腳本叠赦,之后它們都將具有可用的Docker版本宛渐。
下一步是配置主節(jié)點和從屬節(jié)點:

Step 7: 配置主節(jié)點——Master Node

在某些情況下,你甚至不需要多個從屬節(jié)點來分布式運行測試眯搭,比如窥翩,當(dāng)你有一臺功能強大的主機并且該計算機能夠生成目標(biāo)的負(fù)載量時,對于這種特定情況鳞仙,不需要Step 8和Step 9寇蚊。對于這種情況,你甚至不想使用容器并直接在主機上安裝JMeter棍好。

但是仗岸,假設(shè)你確實需要一個Master + Slaves系統(tǒng),然后繼續(xù)啟動Master容器:
直接使用命令(直接在Ubuntu上的實例終端中執(zhí)行):

HostIP=$(ip route show | awk '/default/ {print $9}') \
&& docker pull dragoscampean/testrepo:jmetrumaster \
&& docker run -dit --name master --network host -e HostIP=$HostIP -e Xms=256m -e Xmx=512m -e MaxMetaspaceSize=512m -v /opt/Sharedvolume:/opt/Sharedvolume dragoscampean/testrepo:jmetrumaster /bin/bash

通過“Run command”執(zhí)行的Shell腳本:

#!/bin/bash
HostIP=$(ip route show | awk '/default/ {print $9}')
docker pull dragoscampean/testrepo:jmetrumaster
docker run -dit --name master --network host -e HostIP=$HostIP -e Xms=256m -e Xmx=512m -e MaxMetaspaceSize=512m -v /opt/Sharedvolume:/opt/Sharedvolume dragoscampean/testrepo:jmetrumaster /bin/bash

腳本的第一行將機器的私有IP存儲在變量“HostIP”中借笙。主的HostIP不用于任何目的扒怖,僅使用從屬節(jié)點的HostIP。我們將在Step 9看到具體要做什么∫导冢現(xiàn)在盗痒,請記住,你可以快速訪問每個容器中主機的專用IP地址低散。

第二行很簡單俯邓,只是從適當(dāng)?shù)膫}庫中獲取圖像。

最后一行創(chuàng)建我們將要使用的容器熔号。此命令中有一些要點:
1稽鞭、'--network host '命令啟用主機連網(wǎng),這意味著容器內(nèi)的應(yīng)用程序(JMeter)引镊,將在‘entrypoint.sh’腳本公開的端口上可用朦蕴。如果沒有它,我就無法進(jìn)行設(shè)置弟头。問題是吩抓,即使腳本是在從節(jié)點上執(zhí)行的,由于錯誤(java.rmi.ConnectException: Connection refused to host:masterPrivateIP)亮瓷,主節(jié)點上也沒有聚集任何結(jié)果琴拧。注意,我在較老版本的JMeter(如3.x.x)中沒有遇到這個問題

2嘱支、‘- e Xms=256m -e Xmx=512m -e MaxMetaspaceSize=512m’ 是Xms和Xmx的參數(shù)化蚓胸,MaxMetaspaceSize決定了允許使用JMeter的內(nèi)存量挣饥。這是通過首先在容器內(nèi)設(shè)置一些環(huán)境變量來完成的。然后沛膳,在“ entrypoint.sh”腳本中運行命令扔枫,將更改JMeter的“ / bin”文件夾中的“JMeter”文件。如果未指定這些值锹安,則使用默認(rèn)值短荐。

要進(jìn)一步了解這些變量代表什么以及如何設(shè)置它們,請閱讀以下內(nèi)容:
Xmx計算如下:系統(tǒng)總內(nèi)存-(OS使用的內(nèi)存+ JVM使用的內(nèi)存+在計算機上運行所需的任何其他腳本)
如果您有一臺專用的測試機器叹哭,為避免在測試運行時重新分配Xms忍宋,請從一開始就設(shè)置Xms = Xmx

MaxMetaspaceSize跟蹤所有加載的類元數(shù)據(jù)和靜態(tài)內(nèi)容(靜態(tài)方法风罩,原始變量和對象引用)

例如:
一臺專用機器上64 GB RAM
Xmx = 56G
Xms = 56G
MaxMetaspaceSize = 4096 MB
這為操作系統(tǒng)和其他進(jìn)程留下了將近4GB的空間糠排,這綽綽有余。

3超升、-v /opt/Sharedvolume:/opt/Sharedvolume userName/repoName:imageTag 該命令只是將主機上的文件夾映射到容器內(nèi)的文件夾入宦,你將在其中保存腳本文件和生成的日志。我們將不做進(jìn)一步詳細(xì)介紹室琢,但是如果您想了解有關(guān)卷映射的更多信息乾闰,請參閱本文和迷你教程

Step 8: 配置從節(jié)點——Slave Nodes

HostIP”變量僅在“entrypoint.sh”腳本中用于此處盈滴,以啟用從master服務(wù)器到slave服務(wù)器的遠(yuǎn)程訪問(“-Djava.rmi涯肩。server.hostname = $ HostIP”)。
直接使用命令(直接在Ubuntu上的實例終端中執(zhí)行):

HostIP=$(ip route show | awk '/default/ {print $9}') \
&& docker pull dragoscampean/testrepo:jmetruslave \
&& docker run -dit --name slave --network host -e HostIP=$HostIP -e HostIP=$HostIP -e Xms=256m -e Xmx=512m -e MaxMetaspaceSize=512m dragoscampean/testrepo:jmetruslave /bin/bash

通過“Run command”執(zhí)行的Shell腳本:

#!/bin/bash
HostIP=$(ip route show | awk '/default/ {print $9}')
docker pull dragoscampean/testrepo:jmetruslave
docker run -dit --name slave --network host -e HostIP=$HostIP -e Xms=256m -e Xmx=512m -e MaxMetaspaceSize=512m dragoscampean/testrepo:jmetruslave /bin/bash

Step 9: 分布式模式下運行腳本

到此雹熬,準(zhǔn)備就緒宽菜,可以開始運行測試了。這是我們需要在master主節(jié)點上運行以開始運行分布式測試的命令:

jmeter -n -t /path/to/scriptFile.jmx -Dserver.rmi.ssl.disable=true -R host1PrivateIP, host2PrivateIP,..., hostNPrivateIP -l /path/to/logfile.jtl

總結(jié):

按照上面的操作步驟竿报,可以實現(xiàn)AWS EC2+Jmeter+Docker的分布式性能測試,可能會遇到一些問題继谚,完全沒問題那是不可能的烈菌。
比如:
該文提到了一個EC2實例中有太多Websocket連接時可能遇到的問題。
另一個例子是我的一位同事在對Apa??che服務(wù)器進(jìn)行負(fù)載測試時遇到的情況花履,他會在JMeter中遇到各種連接錯誤芽世,我們最初認(rèn)為這是來自被測試的服務(wù)器。解決這個問題的方法來自這篇簡短的文章诡壁。

我在一個項目中偶然發(fā)現(xiàn)的一個問題是济瓢,在嘗試從一臺計算機執(zhí)行大約20000個線程時,進(jìn)行了一些數(shù)據(jù)驅(qū)動的測試妹卿。如果在Linux / MacOS終端中鍵入“ ulimit -a”旺矾,則會看到名為“ open files”的行蔑鹦。問題在于該屬性在測試計算機上設(shè)置為1024。使用JMeter運行數(shù)據(jù)驅(qū)動的測試時箕宙,此工具將為每個啟動的線程打開.csv文件或描述符嚎朽,一旦并行線程數(shù)超過1024,我將收到錯誤消息柬帕。
解決方案: 是從'/etc/security/limits'文件中編輯'open files'的最大值哟忍,并設(shè)置為'unlimited'。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末陷寝,一起剝皮案震驚了整個濱河市锅很,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌凤跑,老刑警劉巖爆安,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異饶火,居然都是意外死亡鹏控,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門肤寝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來当辐,“玉大人,你說我怎么就攤上這事鲤看≡稻荆” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵义桂,是天一觀的道長找筝。 經(jīng)常有香客問我,道長慷吊,這世上最難降的妖魔是什么袖裕? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮溉瓶,結(jié)果婚禮上急鳄,老公的妹妹穿的比我還像新娘。我一直安慰自己堰酿,他們只是感情好疾宏,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著触创,像睡著了一般坎藐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上哼绑,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天岩馍,我揣著相機與錄音碉咆,去河邊找鬼。 笑死兼雄,一個胖子當(dāng)著我的面吹牛吟逝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播赦肋,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼块攒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了佃乘?” 一聲冷哼從身側(cè)響起囱井,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎趣避,沒想到半個月后庞呕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡程帕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年住练,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片愁拭。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡讲逛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出岭埠,到底是詐尸還是另有隱情盏混,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布惜论,位于F島的核電站许赃,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏馆类。R本人自食惡果不足惜混聊,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望乾巧。 院中可真熱鬧技羔,春花似錦、人聲如沸卧抗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽社裆。三九已至,卻和暖如春向图,著一層夾襖步出監(jiān)牢的瞬間泳秀,已是汗流浹背标沪。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留嗜傅,地道東北人金句。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像吕嘀,于是被迫代替她去往敵國和親违寞。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359

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

  • 一、基本用法 1棕洋、COUNT:計算區(qū)域中數(shù)字的單元格個數(shù)挡闰。 ①如果參數(shù)為數(shù)字、日期或者代表數(shù)字的文本掰盘,...
    CC_e3da閱讀 833評論 0 0
  • 說起來很不好意思摄悯。我不但自己不愛景物描寫,也不喜歡看大段的景物描寫愧捕。 大多純景物在我心里不起波瀾奢驯,白描顯得生硬乏味...
    趁早退場閱讀 149評論 2 2
  • 抱歉,誤會了晃财! 回武漢快3個月了叨橱,基本適應(yīng)生活和工作的節(jié)奏,江城武漢的天氣總是異常變化断盛,總能碰到在上班的路上罗洗,熱的...
    佩嘟嘟的Family閱讀 130評論 0 1
  • 弟弟生于臘月,極其寒冷钢猛,母親剛剛坐完月子就是正月十四了伙菜。在母親還在坐月子期間父親就以要做生意賺錢為由,在村里借了三...
    語嫣柔柔美麗愛閱讀 159評論 0 1
  • 我在今年三月份開始了up主的生涯命迈,之前的一段時間粗略的學(xué)習(xí)了Pr贩绕,主題的選擇讓我發(fā)了愁。 我不是技術(shù)流壶愤,自己生活也...
    歲月過閱讀 309評論 0 2