mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2025-09-26 21:26:41 +08:00
320 lines
24 KiB
HTML
320 lines
24 KiB
HTML
<!DOCTYPE html>
|
||
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
|
||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
<head>
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
|
||
<link rel="icon" href="/static/favicon.png">
|
||
<title>17 如何向面试官证明你做的系统是高性能的?.md.html</title>
|
||
<!-- Spectre.css framework -->
|
||
<link rel="stylesheet" href="/static/index.css">
|
||
<!-- theme css & js -->
|
||
<meta name="generator" content="Hexo 4.2.0">
|
||
</head>
|
||
<body>
|
||
<div class="book-container">
|
||
<div class="book-sidebar">
|
||
<div class="book-brand">
|
||
<a href="/">
|
||
<img src="/static/favicon.png">
|
||
<span>技术文章摘抄</span>
|
||
</a>
|
||
</div>
|
||
<div class="book-menu uncollapsible">
|
||
<ul class="uncollapsible">
|
||
<li><a href="/" class="current-tab">首页</a></li>
|
||
</ul>
|
||
<ul class="uncollapsible">
|
||
<li><a href="../">上一级</a></li>
|
||
</ul>
|
||
<ul class="uncollapsible">
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/00 开篇词 中高级研发面试,逃不开架构设计这一环.md.html">00 开篇词 中高级研发面试,逃不开架构设计这一环</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/01 研发工程师想提升面试竞争力,该具备这三个技术认知.md.html">01 研发工程师想提升面试竞争力,该具备这三个技术认知</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/02 研发工程师如何用架构师视角回答架构设计方案?.md.html">02 研发工程师如何用架构师视角回答架构设计方案?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/03 面试官如何考察与 CAP 有关的分布式理论?.md.html">03 面试官如何考察与 CAP 有关的分布式理论?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/04 亿级商品存储下,如何深度回答分布式系统的原理性问题?.md.html">04 亿级商品存储下,如何深度回答分布式系统的原理性问题?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/05 海量并发场景下,如何回答分布式事务一致性问题?.md.html">05 海量并发场景下,如何回答分布式事务一致性问题?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/06 分布式系统中,如何回答锁的实现原理?.md.html">06 分布式系统中,如何回答锁的实现原理?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/07 RPC:如何在面试中展现出“造轮子”的能力?.md.html">07 RPC:如何在面试中展现出“造轮子”的能力?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/08 MQ:如何回答消息队列的丢失、重复与积压问题.md.html">08 MQ:如何回答消息队列的丢失、重复与积压问题</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/08 案例串联 如何让系统抗住双十一的预约抢购活动?.md.html">08 案例串联 如何让系统抗住双十一的预约抢购活动?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/09 如何回答 MySQL 的索引原理与优化问题?.md.html">09 如何回答 MySQL 的索引原理与优化问题?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/10 如何回答 MySQL 的事务隔离级别和锁的机制?.md.html">10 如何回答 MySQL 的事务隔离级别和锁的机制?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/11 读多写少:MySQL 如何优化数据查询方案?.md.html">11 读多写少:MySQL 如何优化数据查询方案?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/12 写多读少:MySQL 如何优化数据存储方案?.md.html">12 写多读少:MySQL 如何优化数据存储方案?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/13 缓存原理:应对面试你要掌握 Redis 哪些原理?.md.html">13 缓存原理:应对面试你要掌握 Redis 哪些原理?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/14 缓存策略:面试中如何回答缓存穿透、雪崩等问题?.md.html">14 缓存策略:面试中如何回答缓存穿透、雪崩等问题?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/15 如何向面试官证明你做的系统是高可用的?.md.html">15 如何向面试官证明你做的系统是高可用的?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/16 如何从架构师角度回答系统容错、降级等高可用问题?.md.html">16 如何从架构师角度回答系统容错、降级等高可用问题?</a>
|
||
</li>
|
||
<li>
|
||
<a class="current-tab" href="/专栏/架构设计面试精讲/17 如何向面试官证明你做的系统是高性能的?.md.html">17 如何向面试官证明你做的系统是高性能的?</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/18 如何从架构师角度回答怎么应对千万级流量的问题?.md.html">18 如何从架构师角度回答怎么应对千万级流量的问题?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/19 彩蛋 互联网架构设计面试,你需要掌握的知识体系.md.html">19 彩蛋 互联网架构设计面试,你需要掌握的知识体系</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/架构设计面试精讲/结束语 程序员的道、术、势.md.html">结束语 程序员的道、术、势</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
|
||
<div class="sidebar-toggle-inner"></div>
|
||
</div>
|
||
<script>
|
||
function add_inner() {
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
inner.classList.add('show')
|
||
}
|
||
function remove_inner() {
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
inner.classList.remove('show')
|
||
}
|
||
function sidebar_toggle() {
|
||
let sidebar_toggle = document.querySelector('.sidebar-toggle')
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
let content = document.querySelector('.off-canvas-content')
|
||
if (sidebar_toggle.classList.contains('extend')) { // show
|
||
sidebar_toggle.classList.remove('extend')
|
||
sidebar.classList.remove('hide')
|
||
content.classList.remove('extend')
|
||
} else { // hide
|
||
sidebar_toggle.classList.add('extend')
|
||
sidebar.classList.add('hide')
|
||
content.classList.add('extend')
|
||
}
|
||
}
|
||
function open_sidebar() {
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
sidebar.classList.add('show')
|
||
overlay.classList.add('show')
|
||
}
|
||
function hide_canvas() {
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
sidebar.classList.remove('show')
|
||
overlay.classList.remove('show')
|
||
}
|
||
</script>
|
||
<div class="off-canvas-content">
|
||
<div class="columns">
|
||
<div class="column col-12 col-lg-12">
|
||
<div class="book-navbar">
|
||
<!-- For Responsive Layout -->
|
||
<header class="navbar">
|
||
<section class="navbar-section">
|
||
<a onclick="open_sidebar()">
|
||
<i class="icon icon-menu"></i>
|
||
</a>
|
||
</section>
|
||
</header>
|
||
</div>
|
||
<div class="book-content" style="max-width: 960px; margin: 0 auto;
|
||
overflow-x: auto;
|
||
overflow-y: hidden;">
|
||
<div class="book-post">
|
||
<p id="tip" align="center"></p>
|
||
<div><h1>17 如何向面试官证明你做的系统是高性能的?</h1>
|
||
<p>前两讲,我带你了解了“高可用的衡量标准”以及“如何设计高可用的架构”,接下来我们会用两讲的时间来聊一聊“高性能”的话题,今天咱们先来探讨怎么向面试官证明你做的系统是高性能的?(其中会涉及性能优化的指标和关注点,以及怎样分析系统的性能瓶颈)。</p>
|
||
<h3>案例背景</h3>
|
||
<p>我曾经面试过很多研发工程师和架构师,他们在介绍系统性能时,一般会说:“我们的架构最高支持 200 万的并发流量”。</p>
|
||
<p>如果不考虑实际业务需求,这样的回答没有任何意义,因为高性能与业务是强相关的:</p>
|
||
<ul>
|
||
<li>如果一台网络游戏服务器,可以支撑 2 百名玩家同时在线开黑,可能就算高性能;</li>
|
||
<li>如果一台网络直播服务器,可以支撑 2 千名用户同时在线观看,可能就算高性能;</li>
|
||
<li>如果一台电商平台服务器,可以支撑 2 万名用户同时在线下单,可能就算高性能;</li>
|
||
</ul>
|
||
<p>这些数据也许有出入,但逻辑没问题,并且在实际的业务场景中,你要关注很多业务相关性指标,比如游戏需要关注稳定性;视频需要关注延时;电商需要关注一致性……</p>
|
||
<p>在明确了业务场景之后,你还要关注系统的性能指标主要有吞吐量、延迟以及 TP。</p>
|
||
<h3>案例分析</h3>
|
||
<p>我们在拿到产品经理的 PRD 文档时,心里就会清楚要关心哪些系统性能指标,因为需求文档中会描述同时支持多少人在线访问,你也可以借此估算出系统的并发用户数。一般来讲,系统建立的会话数量就是用户同时访问系统的数量。你也可以通过公式,估算出系统的吞吐量(throughput)和延迟(latency)。</p>
|
||
<p><img src="assets/CioPOWA2H8qAC-PfAAAEsxBVbwY511.png" alt="Drawing 0.png" /></p>
|
||
<p>延迟和吞吐量,是衡量软件系统最常见的两个指标。</p>
|
||
<ul>
|
||
<li><strong>吞吐量</strong>(系统处理请求的速率):反映单位时间内处理请求的能力(单位一般是TPS或QPS)。</li>
|
||
<li><strong>延迟</strong>(响应时间):从客户端发送请求到接收响应的时间(单位一般是ms、s)。</li>
|
||
</ul>
|
||
<p>一般来说,<strong>延迟和吞吐量既互斥,又不绝对的互斥</strong>,你可以通过性能压测分别绘制吞吐量和延迟的曲线图:</p>
|
||
<p><img src="assets/Cgp9HWA2_ZuAHdfgAAA1WOvYXBI512.png" alt="image" /></p>
|
||
<p>延迟总是非递减的曲线,开始时表现比较平稳,到了某一个特定值后,会迅速增大。而吞吐量曲线在开始时迅速增加,到达峰值后逐渐减小。</p>
|
||
<p>总体来看,随着压力增大,单位时间内系统被访问的次数增加。结合延迟和吞吐量观察的话,吞吐量曲线的最高点,往往是延迟曲线最低偏后的一个时间点,这意味着延迟已经开始增大一段时间了。那么<strong>对一些延迟要求比较高的系统来说,系统优化性能指标是要找到延迟趋向最低和吞吐量趋向最高的点</strong>。</p>
|
||
<p>从图中你也可以看出,如果不做流量控制,在系统压力不断增大后,系统便什么也做不成。这也是一些不够健壮的系统,在压力较大的特殊业务场景下(比如一元秒杀、抢购、瞬时流量非常大的系统),直接崩溃,对所有用户拒绝服务的原因。</p>
|
||
<p><strong>除了吞吐量和延迟,TP(Top Percentile)也经常被提到。</strong> 以 TP 99 为例,它是指请求中 99% 的请求能达到的性能,TP 是一个时间值,比如 TP 99 = 10ms,含义就是 99%的请求,在 10ms 之内可以得到响应。</p>
|
||
<p>关于 TP 指标,你要掌握两个考点。</p>
|
||
<ul>
|
||
<li><strong>计算 TP 指标:</strong> 比如 TP 99,把一段时间内所有请求的响应时间,从小到大进行排序,然后取 99% 对应的请求的响应时间,即为 TP99 的值。</li>
|
||
<li><strong>TP指标相比于性能均值的意义:</strong> 为什么要用 TP 99 这样的比例方式,而不直接用平均数来定义性能呢?这是为了更符合实际系统的情况。</li>
|
||
</ul>
|
||
<p>举个例子,比如在一个系统的 100 个请求中,99 个都在 1 s 左右返回,剩下 1 个 100s 还不返回,如果计算平均时间,就是<img src="assets/CioPOWA2IE-AQq34AAAFrvhSBV4194.png" alt="Drawing 2.png" />,无法反映系统的真实情况。因为耗时 100 s 的请求也许是异常请求,正常请求的平均时间仍是 1 秒,而 TP99 就比较能反映真实情况,因为 TP99 就可以达到 1 秒。</p>
|
||
<p>对初中级研发工程师来说,回答“吞吐率、延迟、TP 99(TP 99 比较有代表性)”这三个指标就够了,但如果你应聘高级研发工程师,还要站在系统全链路的角度上思考问题,从端到端的角度思考系统的性能指标(也就是从架构师的视角分析系统)。</p>
|
||
<h3>案例解答</h3>
|
||
<h4>用架构师的视角分析系统性能指标</h4>
|
||
<p>架构师视角说白了就是系统的全链路视角,我们从前端请求流程开始,来讲解一次请求链路会涉及哪些前后端性能指标。</p>
|
||
<p><img src="assets/Cgp9HWA2_bWARBegAABGgCuF23Q624.png" alt="image" /></p>
|
||
<p>一次请求链路</p>
|
||
<p><strong>步骤一:DNS解析</strong></p>
|
||
<p>用户在浏览器输入 URL 按回车,请求会进行 DNS 查找,浏览器通过 DNS 解析查到域名映射的IP 地址,查找成功后,浏览器会和该 IP 地址建立连接。对应的性能指标为:<strong>DNS解析时间</strong>。</p>
|
||
<p>那你怎么提升域名DNS解析性能呢?</p>
|
||
<p>答案是通过 DNS缓存或 DNS 预解析,适当增大域名的TTL 值来增大 DNS 服务器缓存域名的时间,进而提升了缓存的命中率。也可以用 dns-prefetch 标签实现域名的预解析,让浏览器在后台把要用的 DNS请求提前解析,当用户访问的网页中包含了预解析的域名时,再次解析 DNS 就不会有延迟了,比如京东针对静态资源域名的预解析如下:</p>
|
||
<pre><code><link rel="dns-prefetch" href="//static.360buyimg.com">
|
||
</code></pre>
|
||
<p><strong>步骤二:建立TCP连接</strong></p>
|
||
<p>由于 HTTP 是应用层协议,TCP 是传输层协议,所以 HTTP 是基于 TCP 协议基础上进行数据传输的。所以你要建立 TCP 请求连接,这里你也可以用 TCP的连接时间来衡量浏览器与 Web 服务器建立的请求连接时间。</p>
|
||
<p><strong>步骤三:服务器响应</strong></p>
|
||
<p>这部分就是我们开篇讲到的最重要的性能指标了,即服务器端的延迟和吞吐能力。针对影响服务端性能的指标,还可以细分为基础设施性能指标、数据库性能指标,以及系统应用性能指标。</p>
|
||
<ul>
|
||
<li>基础设施性能指标主要针对 CPU 利用率、磁盘 I/O,网络带宽、内存利用率等。</li>
|
||
</ul>
|
||
<p>举个例子,如果 CPU 占用率超过80%,很可能是系统出了问题。如果内存利用率 100%,可能是因为内存中存放了缓存,因此还要衡量 SWAP 交换空间的利用率。另外,还要考虑容器的 JVM 的Full GC 情况、磁盘 I/O 是否可以优化、网络带宽是否存在瓶颈等问题都会影响系统的最终性能。</p>
|
||
<ul>
|
||
<li>数据库的性能指标主要有 SQL 查询时间、并发数、连接数、缓存命中率等。</li>
|
||
<li>系统应用性能指标和系统业务有关,因为业务场景影响架构设计,比如To C 的系统一般会设计成同步 RPC 调用,因为要实时反馈 C 端用户的请求,而 To B 的系统则可以设计成事件驱动模式,通过异步通知的方式,推送或拉取数据,两种架构对比,显然异步事件驱动的吞吐量会更高。</li>
|
||
</ul>
|
||
<p><strong>步骤四:白屏时间</strong></p>
|
||
<p>当浏览器与 Web 服务器建立连接后,就可以进行数据通信了。Web 服务器接收请求后,开始处理请求,浏览器这时会等待Web 服务器的处理响应。</p>
|
||
<p>由于浏览器自上而下显示 HTML,同时渲染顺序也是自上而下的,所以当用户在浏览器地址栏输入 URL 按回车,到他看到网页的第一个视觉标志为止,这段白屏时间可以作为一个性能的衡量指标(白屏时间越长,用户体验越差)。</p>
|
||
<p>优化手段为减少首次文件的加载体积,比如用 gzip 算法压缩资源文件,调整用户界面的浏览行为(现在主流的Feed流也是一种减少白屏时间的方案)。</p>
|
||
<p><strong>步骤五:首屏时间</strong></p>
|
||
<p>用户端浏览界面的渲染,首屏时间也是一个重要的衡量指标,首屏时间是指:用户在浏览器地址输入 URL 按回车,然后看到当前窗口的区域显示完整页面的时间。一般情况下,一个页面总的白屏时间在 2 秒以内,用户会认为系统响应快,2 ~ 5 秒,用户会觉得响应慢,超过 5 秒很可能造成用户流失。</p>
|
||
<h4>如何分析系统的性能瓶颈?</h4>
|
||
<p>通常情况下,系统性能不达标一般会反映在TP 99 的延迟上面,但这只是表层的现象,怎么找到系统真正的性能瓶颈呢? 你可以遵循这几个步骤。</p>
|
||
<ul>
|
||
<li><strong>设计阶段,定义系统性能目标</strong></li>
|
||
</ul>
|
||
<p>你要在项目初期定义好系统大致的性能目标,比如希望单台服务器能够负载多少 TPS 的请求,因为不同的性能会影响到系统的架构设计,也会带来不同的成本,一旦过了设计阶段,再因为性能问题调整系统架构,成本极高。比如,当前单机性能是 80 TPS,要想优化到100 TPS,可以做一些小的性能优化,但要提升到 1000 TPS,就要进行架构改造了,代价非常大。</p>
|
||
<ul>
|
||
<li><strong>开发阶段,走查代码和业务流程</strong></li>
|
||
</ul>
|
||
<p>也就是评审代码,代码包括应用程序源代码、环境参数配置、程序整个调用流程和处理逻辑。比如,用户在 App 中触发了“立即下单”按钮,服务端的应用程序从线程池里取得了线程来处理请求,然后查询了几次缓存和数据库,都读取和写入了什么数据,再把最终的响应返回给 App,响应的数据报文格式是什么,有哪些状态码和异常值……</p>
|
||
<ul>
|
||
<li><strong>测试阶段,压测发现系统性能峰值</strong></li>
|
||
</ul>
|
||
<p>一般来说,你要在系统上线前,对系统进行全方位的压力测试,绘制出系统吞吐量和延迟曲线,然后找到最佳性能点,并在超过最佳性能点时做限流,如果达不到最佳性能点(比如多数系统的吞吐量,随着压力增大,吞吐量上不去)就需要考虑出现延迟和吞吐量的这几种情况。</p>
|
||
<p><strong>1.定位延迟问题</strong></p>
|
||
<p>你要本着端到端的策略,大到整体流程,小到系统模块调用,逐一排查时间消耗在哪里。</p>
|
||
<p>你可以使用 kill -3 PID, jstack 等命令打印系统当前的线程执行的堆栈;还可以用一些性能分析工具,如 JProfiler 来监控系统的内存使用情况、垃圾回收、线程运行状况,比如你发现了运行的 100 个线程里面,有 80 个卡在某一个锁的释放上面,这时极有可能这把锁造成的延迟问题。</p>
|
||
<p><strong>2. 对于吞吐量问题的定位</strong></p>
|
||
<p>对于吞吐量指标要和 CPU使用率一起来看,在请求速率逐步增大时,经常会出现四种情况:</p>
|
||
<p><img src="assets/CioPOWA2_caAfX8HAADVumEYCPE554.png" alt="图片1.png" /></p>
|
||
<h3>总结</h3>
|
||
<p>对于怎么评估系统高性能,你可以从系统的吞吐量、延迟以及 TP 99,这三个指标出发回答面试官提出的问题。而对于高级研发工程师,不仅仅要了解后端的性能指标,还有对全链路的性能指标有所了解。</p>
|
||
<p>另外,在实际生产环境,还会涉及 CDN 加速、ISP 路由策略、边缘计算等一系列网络工程层面的性能优化指标,这里展开的内容相对较多,你可以自己课下学习。总的来说,你要在大脑里先建立起整个请求的链路蓝图,熟悉每个环节的性能损耗。</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<div style="float: left">
|
||
<a href="/专栏/架构设计面试精讲/16 如何从架构师角度回答系统容错、降级等高可用问题?.md.html">上一页</a>
|
||
</div>
|
||
<div style="float: right">
|
||
<a href="/专栏/架构设计面试精讲/18 如何从架构师角度回答怎么应对千万级流量的问题?.md.html">下一页</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
|
||
</div>
|
||
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"709979273bff3cfa","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
|
||
</body>
|
||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
|
||
<script>
|
||
window.dataLayer = window.dataLayer || [];
|
||
function gtag() {
|
||
dataLayer.push(arguments);
|
||
}
|
||
gtag('js', new Date());
|
||
gtag('config', 'G-NPSEEVD756');
|
||
var path = window.location.pathname
|
||
var cookie = getCookie("lastPath");
|
||
console.log(path)
|
||
if (path.replace("/", "") === "") {
|
||
if (cookie.replace("/", "") !== "") {
|
||
console.log(cookie)
|
||
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
|
||
}
|
||
} else {
|
||
setCookie("lastPath", path)
|
||
}
|
||
function setCookie(cname, cvalue) {
|
||
var d = new Date();
|
||
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
|
||
var expires = "expires=" + d.toGMTString();
|
||
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
|
||
}
|
||
function getCookie(cname) {
|
||
var name = cname + "=";
|
||
var ca = document.cookie.split(';');
|
||
for (var i = 0; i < ca.length; i++) {
|
||
var c = ca[i].trim();
|
||
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
|
||
}
|
||
return "";
|
||
}
|
||
</script>
|
||
</html>
|