【问题标题】:Creating a web farm in PowerShell在 PowerShell 中创建网络场
【发布时间】:2018-04-22 13:42:53
【问题描述】:

我正在尝试在 PowerShell 中自动创建服务器场。通过手动创建,我得到了以下 XML:

<webFarms>
    <webFarm name="alwaysup" enabled="true">
        <server address="alwaysup-blue" enabled="true">
            <applicationRequestRouting httpPort="8001" />
        </server>
        <server address="alwaysup-green" enabled="true">
            <applicationRequestRouting httpPort="8002" />
        </server>
        <applicationRequestRouting>
            <healthCheck url="http://alwaysup/up.html" interval="00:00:05" responseMatch="up" />
        </applicationRequestRouting>
    </webFarm>
    <applicationRequestRouting>
        <hostAffinityProviderList>
            <add name="Microsoft.Web.Arr.HostNameRoundRobin" />
        </hostAffinityProviderList>
    </applicationRequestRouting>
</webFarms>

然而,尝试通过 PS 执行此操作很麻烦:据我所知,没有专门的 API 可以通过此操作(WebFarmSnapin 用于旧版本)。

我已将注意力转移到IIS Administration Cmdlets,但只完成了一半。

我拥有的代码:

#####
# Overwriting the server farm
#####

Write-Host "Overwriting the server farm $($webFarmName)"

$webFarm = @{};
$webFarm["name"] = 'siteFarm'

Set-WebConfiguration "/webFarms" -Value $webFarm

#####
# Adding the servers
#####

Write-Host "Adding the servers"

$blueServer = @{}
$blueServer["address"] = 'site-blue'
$blueServer["applicationRequestRouting"] = @{}

$greenServer = @{}
$greenServer["address"] = 'site-green'
$greenServer["applicationRequestRouting"] = @{}

$servers = @($blueServer, $greenServer)

Add-WebConfiguration -Filter "/webFarms/webFarm[@name='siteFarm']" -Value $servers

#####
# Adding routing
#####

Write-Host "Adding the routing configurations"

$blueServerRouting = @{}
$blueServerRouting["httpPort"] = "8001"
Add-WebConfiguration -Filter "/webFarms/webFarm[@name='siteFarm']/server[@address='site-blue']" -Value $blueServerRouting

这会生成

<webFarms>
    <webFarm name="siteFarm">
        <server address="site-blue" />
        <server address="site-green" />
    </webFarm>
    <applicationRequestRouting>
        <hostAffinityProviderList>
            <add name="Microsoft.Web.Arr.HostNameRoundRobin" />
        </hostAffinityProviderList>
    </applicationRequestRouting>
</webFarms>

如您所见,它缺少与路由相关的端口。而且我现在还没有开始尝试添加运行状况检查。

我做错了什么?是否有一些我没有找到的 Cmdlet 使这更容易?

Related 但没有太多有用的答案(带有生成代码的 PowerShell 选项卡保持空白)。

【问题讨论】:

  • 你可以试试看 IIS 提供程序是否可以做你想做的事情technet.microsoft.com/en-us/library/ee909471(v=ws.10).aspx 可以说它比使用 IIS cmdlet 更具体,但有时这就是它所需要的。
  • 您是否查看过此 cmdlet 来配置端口? Set-WebBinding -Name 'Default Web Site' -BindingInformation "*:80:" -PropertyName "Port" -Value "1234"我对网络农场还不够熟悉,不知道这是否对您有帮助。
  • 如果您还没有,我建议您查看xWebAdministration DSC resource 以自动化网络农场的创建/配置/期望状态。 WebAdministration 模块还有很多不足之处(根据今年早些时候自动化一些 IIS 设置后的经验)
  • @TheIncorrigible1 我没有看到任何与网络农场相关的内容。我在看过去吗?
  • 我很好奇这是如何工作的!我们对容器做了一些类似但不是农场的事情。

标签: powershell iis load-balancing arr


【解决方案1】:

看到没有人提出解决方案:我采用了非常简单的解决方法,直接编辑 XML,而不是通过 API。

实际的 webfarm 功能我还没有开始工作,但似乎至少所有部分都在那里。

操作 XML 的示例如下:

$configPath = "C:\Windows\System32\inetsrv\config\applicationHost.config"
$configXml = [xml] (type $configPath)

[xml] $webFarmXml = @"
<webFarms>
    <webFarm name="siteFarm" enabled="true">
        <server address="site-blue" enabled="true">
            <applicationRequestRouting httpPort="$bluePort" />
        </server>
        <server address="site-green" enabled="true">
            <applicationRequestRouting httpPort="$greenPort" />
        </server>
        <applicationRequestRouting>
            <healthCheck url="http://mySite/up.html" interval="00:00:05" responseMatch="up" />
            <protocol reverseRewriteHostInResponseHeaders="true">
                <cache enabled="false" queryStringHandling="NoCaching" />
            </protocol>
        </applicationRequestRouting>
    </webFarm>
    <applicationRequestRouting>
        <hostAffinityProviderList>
            <add name="Microsoft.Web.Arr.HostNameRoundRobin" />
        </hostAffinityProviderList>
    </applicationRequestRouting>
</webFarms>
"@

$configXml.configuration.AppendChild($configXml.ImportNode($webFarmXml.webFarms, $true))
$configXml.Save($configPath)

【讨论】:

  • 你为什么不用power shell脚本直接创建这个xml
【解决方案2】:

看起来您通过修改 XML 配置文件本身找到了如何做到这一点。尽管感觉这似乎不是“正确的方法”,但直接更改配置文件是一个完全有效的解决方案。本质上,您创建了一个模板,配置模板提供了一种快速且可读的方法来生成可维护和可重复的配置。

我们可以通过将脚本中的模板文本提取到单独的文本文件中来改进这种方法。然后,脚本可以读取(或获取)模板并根据需要换出任何占位符值。这类似于我们通过将 HTML 模板与代码分离来分离 Web 应用程序中的关注点。

为了更直接地回答这个问题,让我们看看如何使用 PowerShell 和 IIS 管理 API 来执行此操作(您是对的 - 如果 IIS 和 Windows,最新版本不再支持 Web Farm Framework)。问题中的原始代码是一个好的开始。我们只需要区分操作配置collections(使用*-WebConfiguration cmdlet)和配置items(使用*-WebConfigurationProperty cmdlet)。这是一个脚本,它将根据问题中的示例设置配置值:

$farmName = 'siteFarm'

Add-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' `
    -Filter 'webFarms' `
    -Name '.'  `
    -Value @{ name = $farmName; enabled = $true }

Add-WebConfiguration -PSPath 'MACHINE/WEBROOT/APPHOST' `
    -Filter "webFarms/webFarm[@name='$farmName']" `
    -Value @(
        @{ address = 'site-blue'; enabled = $true },
        @{ address = 'site-green'; enabled = $true }
    )

Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' `
    -Filter "webFarms/webFarm[@name='$farmName']/server[@address='site-blue']" `
    -Name 'applicationRequestRouting' `
    -Value @{ httpPort = 8001 }

Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' `
    -Filter "webFarms/webFarm[@name='$farmName']/server[@address='site-green']" `
    -Name 'applicationRequestRouting' `
    -Value @{ httpPort = 8002 }

Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' `
    -Filter "webFarms/webFarm[@name='$farmName']/applicationRequestRouting" `
    -Name 'healthCheck' `
    -Value @{
        url = 'http://mySite/up.html'
        interval = '00:00:05'
        responseMatch = 'up'
    }

Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' `
    -Filter "webFarms/webFarm[@name='$farmName']/applicationRequestRouting" `
    -Name 'protocol' `
    -Value @{ reverseRewriteHostInResponseHeaders = $true }

Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' `
    -Filter "webFarms/webFarm[@name='$farmName']/applicationRequestRouting/protocol" `
    -Name 'cache' `
    -Value @{ enabled = $false; queryStringHandling = 'NoCaching' }

这可能有点过于冗长,但我想清楚地说明每个步骤的意图。此实现对-Filter 参数使用XPath 查询来选择适当的XML 节点。我们或许可以重构脚本以减少重复性任务,例如定义一个Add-FarmServer 函数,该函数接受服务器名称和端口,然后添加适当的指令。如果我们遇到锁定的配置问题,我们可能还需要Remove-WebConfigurationLock

我们选择使用模板还是程序化方法取决于项目和团队的偏好。当我们有许多类似的项目要配置时,API 变得更具吸引力,例如如果我们有数百台服务器要添加到网络农场。另一方面,模板很容易理解,不需要其他团队成员学习新的(可能有些令人困惑的)API。

【讨论】:

  • 感谢您富有洞察力的回答!我不太喜欢我的方法,因为它只是添加了一个 XML 块,所以我喜欢你的方法,因为它至少使用 XML API 来操作它。
【解决方案3】:

我一直在研究这个,我发现你可以在 Powershell 中使用Microsoft.Web.Administration 来完成这个。

Add-Type -AssemblyName "Microsoft.Web.Administration, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"

$iisManager = New-Object Microsoft.Web.Administration.ServerManager
$applicationHostConfig = $IISManager.GetApplicationHostConfiguration()

# Get the WebFarms section. Section names are case-sensitive.
$webFarmSection = $ApplicationHostConfig.GetSection("webFarms")
$webFarms = $WebFarmSection.GetCollection()

# Create a new webfarm and assign a name.
$webFarm = $WebFarms.CreateElement("webFarm")
$webFarm.SetAttributeValue("name", "MyNewWebFarmName")
# Add it to the parent element
$webFarms.Add($webFarm)
# get Webfarm server collection
$servers = $webFarm.GetCollection()
# add server
$serverBlue = $servers.CreateElement("server")
$routingBlue = $serverBlue.GetChildElement("applicationRequestRouting")
$routingBlue.SetAttributeValue("httpPort", "8001")
$serverBlue.SetAttributeValue("address", "MyNewWebFarmName-blue")
$servers.Add($serverBlue)
# Save changes
$iisManager.CommitChanges()

有两点很重要:

  1. 一旦调用 $iisManager.CommitChanges(),对象就会进入只读模式。在进行任何新更改之前,您需要重新实例化所有对象。

  2. 如果您决定在您的网络场中创建一个新服务器,如果您为该服务器分配一个名称,然后尝试访问其端口设置,则会遇到问题。您需要做的是先分配端口,然后分配名称以及是否启用/禁用。否则会抛出System.AccessViolationException: Attempted to read or write protected memory. 错误。

告诉我进展如何!

【讨论】:

  • 你把我引向了正确的方向,但是我花了一段时间才弄清楚我必须打电话给 $servers = $webFarm.GetCollection() 才能创建服务器
  • 所以,我用一个创建服务器的示例来更新你的答案
  • 我知道这是旧的,但很棒的帖子,这正是我所需要的,再加上来自 MS 的文档:docs.microsoft.com/en-us/dotnet/api/…
猜你喜欢
  • 2010-12-21
  • 2023-03-20
  • 1970-01-01
  • 2021-12-01
  • 1970-01-01
  • 2023-04-04
  • 2010-12-23
  • 2013-01-20
相关资源
最近更新 更多