不再回头 .net学习日记&资料

我再也不愿听你要求 我受够了你那些自私要求

  IT博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  39 随笔 :: 2 文章 :: 14 评论 :: 0 Trackbacks

#

  尽早缓存;经常缓存  

  您应该在应用程序的每一层都实现缓存。向数据层、业务逻辑层、UI 或输出层添加缓存支持。内存现在非常便宜 — 因此,通过以智能的方式在整个应用程序中实现缓存,可以获得很大的性能提高。

  缓存可以掩盖许多过失  

  缓存是一种无需大量时间和分析就可以获得“足够良好的”性能的方法。这里再次强调,内存现在非常便宜,因此,如果您能通过将输出缓存 30 秒,而不是花上一整天甚至一周的时间尝试优化代码或数据库就可以获得所需的性能,您肯定会选择缓存解决方案(假设可以接受 30 秒的旧数据)。缓存正是那些利用 20% 付出获得 80% 回报的特性之一,因此,要提高性能,应该首先想到缓存。不过,如果设计很糟糕,最终却有可能带来不良的后果,因此,您当然也应该尽量正确地设计应用程序。但如果您只是需要立即获得足够高的性能,缓存就是您的最佳选择,您可以在以后有时间的时候再尽快重新设计应用程序。  

  页面级输出缓存

  作为最简单的缓存形式,输出缓存只是在内存中保留为响应请求而发送的 HTML 的副本。其后再有请求时将提供缓存的输出,直到缓存到期,这样,性能有可能得到很大的提高(取决于需要多少开销来创建原始页面输出 - 发送缓存的输出总是很快,并且比较稳定)。  

  实现  

  要实现页面输出缓存,只要将一条 OutputCache 指令添加到页面即可。  

  <%@ OutputCache Duration="60" VaryByParam="*" %>  

  如同其他页面指令一样,该指令应该出现在 ASPX 页面的顶部,即在任何输出之前。它支持五个属性(或参数),其中两个是必需的。 

  Duration

  必需属性。页面应该被缓存的时间,以秒为单位。必须是正整数。 

  Location

  指定应该对输出进行缓存的位置。如果要指定该参数,则必须是下列选项之一:Any、Client、Downstream、None、Server 或 ServerAndClient。 

  VaryByParam

   必需属性。Request 中变量的名称,这些变量名应该产生单独的缓存条目。"none" 表示没有变动。"*" 可用于为每个不同的变量数组创建新的缓存条目。变量之间用 ";" 进行分隔。  

  VaryByHeader

   基于指定的标头中的变动改变缓存条目。  

  VaryByCustom

   允许在 global.asax 中指定自定义变动(例如,"Browser")。  

  利用必需的 Duration 和 VaryByParam 选项的组合可以处理大多数情况。例如,如果您的产品目录允许用户基于 categoryID 和页变量查看目录页,您可以用参数值为 "categoryID;page" 的 VaryByParam 将产品目录缓存一段时间(如果产品不是随时都在改变,一小时还是可以接受的,因此,持续时间是 3600 秒)。这将为每个种类的每个目录页创建单独的缓存条目。每个条目从其第一个请求算起将维持一个小时。 

  VaryByHeader 和 VaryByCustom 主要用于根据访问页面的客户端对页面的外观或内容进行自定义。同一个 URL 可能需要同时为浏览器和移动电话客户端呈现输出,因此,需要针对不同的客户端缓存不同的内容版本。或者,页面有可能已经针对 IE 进行了优化,但需要能针对 Netscape 或 Opera 完全降低优化(而不仅仅是破坏页面)。后一个例子非常普遍,我们将提供一个说明如何实现此目标的示例: 

  示例:VaryByCustom 用于支持浏览器自定义  

  为了使每个浏览器都具有单独的缓存条目,VaryByCustom 的值可以设置为 "browser"。此功能已经内置在缓存模块中,并且将针对每个浏览器名称和主要版本插入单独的页面缓存版本。 

  <%@ OutputCache Duration="60" VaryByParam="None" VaryByCustom="browser" %> 

  片段缓存,用户控件输出缓存

  缓存整个页面通常并不可行,因为页面的某些部分是针对用户定制的。不过,页面的其他部分是整个应用程序共有的。这些部分最适合使用片段缓存和用户控件进行缓存。菜单和其他布局元素,尤其是那些从数据源动态生成的元素,也应该用这种方法进行缓存。如果需要,可以将缓存的控件配置为基于对其控件(或其他属性)的更改或由页面级输出缓存支持的任何其他变动进行改变。使用同一组控件的几百个页面还可以共享那些控件的缓存条目,而不是为每个页面保留单独的缓存版本。 

  实现  

  片段缓存使用的语法与页面级输出缓存一样,但其应用于用户控件(.ascx 文件)而不是 Web 窗体(.
aspx 文件)。除了 Location 属性,对于 OutputCache 在 Web 窗体上支持的所有属性,用户控件也同样支持。用户控件还支持名为 VaryByControl 的 OutputCache 属性,该属性将根据用户控件(通常是页面上的控件,例如,DropDownList)的成员的值改变该控件的缓存。如果指定了 VaryByControl,可以省略 VaryByParam。最后,在默认情况下,对每个页面上的每个用户控件都单独进行缓存。不过,如果一个用户控件不随应用程序中的页面改变,并且在所有页面都使用相同的名称,则可以应用 Shared="true" 参数,该参数将使用户控件的缓存版本供所有引用该控件的页面使用。

  示例  

  <%@ OutputCache Duration="60" VaryByParam="*" %>  

  该示例将缓存用户控件 60 秒,并且将针对查询字符串的每个变动、针对此控件所在的每个页面创建单独的缓存条目。  

  <%@ OutputCache Duration="60" VaryByParam="none"

  VaryByControl="CategoryDropDownList" %>  

  该示例将缓存用户控件 60 秒,并且将针对 CategoryDropDownList 控件的每个不同的值、针对此控件所在的每个页面创建单独的缓存条目。  

  <%@ OutputCache Duration="60" VaryByParam="none" VaryByCustom="browser"

  Shared="true %>  

  最后,该示例将缓存用户控件 60 秒,并且将针对每个浏览器名称和主要版本创建一个缓存条目。然后,每个浏览器的缓存条目将由引用此用户控件的所有页面共享(只要所有页面都用相同的 ID 引用该控件即可)。  

  页面级和用户控件级输出缓存的确是一种可以迅速而简便地提高站点性能的方法,但是在 ASP.NET 中,缓存的真正灵活性和强大功能是通过 Cache 对象提供的。使用 Cache 对象,您可以存储任何可序列化的数据对象,基于一个或多个依赖项的组合来控制缓存条目到期的方式。这些依赖项可以包括自从项被缓存后经过的时间、自从项上次被访问后经过的时间、对文件和/或文件夹的更改以及对其他缓存项的更改,在略作处理后还可以包括对数据库中特定表的更改。 

  在 Cache 中存储数据  

  在 Cache 中存储数据的最简单的方法就是使用一个键为其赋值,就像 HashTable 或 Dictionary 对象一样:  

  Cache["key"] = "value";  

  这种做法将在缓存中存储项,同时不带任何依赖项,因此它不会到期,除非缓存引擎为了给其他缓存数据提供空间而将其删除。要包括特定的缓存依赖项,可使用 Add() 或 Insert() 方法。其中每个方法都有几个重载。Add() 和 Insert() 之间的唯一区别是,Add() 返回对已缓存对象的引用,而 Insert() 没有返回值(在 C# 中为空,在 VB 中为 Sub)。  

  示例 

  Cache.Insert("key", myXMLFileData, new

  System.Web.Caching.CacheDependency(Server.MapPath("users.xml")));  

  该示例可将文件中的 xml 数据插入缓存,无需在以后请求时从文件读取。 CacheDependency 的作用是确保缓存在文件更改后立即到期,以便可以从文件中提取最新数据,重新进行缓存。如果缓存的数据来自若干个文件,还可以指定一个文件名的数组。  

  Cache.Insert("dependentkey", myDependentData, new

  System.Web.Caching.CacheDependency(new string[] {}, new string[]

  {"key"}));  

  该示例可插入键值为 "key" 的第二个数据块(取决于是否存在第一个数据块)。如果缓存中不存在名为 "key" 的键,或者如果与该键相关联的项已到期或被更新,则 "dependentkey" 的缓存条目将到期。  

  Cache.Insert("key", myTimeSensitiveData, null,

  DateTime.Now.AddMinutes(1), TimeSpan.Zero);  

  绝对到期:此示例将对受时间影响的数据缓存一分钟,一分钟过后,缓存将到期。注意,绝对到期和滑动到期(见下文)不能一起使用。  

  Cache.Insert("key", myFrequentlyAccessedData, null,

  System.Web.Caching.Cache.NoAbsoluteExpiration,

  TimeSpan.FromMinutes(1));  

  滑动到期:此示例将缓存一些频繁使用的数据。数据将在缓存中一直保留下去,除非数据未被引用的时间达到了一分钟。注意,滑动到期和绝对到期不能一起使用。 

  更多选项  

  除了上面提到的依赖项,我们还可以指定项的优先级(依次为 low、high、NotRemovable,它们是在 System.Web.Caching.CacheItemPriority 枚举中定义的)以及当缓存中的项到期时调用的 CacheItemRemovedCallback 函数。大多数时候,默认的优先级已经足够了 — 缓存引擎可以正常完成任务并处理缓存的内存管理。CacheItemRemovedCallback 选项考虑到一些很有趣的可能性,但实际上它很少使用。不过,为了说明该方法,我将提供它的一个使用示例:  

  CacheItemRemovedCallback 示例
 
  System.Web.Caching.CacheItemRemovedCallback callback = new System.Web.Caching.CacheItemRemovedCallback (OnRemove);

  Cache.Insert("key",myFile,null,

  System.Web.Caching.Cache.NoAbsoluteExpiration,

  TimeSpan.Zero,

  System.Web.Caching.CacheItemPriority.Default, callback);

  . . .

  public static void OnRemove(string key,

  object cacheItem,

  System.Web.Caching.CacheItemRemovedReason reason)

  {

  AppendLog("The cached value with key '" + key +

  "' was removed from the cache. Reason: " +

  reason.ToString());

  }  

  该示例将使用 AppendLog() 方法(这里不讨论该方法,请参阅 Writing Entries to Event Logs)中定义的任何逻辑来记录缓存中的数据到期的原因。通过在从缓存中删除项时记录这些项并记录删除的原因,您可以确定是否在有效地使用缓存或者您是否可能需要增加服务器上的内存。注意,callback 是一个静态(在 VB 中为 Shared)方法,建议使用该方法的原因是,如果不使用它,保存回调函数的类的实例将保留在内存中,以支持回调(对 static/Shared 方法则没有必要)。

  该特性有一个潜在的用处 — 在后台刷新缓存的数据,这样用户永远都不必等待数据被填充,但数据始终保持相对较新的状态。但实际上,此特性并不适用于当前版本的缓存 API,因为在从缓存中删除缓存的项之前,不触发或不完成回调。因此,用户将频繁地发出尝试访问缓存值的请求,然后发现缓存值为空,不得不等待缓存值的重新填充。我希望在未来的 ASP.NET 版本中看到一个附加的回调,可以称为 CachedItemExpiredButNotRemovedCallback,如果定义了该回调,则必须在删除缓存项之前完成执行。  

  缓存数据引用模式  

  每当我们尝试访问缓存中的数据时,都应该考虑到一种情况,那就是数据可能已经不在缓存中了。因此,下面的模式应该普遍适用于您对缓存的数据的访问。在这种情况下,我们假定已缓存的数据是一个数据表。  

  public DataTable GetCustomers(bool BypassCache)

  {

  string cacheKey = "CustomersDataTable";

  object cacheItem = Cache[cacheKey] as DataTable;

  if((BypassCache)    (cacheItem == null))

  {

  cacheItem = GetCustomersFromDataSource();

  Cache.Insert(cacheKey, cacheItem, null,

  DateTime.Now.AddSeconds(GetCacheSecondsFromConfig(cacheKey),

  TimeSpan.Zero);

  }

  return (DataTable)cacheItem;

  }  

  关于此模式,有以下几点需要注意:   

  ? 某些值(例如,cacheKey、cacheItem 和缓存持续时间)是一次定义的,并且只定义一次。 

  ? 可以根据需要跳过缓存 — 例如,当注册一个新客户并重定向到客户列表后,最好的做法可能就是跳过缓存,用最新数据重新填充缓存,该数据包括新插入的客户。   

  ? 缓存只能访问一次。这种做法可以提高性能,并确保不会发生 NullReferenceExceptions,因为该项在第一次被检查时是存在的,但第二次检查之前就已经到期了。   

  ? 该模式使用强类型检查。C# 中的 "as" 运算符尝试将对象转换为类型,如果失败或该对象为空,则只返回 null(空)。   

  ? 持续时间存储在配置文件中。在理想的情况下,所有的缓存依赖项(无论是基于文件的,或是基于时间的,还是其他类型的依赖项)都应该存储在配置文件中,这样就可以进行更改并轻松地测量性能。我还建议您指定默认缓存持续时间,而且,如果没有为所使用的 cacheKey 指定持续时间,就让 GetCacheSecondsFromConfig() 方法使用该默认持续时间。   

  相关的代码示例是一个 helper 类,它将处理上述所有情况,但允许通过一行或两行代码访问缓存的数据。请下载 CacheDemos.msi。  

  小结

  缓存可以使应用程序的性能得到很大的提高,因此在设计应用程序以及对应用程序进行性能测试时应该予以考虑。应用程序总会或多或少地受益于缓存,当然有些应用程序比其他应用程序更适合使用缓存。对 ASP.NET 提供的缓存选项的深刻理解是任何 ASP.NET 开发人员应该掌握的重要技巧。

posted @ 2006-04-12 16:13 不再回头 阅读(208) | 评论 (0)编辑 收藏

筛选器

IIS服务器

处理连接请求标题

处理连接请求数据

URL 映射成物理路径

授权用户(如果需要)

组织数据

写入日志

结束连接

OnReadRawData

OnPreprocHeaders

OnUrlMap

OnAuthentication

OnSendRawData

OnEndOfNetSession

发送给客户机

OnLog1显示了IIS服务器从接收到客户机请求数据到结束连接整个过程中IIS的处理步骤,以及筛选器可以获得的通知和处理方式。

1 IIS 服务器与筛选器工作流程

posted @ 2006-04-11 14:46 不再回头 阅读(235) | 评论 (0)编辑 收藏

versalsoft 的人太气人了 自己也想办法整个ISAPI

C++看着头就大 晕哦

一定把这个东西写好 省得买人家的东西 还受人家的气 晕死!
posted @ 2006-04-11 14:03 不再回头 阅读(134) | 评论 (0)编辑 收藏


  <head>
  <link id="MyStyleSheet" rel="stylesheet" type="text/css" runat="server" />
  </head>

  之后,在要更换CSS的页面中,使用如下代码


  Sub Page_Load(Sender As Object, E As EventArgs)
  If Not (IsPostBack)
  MyStyleSheet.Attributes.Add("href","/css/flostyle.css")
  End If

posted @ 2006-04-07 00:35 不再回头 阅读(176) | 评论 (0)编辑 收藏

select * from(
   select *, row=row_number() over(order by 1)
   from 你的表
)a where row between (页号 -1) * 每页页数 + 1 and 页号 * 每页页数



WITH PartsCTE AS(SELECT *, ROW_NUMBER() OVER(order by id DESC) as row FROM meetingroom)

SELECT * from PartsCTE where row between @intStart and @intStart+@intLength-1


--SQL SERVER 2005
DECLARE @pagenum AS INT, @pagesize AS INT
SET @pagenum = 2
SET @pagesize = 3
SELECT *
FROM (SELECT ROW_NUMBER() OVER(ORDER BY score DESC, speaker) AS rownum,
        speaker, track, score
      FROM SpeakerStats) AS D
WHERE rownum BETWEEN (@pagenum-1)*@pagesize+1 AND @pagenum*@pagesize
ORDER BY score DESC, speaker

posted @ 2006-04-02 16:25 不再回头 阅读(629) | 评论 (0)编辑 收藏

<style>
body
{margin: 30px; font-size:9pt;}

.a, .b, .c, .d, .e
{
width: 100px;
height: 100px;
margin: 5 auto;
color: #fff;
background: #000;
}
.aa, .bb, .cc, .dd, .ee
{
top: 10px;
left: 10px;
width: 10px;
height: 10px;
overflow: hidden;
background: #F90;
}
.b, .d, .e
{position: relative;}
.cc, .dd, .ee
{position: absolute;}
</style>

<div class="a">
<div class="aa"></div>
A:均不设置postion,一般嵌套关系
</div>

<div class="b">
<div class="bb"></div>
B:仅外div设置relative,一般嵌套关系
</div>

<div class="c">
<div class="cc"></div>
C:仅内div设置absolute,文档中为嵌套关系,页面中内div浮起[非float],相对于页面定位,与外div无关。
</div>

<div class="d" style="background:#ff0000">
<div class="dd" ></div>
D:外div设置relative,内div设置absolute,内div浮起来并相对于外div定位
</div>

<div class="d" style="background:#ff0000">
<div class="dd" style="position:relative"></div>
D:外div设置relative,内div设置relative,内div浮起来并相对于外div定位
</div>

<div class="e">
<div class="ee" style="left: -10px;"></div>
E:这个是说明边界问题。-10 != 反向10px间距
</div>
posted @ 2006-04-02 09:18 不再回头 阅读(10540) | 评论 (3)编辑 收藏

helix 限制下载、用户认证之我见!!!

本人自己也有一个影视网站,为全免费的,但是经过一段时间后,盗下的人越来越多,所以开始对 HELIX 进行研究,终于解决了盗下和用户认证的问题,以下是我的方法,不足之处清高手指教!

 

第一个大问题:服务器软件配置

 

SQL 中建立 VOD 数据库

经发现在 C:RealCommercedatabaseodbcmssql 下有个 ppvdemo.sql 文件,是 SQL 表结构,刚好可以用来 SQL 中建立数据库。

数据库的建立我就不多说了,
baseline

配置 ODBC 数据源

第一步:在系统 DSN 中选择“添加”

 

baseline

第二步:选择最下面的 SQL SERVER

 

baseline

第三步:定义数据库名称

 

baseline

第四步:选择 SQL 中我们刚刚建立的 VOD 数据库

 

baseline

第五步:测试连接,成功就对了

 

baseline

helix 配置

这里是重点哦,为了操作正确,建议你按我的标准一步一步来,等熟悉了以后你就可以自己改来改去了!!!

第一步:配置加载点。完成后记得“应用”

 

baseline

第二步:配置用户数据库。选择“ + ”号添加。完成后记得“应用”

 

baseline

第三步:配置用户认证,先按 1 增加一个域描述,“应用”后再按 2 方法增加一个用户。名字和密码都为 test_sql

 

baseline

第四步:配置商业应用。同样先按 1 方法增加一个规则名,应用后再按 2 方法赋予 test_sql 这个用户名的访问权限。

 

baseline

第五步:设置 test_sql 用户权限

 

baseline

一切好了以后,为了保证,重起 helix 服务。

然后再播放: rtsp://ip:554/vod1/filename

提示输入用户名密码,都输入 test_sql ,现在应该可以播放了吧?

如果还不能播放的话(一般错误为提示一行英文字,忘了:)),那就认真检查刚刚的配置,或者看你的许可是否支持用户认证功能。

第二个大问题:影视系统配置

服务器软件设置解决后,我们只能用一个或者几个固定的用户名播放,这样还是防止不了下载。

先介绍一下我的影视系统配置情况。我是采取了影视系统和现有论坛用户数据库相结合的。只有论坛注册用户才能播放电影。但是就是有那么些用户老是盗下影片,造成服务器流量剧增。

现在的解决方法是:

举列 play.asp 为播放窗口页面

页面开头就把用户名和一个临时密码写入 HELIX 数据库。假设有 test 这个用户已经登陆,他打开 play.asp 页面后, play,asp 中代码如下:

user=session("username") //test 用户已经登陆,所以 session("username")=test

lsmm=123456 // 这里可以写一个随机函数 , 每次都不一样

pathurl="vod1/" // 授权访问路径

然后把 user lsmm 用代码写入 vod 数据库中的 user

再写一个代码赋予 test 的访问路径到 vod 数据库中的 permissions

sql="insert into users (userid,password,uuid_writeable,uuid) values ('"&user&"','"&lsmm&"',1,'')"

conn.execute sql

sql="insert into permissions (userid,url,url_type,expires) values ('"&user&"','"&pathurl&"',1,'')"

conn.execute sql

数据库写入完毕后就是播放的代码了,播发代码就是播放窗口了,不用我说了吧。最后就是将 user permissions 两个表中的用户信息删除。

sql="delete from USERS;delete from permissions"

conn.execute sql

整个代码流程:

/// 把用户名写入 HELIX 数据库 ////

/// 播放代码 ///

/// 删除用户 ///

也就是说用户播发电影后马上把其用户和临时密码删除,这样他用任何方法都下载不了了。

思路给大家了,具体怎么操作还是要靠大家自己了阿, 你有更好的方法别忘了告诉我啊!

 

还有一个忘了说,在 VOD 数据库中的 access_log 表,里面详细记录了用户播放影片的日志,很实用哦,可以根据这些内容开发更强大的影视系统。

评论:

这种方法适合于在线用户小的用户,实现起来比较方便,无需要任何第三方插件,配置比较烦琐一点,另外还需要自己对数据库操作,人数少时,采用ODBC连接数据库不会出现稳定性的问题。另外加上不停操作数据库,给服务器带来了一些额外开销,特别是如果在线人数多时,可能会遇到认证不能通过的问题。所以只推荐小型客户使用。
posted @ 2006-03-31 20:45 不再回头 阅读(201) | 评论 (0)编辑 收藏

常常看到一些抱怨,无论多好的服务器总存在媒体的缓冲。经过观察发现,每当连接人数达到一定值时,客户就有播放缓冲的现象发生,而此刻服务器的CPU使用率、内存占用率、带宽占用等都很低,没有理由怀疑服务器此刻的状态。这一问题始终困扰我,后来尝试平均分配554、7070端口来播放,情况也没有根本好转。

    一天突然想到可以并列服务试试,就是同一台机器多装几个RealServer看看,详细请参阅 http://service.real.com/help/library/guides/server8/htmfiles/started.htm#35132 。
按照说明进行了如下工作,把原来的rmserver.cfg拷贝到 bin目录下,更名为rm2.cfg,名字短点好输入,放置和 rmserver.exe相同的目录好操作。把rm2.cfg中的端口都加1,如554,7070改为555,7071等等。

一、如何安装多个服务
    [参考 lucian (hyne) 的 单机安装多个helix server全攻略]
    首先复制上述的配置文件,用文本编辑器修改各个端口设置,如果你想多个,那么另存为多个名称不同的配置文件。然后注册系统服务:cmd下转到 ..\bin目录
  运行:rmserver -install:rm1 "你的实际路径\rm1.cfg" ,其中rm1是你命名的服务名称,可以按你的意愿取名。
    返回消息应该是Successfully installed the rm1 Service。如果想再安装rm2 service按照同样的方法完成。你可以在DOS启动这个新服务:rmserver.exe rm2.cfg。
    Real公司还提供了一种方法: 先执行 rmserver.exe -import:rmReg2 rm2.cfg 导入注册表,再执行 rmserver.exe -install:rm2 "rmReg2" 注册服务,用rmserver.exe registry:rm2 来启动服务。我个人认为这个比较麻烦,还不容易修改,不推荐。
    最后在服务管理里能发现新添加的rm1 ... 服务,修改其属性为自动启动,这样每次重新启动机器,服务都会自动运行的。

提示:
   rmserver -install:rm1 "????",如果这个路径不包含空格,就可以直接启动了。如果含有空格,你需要进入注册表,搜寻rm1.cfg这样的关键字,修改StartupParams项,检查其路径是否与你实际的一致,路径如果有空格,一定要把引号加上,如: "C:\program files\real\helixServer\rm1.cfg" 。建议大家都要检查这一项,因为有时比如RealServer8.x就写个错误的路径在那里,所以总有人说RealServer8.0不行,其实你把注册表修改对了就可以了。
   各个rmx.cfg中的端口不能相同,否则会发生端口冲突,造成无法启动服务,这也是许多人初次尝试失败的原因。我的经验是先对首个服务进行全面的配置,如加载点,IP限制等等,然后再复制这个配置文件,这样不仅能快速配置其它服务,而且也能保证配置的同步性。

二、有效性
    大多数人经过试用都表示有效,但也有如xxzHou就表示没有效果,他启动了4个服务,120以上时,客户端就出现缓冲,"而改用http方式时,此服务器可以提供600-700不缓冲播放500k左右的电影",对于引号中的声明我感到怀疑。首先我声明,这个方法是有效的,是我通过实践总结的。
    首先你要确认你的机器是否有余量,例如我的60人时缓冲,此时CPU使用率只有10%,内存也绰绰有余,这时启动多服务是有效果的。但服务不是越多越好,2-4个为好,这时CPU能到50-60%,这时的负荷已经很重了,能在40-50%是最好的。另外客户端的机器和软件状态不佳,也是造成缓冲的重要原因,还有你是否真正做到了服务平衡。
    我也发现不是所有的机器效果都明显,尤其是播放高带宽,如400-500k以上的,所能承受的人数急剧下降。带宽也是原因100M带宽的理论值是多少?不好说,还有收发器、交换机都能达到100M?我们没有有效的手段检验,专业性的仪器太贵,承受不起。但我知道原以为那些光纤收发器都是高科技产品,其实小厂都能生产,两三百元就能买到,而且质量良莠不齐,我们多次发现因为收发器性能下降造成实际带宽的下降。
    我个人认为所谓百兆可能只能发挥60-80M能力,这样你算算多少人?200多人的在线吧,如果你还同时通过这条线路提供网页、游戏等其他服务,可能打的折扣多了。上面说的"600-700不缓冲播放500k左右的电影",这时带宽多少呀?百兆是不可能的,只有是千兆网,这样的话是否全部通道都是千兆了?

    题外话,电信内部人员最终承认,发现1M的ADSL只能看225k的电影,2M看350k的,因为当别人报告缓冲时,他们用8M的看,结果一切正常,我猜测这可能是ADSL交换那儿不太好,不过谁敢对电信指点一二呀!所以具体说来这是个系统的综合问题,不能片面地钻一个地方。总之我是把服务器的性能发挥到极限了,剩下的只能看天命了。
    采用http是不错,我一度也曾采用这个办法,结果开始不错,当人数上来后就不行了。且人家能高速下载了,而且一旦稍有缓冲大家都开始下载,http不好限制线程,结果更拥挤更累机器,最终还不如流播放。另外中途中断了不能接续,拖放也不自如,还是不用为好。
    我个人认为是rm的服务软件的效率不行,至于版本估计美金买的也好不了哪去,要是D和正之间有这么大的差距,就不会打击D版了,这是多好的广告呀。目前为止我比较了周围的流媒体服务情况,在相同的硬件条件下,我这个是最好的。当然还有许多不满意的,所以才公开经验,希望有更好的建议和方案出现。
    
    通常流媒体服务器都是专用的,所以封闭全部不需要的端口,防止黑客攻击,我的就被攻击过。关闭不需要的服务,尽量释放系统资源,你可以尝试着关,只要不影响运行和服务的都关掉。我认为不要装防火墙、杀毒软件等这些软件,这些都涉及系统内核操作,消耗的资源不知道有多少。既然是服务器,你不会在上面玩游戏、看网页的,不存在感染病毒的途径。网友 quake777 称他的小服务器,不小心装了个瑞星防毒,HAHA~,25人联线就缓冲了。换了个诺顿企业版,最高40人联线时还跑得疯快,说明这些软件是有影响的。

三、关于Real官方的冗余和动态负载平衡
    关于Helix的冗余,不知大家仔细看过,它需要多台Helix服务器,这个好办,机器不缺。但你的内容加载点呢?我将近1T的资料,3台Helix服务,需要额外2T的内容空间,而且还要保证同步,我看是比较麻烦的。如果我真的有,我也会拿来增加内容,而不是做冗余。楼上还有一位说的DNS动态平衡也是针对多台Helix服务而言,通过DNS来分配不同的机器来提供服务。
    当然你可以使用专用的磁盘阵列,这也是Helix图例里表明的,多个Helix服务器共享这个阵列,通过DNS分配或其它方式均衡这些服务器,平衡服务。可是投资呢?不用说专用阵列了,单SCSI硬盘大家就知道有多贵了。要知道多数人的服务都是免费的,好多都是个人爱好者,像我一样,用普通微机做服务器,且没有发现IDE硬盘是瓶颈。那些专业的配置就不用考虑了吧。而且大家也看到讨论的,那些2个CPU的专业服务器 120人就缓冲了,赶不上我5000元2台服务器的(显示器不用的啦,远程控制的),呵呵,你们说呢?
    我的关键是一台机器,进行多个进程的同时服务,是尽力发挥一台机器的能力,和Real官方的说法是两个不同的概念。

四、端口平衡
    hyne 的算法挺好:
  Randomize
   rndcount=Int(Rnd*3)
   if rndcount=0 then
   response.write "pnm://*.*.*.*:7070"+url
   end if
   if rndcount=1 then
   response.write "pnm://*.*.*.*7071"+url
   end if
   if rndcount=2 then
   response.write "pnm://*.*.*.*:7072"+url
   end if

    我是采用asp.net编程,主要涉及以下内容,相关人员一看就会懂的。
    首先设置服务的数量和端口,在web.config中:
   <add key="HelixPort1" value="Real服务A:;554;7070;1755" />
    <add key="HelixPort2" value="Real服务B:;555;7071;1756" />
    <add key="WebPort1" value="网页浏览:;80" />
    <add key="FTPPort1" value="FTP下载:;21" />
    程序自动寻找HelixPort、WebPort和FTPPort加上递增的序号,直到找不到为止,如寻找到HelixPort3或WebPort2,发现不存在就终止。后面的值是我自己设定的格式,是名称加端口。程序会自动把HelixPort1的端口作为一组统计,同时把所有Helix类型的也统计在一起,这样提供给网页能实时反映在线人数,及其分布。最后有一个这样的结构数组,[端口号,不会出现重复的][组别,指Helix1,FTP1这类][类别,指Helix、Web这样的大类]。
        Public Structure moviePortDefine
            Dim TCP_port As Integer '端口号
            Dim GroupID As Integer  '分类索引
            Dim GroupName As String '分类名称
            Dim Cnt As Integer      '在线人数
            Dim TypeID As Integer   '端口序号
        End Structure

    然后有个程序对各个端口进行扫描:
        Dim p As New Process()
            p.StartInfo.FileName = "netstat.exe"
            p.StartInfo.Arguments = "-n"
            p.StartInfo.UseShellExecute = False
            p.StartInfo.RedirectStandardOutput = True
            p.Start() '执行了 netstat.exe -n 命令

        Dim output As String = p.StandardOutput.ReadToEnd()
            p.WaitForExit()

            Dim ss() As String = output.Split(vbCrLf)
            Dim ssTcp() As String
            Dim i, j, k As Long
            For i = 1 To ss.GetUpperBound(0) '寻找ESTABLISHED,表示建立连接的端口
                If InStr(1, ss(i), "ESTABLISHED", CompareMethod.Text) > 0 Then
                    k = InStr(ss(i), ":")
                    If k > 0 Then j = InStr(k + 1, ss(i), " ", 1)
                    If j > k Then
                        k = Val(Mid(ss(i), k + 1, j - k))
                        For j = 0 To NowFindedPort.GetUpperBound(0)
                            If k = NowFindedPort(j).TCP_port Then
                                NowFindedPort(j).Cnt += 1
                                Exit For
                            End If
                        Next
                    End If
                End If
            Next

    最后统计人数,提供在线报告,给出最少人数的端口,生成超连接。会编软件的往往只需要知道思路,而不是源代码,个人的习惯不同,有看别人代码的能力还不如自己编,看不懂的直接引用,往往出了问题就抓瞎。所以我只讲了我的思路,具体请自己研究。我正在整理我的电影系统,准备编写好说明文件后,编译(不含原码)供下载,不写不知道,写说明比编程还要费劲,要面面俱到,麻烦呀,不知道啥时能完成。
posted @ 2006-03-31 20:15 不再回头 阅读(149) | 评论 (0)编辑 收藏

在asp.net 2.0中,可以很方便地加密web.config文件里的敏感信息了.比如如果有权限操作服务器的话,
可以用下面的方法加密web.config里的敏感信息,比如要加密数据库连接串
aspnet_regiis -pe "connectionStrings" -app "/应用程序的名字"

如果没权限的话,可以在程序里动态实现

 

1 Configuration config  =  Configuration.GetWebConfiguration(Request.ApplicationPath);
2 ConfigurationSection section  =  config.Sections[ " connectionStrings " ];
3  section.ProtectSection ( " DataProtectionConfigurationProvider " );
4  config.Update ();
5
posted @ 2006-03-28 06:12 不再回头 阅读(140) | 评论 (0)编辑 收藏

页面调度采用了UrlRewrite技术,关于该技术的资料可以参考我转发的一篇文章:http://erpcrm.cnblogs.com/articles/232924.html

首先,让我们新建一个网站(我使用的是 VWD 2005 Express BETA2)。
1、添加一个default.aspx ,
该窗体不需要做什么工作,它的存在只有一个意义,就是告诉IIS 把类似的请求(www.xxx.com/)转过来,否则的话,ASP.NET是截获不到这种请求的。
2、我们在哪截获用户的请求呢?
当然是Global.asax了(当然了,你可以把代码放到Global.asax.cs中,或者自己实现IHttpModuler来达到类似的效果)。
代码如下:

;Global.asax文件,只有一行,可以看出具体的代码文件都在Global.asax.cs里面
<% @ Application Language = " C# "  CodeBehind = " Global.asax.cs "  Inherits = " Global "   %>

Global.asax.cs文件:
using  System;
using  System.Data;
using  System.Configuration;
using  System.Web;
using  System.Web.Security;
using  System.Web.UI;
using  System.Web.UI.WebControls;
using  System.Web.UI.WebControls.WebParts;
using  System.Web.UI.HtmlControls;


public   class  Global : System.Web.HttpApplication
{
        
protected   void  Application_BeginRequest(Object sender, EventArgs e)
     
{
       
              String appPath 
=  Request.AppRelativeCurrentExecutionFilePath;

              
if  (appPath.StartsWith( " ~/Admin/ " true null ))
        
{
            
return ;
        }

        
if  (appPath.Equals( " ~/WebResource.axd " , StringComparison.OrdinalIgnoreCase))
        
{
            
return ;
        }

        
if  (appPath.StartsWith( " ~/ApplicationTemplate/ " , StringComparison.OrdinalIgnoreCase))
      
{
            
return ;
        }

               
            
this .Context.RewritePath( " ~/ApplicationTemplate/DefaultTemplate.aspx " );                 

      }
  

 }

从以上的代码可以看出:
除那三个特殊的路径外,其它的请求全部重写到"~/ApplicationTemplate/DefaultTemplate.aspx",
那么
 DefaultTemplate.aspx 包含什么呢?      
让我们新建一个文件夹 ApplicationTemplate 在该文件夹下新建一个web窗体 DefaultTemplate.aspx。
只 是为了演示UrlRewrite,DefaultTemplate.aspx中你可以输入一些简单的内容,如:“这是一个默认的模版”;
这样当我们请求“/default.aspx”时,呈现在我们面前的页面是DefaultTemplate.aspx的内容。
不信?你先动手试试吧!

3、如果我们想 把 / 重写到 ApplicatonTemplate/defaultTemplate.aspx,而把 /product/ 重写到ApplicationTemplate/ProductTemplate.aspx,怎么做呢?

首先我们在ApplicationTemplate文件夹下,添加一个ProductTemplate.aspx。
我们可能会想到在 Global.asax.cs 的 Application_BeginReque方法里再添加一个对路径的判断,显然这是不灵活的。
怎么更灵活呢?就让我们来设计一个页面调度引擎吧!
在这里,我们叫他 ApplicationManager。
添加一个类文件 ApplicationManager.cs ,   VWD提示我们要把它放到 App_Code目录下,就按它说的办吧!

该类有个方法叫  String  GetNewPath(String  oldPath);
我们要这个方法输入“/ default.aspx”返回 “~/ApplicationTemplate/DefaultTemplate.aspx”,
输入"/product/" 返回 “~/ApplicationTemplate/ProductTemplate.aspx” 
如果输入的是“/Admin”,还应该返回“/Admin”。

我们假定GetNewPath()方法有这个功能,那么让我们改造一下 :Applicaton_BeginReques;

 protected void Application_BeginRequest(Object sender, EventArgs e)
    
{
       
        String appPath 
= Request.AppRelativeCurrentExecutionFilePath;
   String newPath 
= ApplicationManager.GetNewPath(appPath) 
        
if(newPath != appPath)
{
 
this.Context.RewritePath(newPath);
}
              

    }

今天先到这,我的下一篇文章会把源码提供出来,也许会和本文中的不太一致,但意思不会差。


posted @ 2005-09-09 12:31 WIND 阅读(757) | 评论 (2)编辑 收藏
 
该门户平台暂定名为:ECubePortal
ECubePortal是什么?
ECubePortal是一个类似于CommunityServer和DotNetNuke的企业级的门户平台,实际上它更像SharePoint(功能没有SPS复杂,但比它灵活)。它相比CS和DNN有两个最大的特点:
1、URL更友好
    CS和DNN里采用这样的Url链接,  www.xxx.com/default.aspx?tabindex=1;www.xxx.com/default.aspx?tabindex=2;
    在该平台中是这样   www.xxx.com/product/; www.xxx.com/service/
2、该平台中的模块采用的是 webpart,是由.net 2.0直接支持的,不像CS和DNN采用自己的标准。
其它的如 主题、皮肤、安全管理等都是建立在.net 2.0基础上,比CS和DNN要灵活方便。

一、设计思想
先让我们假设一种简单的公司网站需求:
有一家叫ECube的公司,想实现一个较简单的公司网站,首先要包含公司简介、产品简介、服务与支持、联系我们四个大栏目,
该公司要求,他们自己能够在线定制每个页面的内容,而且还表示如果有可能还要新加栏目(如 在线招聘),而且也希望他们自己能够在线完成。
通常我们是如下实现的:
先不考虑公司定制的要求,我们新建一个Web项目,然后添加4个页面:
default.aspx  //公司简介页面
product.aspx //产品页面
service.aspx //服务支持页面
Contac.aspx //联系我们 页面。

然后再填充每个页面的内容,页面间的链接,一个简单的公司网站就完成了。
如果考虑客户的深层次需求,事情可能就不是这么简单了,因此就有了CS、DNN。
CS、DNN给我们解决类似问题提供了很好的思路。
CS中,把网站的主栏目、子栏目都集中存储起来,然后用类似的url 去检索 default.aspx?tabid=1;
他们都实现了自定义的HttpModule,由HttpModule来截获用户的请求,然后再组装成一个页面。

我的方案也是这个思路,但组装页面部分交给.net webpart 去实现。
关于主题、皮肤、安全管理等利用.net 2.0的内部机制。

下一步,就让我们先实现一个简单的网站,以展示UrlRewrite的神奇效果。


参考文档:http://erpcrm.cnblogs.com/articles/234246.html
posted @ 2006-03-25 05:39 不再回头 阅读(263) | 评论 (0)编辑 收藏

仅列出标题
共4页: 1 2 3 4