专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

eBay流量管理之LB上下游报文追踪

  一。背景
  网络抓包技术在定位现代复杂的网络问题中有着举足轻重的作用。tcpdump,wireshark这些抓包工具成为运维,研发人员定位网络问题的瑞士军刀。不管你是什么样的应用,采用什么样的网络协议,最终都是一个个符合某种协议规范的报文在网络上传输,只要我们抓住这些报文加以分析,一般都能找到网络问题的根源。
  但是,随着7层网络负载均衡器(后文简称LB)的引入,从客户端到服务器的请求从一个TCP连接变成了两个独立的TCP连接:从客户端到LB的连接从LB到服务器的连接
  两个连接共同完成从客户端到服务器端的请求和应答。如果要想知道从客户端到服务器整个链路上的网络传输情况,我们势必要把这两条连接上的报文都给抓出来。不仅如此,我们还要知道这两条不同连接上的报文的对应关系。这里有两个主要的问题需要解决:
  (点击可查看大图)
  对于客户端到LB的一个HTTP请求,LB在把这个请求转给后端服务器的时候有多个服务器可以选择(如上图所示有server1,server2)。当LB选好某一个服务器之后,还需要从同一个服务器中的多个TCP连接中选择一个连接来传输报文。以上图为例,我们已经知道client和VIP的地址和端口信息,根据这些过滤条件,我们很容易抓取到客户端到LB到报文。但是,我们并不知道LB会选择哪一个后端服务器的哪一个TCP连接来转发这个请求,也就没办法加入过滤条件来抓取后端的报文。
  对于多个客户端到LB的HTTP请求,如果是先后发生的,那么LB一般会复用同一个从LB到服务器的TCP连接来处理这些请求。这意味着我们从LB到服务器的抓包中,并没有办法确定这些报文是来自于哪一个客户端到LB的哪一个连接。这使得我们在排查问题的时候没有办法形成一个从客户端到LB,再从LB到服务器的完整的链路分析。
  从上面的图中可以看到,client1和client2同时都去访问同一个VIP,此时LB一般情况下并不会和后端同一个服务器建立两条TCP连接来分别处理client1和client2的请求。LB会复用同一条到后端服务器的连接来处理client1和client2的请求。这样我们就算抓到从LB到后端服务器的报文,我们也无法判断这个报文是在处理client1的请求还是client2的请求。
  二。问题分析
  在eBay之前的网络架构中,主要使用厂商提供的硬件负载均衡器(后文简称HLB)。厂商都提供了丰富的网络排查工具帮助我们定位问题,比如netscaler的nstrace。为什么nstrace能解决前面提到的问题呢?
  这是因为,厂商的LB接管了报文的整个生命周期。也就是从接收到报文开始,经过处理,到最后发出去报文,整个过程都是在LB的控制范围内。所以HLB有能力知道报文转发的时候的两个关键信息:报文发给了哪一个后端服务器选用了跟后端服务器之间的哪一条TCP连接来发包
  同时,nstrace抓包的介入点也是厂商的软件可以自己完全控制的,可以在报文处理的任何一个时刻去抓包。从下图中可以看到,HLB可以在刚接收到报文的时候抓包,也可以在LB处理完客户端连接并创建和服务器端连接的时候抓包,也可以在报文完全组装好,准备发给服务器的时候抓包,所以它要解决前面两个问题相对来说是容易的。
  (点击可查看大图)
  目前eBay内部的网络架构中,以软件实现的负载均衡器(后文简称SLB)已经开始大规模替换HLB。eBay的SLB选用了目前业界流行的envoy。Envoy是一个运行于操作系统(本文中讲述的内容只针对Linux)之上的应用软件,它基于操作系统提供的socketAPI来完成报文的接收和转发。作为应用软件,envoy通过socket收发的是应用层协议的数据,而完整的TCPIP报文却是Linux内核的网络协议栈来负责的。这跟HLB有着很大的不同。我们通常的抓包工具抓包的时间点是在内核协议栈里,而且这个时间点也是固定的。从下面的图中我们可以看到在收包(ingresspacketcapture)和发包(egresspacketcapture)的时候抓包的位置。抓包是发生在网络驱动程序和以太报文处理之间。
  (点击可查看大图)
  对于本文的情况,我们只知道客户端地址端口和VIP的地址端口,这可以帮助我们抓到客户端到LB的报文。然而,对于LB到服务器这条连接,我们并不知道报文的目的地址,抓包的时候没有足够的信息可以帮助我们过滤得到我们想要的报文。
  三。解决方案
  本文设计并实现了一套工具,能够根据客户端IP地址和要访问的虚拟IP地址和端口(VIP),抓取从客户和LB之间以及对应的从LB和服务器之间交互的所有报文,从而形成完整的链路来分析网络问题。本文的讨论都是基于TCP协议上运行HTTPHTTPS的场景。
  我们先来看一下envoy和内核各自持有哪些信息:Envoy:唯一知道报文应该发送给哪个服务器的哪一条连接的组件。内核:只是负责按照envoy的指示把应用层的数据封装各层网络协议报头之后发送到网络上。所以我们首先需要改造的就是envoy本身的源代码,让它能够在把应用层数据传递给内核的时候(向后端服务器发送报文时)携带更多的信息,让内核能够清楚知道这个报文是来自于哪个客户端的哪个TCP连接。好在envoy来自于开源社区,我们能够比较方便地去修改源代码满足我们的需求。内核接收到envoy传递过来的有关客户端的信息之后,首先需要将该信息保存到报文的内核数据结构skb里面。现在内核有了这些信息,那么内核还需要哪些改动才能将这些信息不断传递下去,直到我们抓包的时候也能够获取到这些信息呢?有以下几种方法可以选择:
  通过eBPF方式加入自己的代码逻辑插入到内核中。但是对于我们需要修改的TCP发包函数并没有hook点可以插入,对于eBPFtracekprobe的方式虽然可以找到TCP发包函数,但是eBPFtracekprobe对于内核数据都是只读的,无法进行数据的改写。所以此方法其实是不可行的。直接修改内核,重新编译。出于对eBay当前实际情况的考量,此方法成本较高,不易推行。以动态加载模块的方式去改变内核行为。理论上这是大多数时候增加内核功能的推荐方式。这种方法其实又可以分为两种情况:内核已经提供了动态加载的Hook点。本文的情况是需要修改TCP发包函数,这个并没有直接相关的Hook点,除非我们替换整个TCP模块。但是我们需要的代码修改量其实非常少,完全没有必要替换整个TCP模块。利用livepatch的方式去替换内核的一些函数。
  最终我们选择了livepatch的方式去更改内核代码,将数据保存到skb中。通过livepatch的方式还可以达到按需加载的目的,因为绝大多数时候是不需要这个patch的,只有我们需要排查问题的时候才加载,任务完成之后就可以卸载patch了。这样对系统的影响也是最小的。当前内核基于传统cBPF抓包的时候,内核里的cBPF程序只能根据报文本身的内容做过滤,也就是根据数据链路层、IP层、传输层、应用层(基于报文数据偏移量来实现)报头来过滤,cBPF并不具有解析协议本身的能力。如果我们希望的过滤条件不是报文上固定的偏移量或者这个过滤条件本身就不属于报文的某个字段,cBPF就无能为力了。比如我们用tcpdump做抓包的时候,常用的过滤条件,比如IP地址、端口、TCPflag等等,都属于RFC规定的在报文固定位置出现的字段。另外一些属性,比如这个报文是属于哪个应用进程,这种信息是无法在报文上面体现的,也就不能作为抓包过滤条件。为了达到根据envoy传递给内核的信息进行过滤的目的,我们有几种可选办法:
  不改动报文长度,将信息写入某层协议报头的某个已知字段。此方法需要找到一些RFC定义的保留字段或者更改已知字段的值,具有一定风险。
  (点击可查看大图)
  改动报文长度,将信息以字段选项的形式插入到当前报文,比如IPoption或者TCPoption。此方法需要增加报文长度,会带来额外附载。
  (点击可查看大图)
  改造当前cBPF的实现,让cBPF能够通过skb的一些字段对报文进行过滤,而不是仅仅通过报文自身的字段来进行过滤。此方法要求对于cBPF有足够的了解,但是cBPF本身代码晦涩难懂,不易操作。而且对于内核的影响也是难以估计。
  (点击可查看大图)
  以eBPF的方式,插入一段代码并设置过滤条件,将报文从内核直接发送到用户空间。因为可以加入自定义代码,所以过滤条件可以十分灵活,除了可以根据报文本身任意字段外,还可以根据报文对应的skb上所有的元数据以及状态信息进行过滤。
  (点击可查看大图)
  上面的方法中,第4种看上去是最完美的方式,也是笔者一开始去实际操作的方法。在Linuxkernel5。5开始引入了新的helper函数bpfskboutput,可以将报文以BPFperfevent的方式从内核态发送到用户态空间。
  intbpfskboutput(voidctx,structbpfmapmap,u64flags,voiddata,u64size)DescriptionWriterawdatablobintoaspecialBPFperfeventheldbymapoftypeBPFMAPTYPEPERFEVENTARRAY。
  在实际编写代码测试的时候发现,当流量达到5MBs左右的时候就已经开始出现event丢失的情况了。通过查看这个helper函数的实现,可以发现是通过内存拷贝的方式将整个报文复制一份。虽然报文拷贝确实是性能的大敌,但是在5Ms这么低的流量就开始丢失event是不能用内存拷贝来解释的。我们发现,最大的问题还是在于BPF的perfevent本身的机制。简单的说就是用户程序通过定期轮询的方式去从内核获取event。不管我们把这个轮询的时间间隔设置多短,最后设置成没有间隔的不断轮询,性能上并没有太大的提升,不超过10MB就开始丢event了。除了性能的原因,当前eBay生产环境上使用的kernel版本还是5。4,就算采用这个方法,还需要升级内核版本或者把eBPF相关的patch引入到当前版本,这些工作都不在控制范围之内。所以最终没有进一步去研究如何提升BPFperfevent的性能来达到抓包的目的,但是我觉得这是eBPF可以去改进的地方。
  最终我们在项目中选择了第二种方法。该方法是在Linux默认提供的netfilter框架里加入我们自己的代码去插入新的TCPOption报头选项。后面会详细描述如何去实现的。
  通过这种方法,我们成功地将客户端到LB的连接信息传递到了从LB发送给服务器的报文之中,cBPF根据这些信息来进行过滤就成为了可能!
  不过我们也不能高兴的太早。现在虽然解决了从LB到服务器的请求报文中携带客户端相关信息的问题,这个客户端信息被保存在TCPoption里,但是从后端服务器返回给LB的报文中是没有这个TCPoption的。所以我们还需要一种机制能抓取从服务器返回给LB的报文。
  这里要强调的是:我们在抓取报文的时候已知条件只有客户端地址和VIP地址,对于后端服务器的IP端口信息,我们是一无所知的。因此在通过TCPoption作为filter抓到LB到服务器的报文的时候,还得把这个包含TCPoption的报文的源目的IP地址和源目的端口四元组记录下来,用来过滤从服务器返回给LB的报文。这里我们选择了eBPFtrace的方式,把这个四元组通过eBPFevent暴露给用户态的抓包程序,然后抓包程序根据这个四元组动态启动抓包线程去抓取服务器到LB的报文。
  (点击可查看大图)
  从上面的框架图中,我把整个工具链分成三部分:
  fetracetool这是一个用户真正操作的命令行工具集。它主要完成下面的功能:根据需求动态加载卸载livepatch模块和netfilterhook模块。获取eBPFtrace程序的结果(服务器IP和端口),动态启动一个线程去过滤并捕获LB和这个服务器之间的我们期望的报文。把用户输入的过滤条件(基于tcpdump语法)转化成内核可识别的cBPF代码,然后调用libpcap去过滤并捕获报文。
  envoy
  加入新的networkfilter来配置你想要抓取报文的的客户端IP端口和VIP信息。通过envoy的dynamicmetadata机制将客户端信息传递给LB发给后端服务器的连接。替换envoy的发包函数,把客户端信息传递到内核中。
  内核
  livepatch:从envoy传递过来的数据中解析出客户端信息并保存到skb。eBPFtrace(ipoutput):将服务器IP和端口信息暴露给用户态的fetracetool。etfilterhook:将客户端信息插入到TCP报头选项。
  Envoy
  PacketTraceFilterenvoy提供了filter的插件编写,本文加入了一个新的filter作为packettrace的过滤条件。
  (点击可查看大图)
  通过上面这个filter,envoy就会抓取满足以下条件的报文:目的IP是10。18。144。73目的端口是8080源IP是10。110。112。181
  在实际情况中,客户端端口一般是系统随机分配的,所以一般无法也不需要指定这个值。通过上面的配置,envoy只对满足这三个过滤条件的客户端到LB的TCP连接做抓包,同时抓取对应的从LB到后端服务器的TCP连接报文。客户端信息的传递Envoy提供了filterdynamicmetadata机制。本文增加了dynamicmetadata从下游连接(客户端到LB)传递到上游连接(LB到服务器)的功能。这样客户端信息被当成一种dynamicmetadata,传递到LB和服务器端的连接里。关于这部分的实现,起初笔者是直接将envoy的上游和下游连接加入指针互指来完成,后来在envoy核心开发维护者的建议下采用了目前的方案。因为从envoy的设计来说,上下游的连接是解耦的,不应该直接把上下游的连接直接关联,否则就违背了envoy的设计初衷。发包
  (点击可查看大图)
  通过上面的图,我们可以看到对于envoy发包的改动就是在调用socketAPI的时候,把客户端端口信息加入到TCPsocket的ancillarydata里去。因为有了前面packettracefilter的过滤,这里envoy只需要针对满足过滤条件的报文加入额外的信息。因为packettracefilter过滤条件里已经包含了客户端IP信息,所以这里我们只需要将客户端的端口信息加入到TCPsocket的ancillarydata就足够了。
  Kernel
  Livepatch
  结合前面envoy发包的图中,内核部分需要修改tcpsendmsglocked函数,将从socketancillarydata取出客户端的端口信息并保存到skb某个字段。我们选用了一个eBay内部没有使用到的一个字段来保存这个值。
  NetfilterHook
  我们选择用netfilterhook插入skb里保存的客户端的端口信息,是应该把这个值插入到IPoption,还是TCPoption呢?考虑到我们的netfilterhook是在IP层的hook,一开始本文选择将这个值插入到IPoption。但是在做性能测试的时候却发现,该方法对网络延时有非常大的影响。我们先来看一下报文的完整流程:
  客户端发起请求LB处理服务器处理服务器回复请求LB处理客户端
  整个过程在我的测试环境中,不插入IPoption的时候只需要几毫秒,插入IPoption并且不引起IP分片的情况下,延迟可以高达100毫秒。从我们netfilterhook加入的代码分析,虽然有内存拷贝来插入IPoption的操作(通常情况下,该操作是影响性能的关键因素之一),但是在本文的情况下,内存拷贝的长度是很小的,就是IP报头的移动,只有二十个字节,理论上不应该对延迟有这么大的影响。但是经过多次测试,仍然是同样的结果。于是我们通过打时间戳的办法将报文的整个过程分成netfilterhook之前、之后、内核驱动发送报文、服务器收到报文、服务器发出报文、LB收到回复报文这几个过程。最后对比发现,时间基本消耗在内核驱动发送报文到服务器收到报文阶段。由此也可看出,插入IPoption引起的时延并不来自于内核的操作,而是来自于从LB到服务器中间的网络设备(交换机路由器防火墙)。由此推测网络设备对于自定义的IPoption处理是比较低效的。但是我们又没法改变中间设备,于是选择TCPoption的方法再次尝试,好在这次的结果是令人欣慰的:在使用自定义TCPoption的情况下,延迟没有发生明显改变。
  eBPF
  由于本文只使用eBPF的trace功能,所以选择了当前比较成熟的BCC框架,从内核ipoutput函数中导出服务器IP和端口信息。fetracetool用golang进行简单封装之后,通过eBPFevent获取到服务器IP和端口。
  CLI(fetracetool)
  包括了:基于kpatch的shell脚本,负责加载卸载livepatch和netfilterhook。基于golang的CLI,负责读取用户希望的过滤参数并根据eBPF导出的服务器IP和端口动态启动goroutine过滤抓取LB和某个服务器之间的报文。这里针对客户端到LB和LB到每个服务器分别启动一个goroutine。最终结束抓包后,CLI负责将所有单个抓包文件合并成一个文件。
  四。演示
  网络拓扑
  (点击可查看大图)
  步骤
  在本次演示过程中,envoy和fetrace以docker容器方式,以hostnetwork模式运行于内核5。459版本的Ubuntu操作系统的同一台虚拟机中。client12server12分别以docker容器方式,运行于不同的虚拟机之中。在fetrace容器之中加载livepatch和netfilter模块
  rootxxxx:。fetracescriptsprestart。shloadStartingloadlivepatchloadingpatchmodule:fetracemoduleslivepatchmarkpatch15。4。059。kowaiting(upto15seconds)forpatchtransitiontocomplete。。。transitioncomplete(1seconds)在envoy容器之中配置packettracefilter指定clientIP,VIPIP和端口
  在client12,server12分别启动Envoynighthawk测试工具收发http流量
  clienthttp:10。18。144。73:8080duration30concurrency10rps100在fetrace容器之中,启动CLI抓包报文,大约30秒之后,Ctrlc终止CLI
  rootxxxx:。fetracebinfetracecifeth0vip10。18。144。73vport8080cip10。110。112。181I080604:01:50。26763837main。go:140〕NotifysubgoroutinequitI080604:01:50。26768337pcap。go:190〕V2SreceivesquitI080604:01:50。26769437pcap。go:190〕V2SreceivesquitI080604:01:50。26773337pcap。go:188〕C2VreceivesquitI080604:01:50。26775537main。go:129〕C2VgoroutineexitI080604:01:50。26764037capture。go:104〕PerfstopI080604:01:50。58626937main。go:135〕eBPFgoroutineexitI080604:01:50。58628837main。go:143〕MergeallpcapI080604:01:50。59546137main。go:145〕Mainthreadexit
  然后可以在fetrace容器里看到如下抓包文件
  rootxxxx:ls。pcapc2v。pcapfinal。pcapv2s10。18。144。734784210。75。119。3280。pcapv2s10。18。144。734999010。75。119。3280。pcap
  c2v。pcap:clientvip
  v2sxxxx。pcap:对应每一个服务器一个抓包文件
  final。pcap:所有抓包文件合并成一个
  用wireshark打开final。pcap
  (点击可查看大图)
  可以看到从LB到服务器的报文的TCP字段多了一个自定义的TCPoption。这里的MagicNumber0x9a6a转换成10进制(44350)之后就是客户端发起连接的端口号。通过这个端口号,我们就可以把从客户端发送给LB和LB发送到后端服务器的报文给对应起来了。
  10。110。112。181:4435010。18。144。73:808010。18。179。53:80
  (点击可查看大图)
  在fetrace容器中,抓包完成之后卸载模块
  rootxxxx:。fetracescriptsprestart。shunloadStartingunloadlivepatchdisablingpatchmodule:livepatchmarkpatchwaiting(upto15seconds)forpatchtransitiontocomplete。。。transitioncomplete(2seconds)unloadingpatchmodule:livepatchmarkpatchUnloadfetracehookmodule
  五。总结和展望
  在基于socket的网络应用软件中,网络中传输的报文经过内核协议栈处理之后,用户态程序接收到的信息并不能完全包含传输过程中的所有信息。对于大部分应用来说,用户态程序的确不需要知道底层的传输信息,这也正是socket设计之初衷,希望屏蔽和应用无关的底层信息,让应用开发者专注于业务层面的逻辑开发。但是,随着网络基础架构和应用架构的不断演化,信息传输已经不再是简单的客户端和服务器端的直接传输,中间过程会涉及多次处理,比如7层负载均衡的代理模式就需要终止当前传输,然后新建连接;比如微服务架构更是要求一个简单的请求需要经过多个服务器之间的中转才能最终完成一次请求和答复。因此,如何把所有这些中间过程的处理形成一条完整的、可追踪的全链路成了一个巨大的挑战。当前关于全链路追踪的解决方案都是从应用的层面在应用层去添加额外的追踪信息来实现,比如HTTP协议的XForwardedFor头部或者traceID头部等机制。这些机制对于关心具体应用的开发者来说确实是有效的。但是从网络基础架构的层面来看,我们并不关心应用层的具体协议,那么就需要把追踪信息下沉到更低的网络协议层。
  本文基于传输层的追踪信息做了相关研究并给出了可行性方案和实现。该解决方案从应用软件到内核都进行了相应的改进,从中我们可以看出当前基于socket的应用软件的一些弊端,即缺乏对于全链路需求的支持。为了让基于socket的软件能够更好的支持全链路追踪,我认为可以在以下几个方面进行增强:
  从内核层面提供更加丰富的socket选项,让应用软件能够通过socket获取到任何可以在网络上传输的信息,比如各个网络协议层级的选项(ip选项,tcp选项,tls选项等等),同时也能让socket把更多的用户自定义属性从用户态传入到内核态,让协议栈能够自由地添加各个网络协议层级的选项来扩展网络传输的表达能力,从而获得到全链路的追踪能力。对应上面内核对socket的增强,提供增强的socketAPI(glibc)来适配。应用软件使用增强的socketAPI来进行编程。但是这对已有的软件有侵入性。对于源码不能修改或者源码修改的代价较大的情况,可以考虑采用用户态的ebpfhook来实现(需要进一步探索可行性和实际解决方案)。

火箭军某部聚焦实战锤炼驾修双能硬核驾驶员连续通过急弯山区路段后立即进行无依托更换轮胎湿滑路段倒车移位入库时进行紧急制动测试某部野外综合训练场上,一场驾驶员道路驾驶维修技能考核正在激烈进行。该部紧贴任务实际,以实战化训练为中青漫评丨流动中国彰显最美时代图景从四纵四横到八纵八横,从一票在手到刷脸进站,从驰骋祖国大地到奔向多姿多彩的世界中国铁路发展一路高歌猛进,绘就出流动中国的时代图景。连点成线,织线成网,让流动的中国更便捷。曾经高寒缺一周年纪念日,俄乌双方都在给自己准备礼物我一直认为,学会使用战斗机,只是几天的事情,无非就是起飞降落投弹三个系列动作,一天学不会,给个三五天,我想总能学个七七八八。2月8日,英国首相苏纳克责成国防大臣华莱尔,研究英国可能接口测试Fiddler介绍以及安装Fiddler介绍以及安装Fiddler简介Fiddler是比较好用的web代理调试工具之一,它能记录并检查所有客户端与服务端的HTTPHTTPS请求,能够设置断点,篡改及伪造Re北京整车无人自动驾驶车辆上路测试日前,北京市首批整车无人自动驾驶车辆获准在北京经开区的限定路线和特定时段分批开展道路测试。这两天,在北京经开区出现了一批整车无人自动驾驶车辆,区别于此前开展的主驾无人车辆的道路测试WCBA第14轮,内蒙古女篮88比46战胜上海女篮,四人得分上双WCBA常规赛14轮内蒙古女篮88比46战胜上海女篮,以42分的优势获得一场大胜。内蒙古女篮12人均有出场参赛,仅有陈丽宇出场16分钟没拿到比赛分数,有4人得分上双,李月汝18分,今日钢铁方向利好政策持续,需求环比好转一宏观消息1。富宝独家解读原油价格周四回落,石油基础设施似乎在土耳其和叙利亚部分地区地震造成的严重破坏中幸免,且美国库存增加,投资者担心美联储加息。这场已经造成逾1。9万人死亡的地金华大拆迁,江北江南,婺州古城游客服务中心项目,即将启动万万没想到,一点风声都没有,婺州古城又要开发了,这次是婺州古城游客中心项目,金华江北最老的区块竟然要征收了我想静静这里的居民要开心了,这个地段的房龄已经有30多年了,真正的老破旧,逛灯会玩潮集赏无人机烟花大秀2月14日芜湖方特夜场邀你共赴浪漫之约彩灯璀璨映佳人!2月14日当天,芜湖方特东方神画将以梦幻花灯潮玩集市无人机烟花秀点亮浪漫仙境,为游客奉献一场爱意满满的仙阙盛筵。199元双人夜场限量特惠票已惊喜上线,游客通过芜湖方近日择机出舱!湖南籍航天员张陆或将首次漫步太空据中国载人航天工程办公室消息,神舟十五号航天员乘组将于近日择机执行第一次出舱活动。从左至右依次是邓清明费俊龙张陆自北京时间2022年11月30日顺利进驻空间站组合体以来,神舟十五号泰山产业集团20万吨碳酸二甲酯项目EPC总承包签约成功2月8日上午,泰山产业集团20万吨碳酸二甲酯EPC总承包暨配套供热签约仪式在新泰市举行。泰山产业集团从服务泰安市发展大局的角度出发,助力新泰市抢抓新能源产业发展风口,与新泰市徂阳城
累吗?挺着年算是过完了,终于可以把自己的面具摘下来了这些天,我好累可看着年迈的父母,我只能挂着伪装的笑容,表现出来我很好!也只有在跟妈妈忙碌的灶台前,我得以暂且的喘息,不想,不看,不念我只有归笼第一天每个学期开学第一天中午无论多忙我都会回家,四个半小时看不到孩子,听不到孩子的声音让我十分难受。这种感觉已经四年了,所以每天中午我都是尽可能的回家,因为孩子中午会回家吃饭。我记得一年好甜!建德这个采摘小番茄的好地方,你还不知道吗钱江晚报小时新闻记者何晟通讯员王莹小可爱圣女果,能生吃,能炒菜,还能摆盘装饰,可谓是水果界的百搭星人,怎能不受人喜爱?2023年新年伊始,建德莲花镇戴农富产业园里的小番茄悄悄红透了辽宁第一名刹楞严寺楞严寺,位于营口市区中部的新兴大街,辽南地区第一名刹,是东北现存较为完整的民国时期大型寺院建筑群之一,1979年被辽宁省人民政府列为省级文物保护单位。楞严寺始建于1922年,193早春时节游普洱,这33个A级旅游景区你要来嘎!来源云南日报目前,普洱共有33个A级旅游景区其中4A级旅游景区10个3A级旅游景区21个,2A级旅游景区2个早春时节,生机勃发何不趁着明媚的春光逛一逛这些各具特色的景区呢33款不同红岩上红梅开早春山城上彩妆今春赏花这样打开三种美重庆日报客户端记者郭晓静崔曜首席记者龙帆2月7日,重庆日报记者来到渝中区红岩公园,看到上千株红梅已经悄然绽放,枝条上三朵一簇,五朵一堆,远望去好似粉色的云霞。不少市民来到这里拍照打汕头自驾游绝不能错过的5个景点旅行是一种追寻,尽可能地去更多的地方,寻找不一样的新鲜与感动旅行是一种分享。一。南澳岛位于闽粤台三省交界海面,是广东省唯一的海岛县,是东南沿海通商的必经泊点和中转站。南澳岛的山水都春节即将结束,令人恶心的一幕,就全国各地重新上演刚刚过去的春节小长假,你感受最深的是什么,是不是曾经热闹喧嚣的场景又回来了。经历了第一轮疫情高峰过后,全社会进入了复苏期,恰好又赶上了春节人流高峰。从节前火车票一票难求高速公路拥堵法拉第未来宣布4月底交付FF91,贾老板能否东山再起2月6日消息,总部位于美国加州的法拉第未来FaradayFuture宣布了一系列融资的最终协议,并表示在按时圆满执行后,法拉第未来将为FF91Futurist的量产筹集到所有必要的霍楠直言姚明只替老板考虑,剥削CBA球员转会权利,姚明终成恶龙曾经的屠龙少年,如今的恶龙,似乎每一个勇士在战胜恶龙后,最终都会成为自己原本最痛恨的那条恶龙,那么曾经为了追求NBA舞台,放话上海队要是再阻拦我去NBA追梦,我就直接选择退役,那时老板亲自出马1还作不作数高老板在杭州做房产中介生意,他说去年促成了一单业务,按照约定应该能拿到九万多的佣金,可最终对方只愿意给一万块钱,他无法接受。老板亲自出马做成第一单,结算后佣金少八万?高老板自己有家
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网