感觉又回到了十几年前给机房机器装环境的日子。虽然Windows Server 2012早就不是主流服务器的首选但你去企业内部转一圈就会发现还有一大票老服务器稳定跑在上面很多核心业务系统、官网后台、内网应用都靠它撑着。配置Web服务器在这台系统上的需求不仅没有消失反而因为存量太大成了运维必须掌握的基本功。这篇内容不打算写成官方文档的复读机我按自己实际配服务器的流程来走一遍。从最开始的软件选型、角色安装到真正把网站跑起来、把PHP和数据库串进来再到底层安全和常见故障的处理尽量把每一步的“为什么”也讲清楚。不管你是刚接手公司服务器的半路运维还是想在自己电脑上搭个开发环境验证项目照着这份操作基本都能跑通。1. 动手前的环境评估与方案选型1.1 先搞清楚这台服务器要干什么很多人拿到一台Windows Server 2012第一反应是赶紧把IIS装上。但我的习惯是先停一下花十分钟搞清楚几个问题后面能少走很多弯路。这台服务器要承载什么应用如果是纯静态企业官网IIS开箱即用如果跑的是ASP.NET程序IIS原生支持几乎不需要额外配置如果要跑PHP那就要么用IIS加FastCGI模块要么改用Apache或者Nginx。Web服务器软件的选择本质上是跟着你的站点程序语言走的。第二预计的访问量是多少企业内部系统可能一天就几十个人用IIS默认配置绰绰有余如果是面向公网的官网就需要在并发连接数、应用池回收策略、缓存压缩这些方面提前做规划。第三数据库建在哪里如果你的程序要连MySQL数据库是装本机还是要单独一台机器。这个决定会影响后续的防火墙放行规则和连接串配置。我建议起步阶段数据库放同一台服务器上没问题等业务量上来了再拆分千万别一上来就搞微服务那套复杂架构中小场景纯粹给自己找麻烦。1.2 IIS、Apache、Nginx三选一怎么权衡在Windows平台上跑Web服务主流选择就是这三样。三个我都实际用过简单说下各自的脾性。对比项IISApacheNginx与Windows集成度原生集成图形化管理手动配置依赖配置文件手动配置Win版支持一般静态文件处理良好良好极强高并发优势明显PHP支持FastCGI配置一次即可mod_php或php-fpm文档多php-cgi稳定性需要调优ASP.NET支持原生完美支持配置繁琐不推荐折腾不推荐运维门槛鼠标点击为主易上手改配置文件适中改配置文件适中适合场景企业系统、ASP.NET/PHP混合老牌Web应用、学习资料多静态资源站、反向代理、高并发我个人在Windows Server 2012上默认选IIS理由很务实Windows单机整合度高不用额外装第三方服务安全更新跟随系统补丁走身份验证还可以直接对接域环境。IIS配合FastCGI跑PHP性能不算顶级但胜在稳定省心尤其是对于企业内网这种并发不高、追求可控的场景IIS绝对是首选。Nginx在Windows上我踩过不少坑多进程模型和Windows的兼容性远不如Linux上那么顺畅除非你明确要用它做反向代理否则别自找麻烦。1.3 安装前要准备的几样东西正式动手前这几样东西建议提前准备齐全能省下不少安装中途才发现缺东少西的尴尬一台装好Windows Server 2012的服务器或虚拟机确认系统盘有至少10GB以上的剩余空间。一个固定的局域网IP地址。尤其是做正式服务静态IP是底线。DHCP分配出来的IP一旦变化站点配置的绑定就全失效了。如果你的网站要对外提供访问域名和公网IP也得提前备好因为IIS绑定主机名和SSL证书时都要用到。最新的系统补丁。很多2012的坑其实在补丁里已经修掉了装机后先跑一遍Windows Update再做其他操作。用本机管理员账号操作。安装IIS角色会改动大量系统组件普通权限账号没法完成。准备工作就绪后就可以开始安装IIS了。2. 在Windows Server 2012上安装IIS实战2.1 通过服务器管理器添加角色功能注意这里我们不从网上去下载IIS安装包Windows Server 2012的IIS是系统组件直接通过“服务器管理器”就能装好。登录系统后打开“服务器管理器”。如果你习惯用英文版入口是Manage - Add Roles and Features中文版就是“管理”-“添加角色和功能”。整个向导分几个步骤安装类型选“基于角色或基于功能的安装”。服务器选择这一页确认选中的是本机服务器。到“服务器角色”页面往下拉勾选“Web服务器(IIS)”。勾选的时候系统会弹出一个提示框问你“添加Web服务器(IIS)所需的功能”直接点“添加功能”。真正需要仔细看的是Web服务器角色下的子组件。默认情况下系统只会装一部分常用模块。我一般会按下面的标准来勾选确保后续不会被某个功能缺失卡住“常见HTTP功能”静态内容、默认文档、HTTP错误、HTTP重定向、目录浏览全部勾上。目录浏览平时关着但装的时候要先装好后面排查问题方便。“运行状况和诊断”HTTP日志、请求监视器都勾上。log太重要了出了问题第一件事就是翻日志少了这个直接两眼一抹黑。“应用程序开发”如果只是静态站可以不选我建议直接把ASP.NET 4.5、.NET扩展性、CGI、ISAPI扩展和ISAPI筛选器全勾上。不要觉得用不到哪天要跑个PHP或者老ASP程序回来补装也可以但既然安装了就一步到位省得来回折腾。“管理工具”管理控制台必需IIS管理脚本和工具、管理服务可选建议也带上。点击下一步到“确认”页确认角色列表无误点安装。整个过程大概一到三分钟取决于服务器磁盘性能。2.2 安装完成后的基本验证安装完成后系统会自动打开IIS管理器的入口。打开浏览器访问http://localhost看到IIS的默认欢迎页就说明Web服务已经跑起来了。这里多说一句默认页面的存在意味着80端口正在监听后面你自己配置站点时要注意把这个默认站点停掉或者改绑定否则访问你的IP会先落到这个默认页上。在IIS管理器里左侧“连接”树会看到本机服务器节点展开后能看到“应用程序池”、“网站”两个关键节点。默认网站存在应用程序池里也有一个DefaultAppPool这说明IIS的核心服务都正常了。2.3 应用池和网站之间的关系先理清楚很多新手到这一步就急着建站了但我建议先把IIS里最核心的两个概念搞清楚应用程序池和网站。打个比方应用程序池就是一个独立运行的“工作单元”它决定了这个池里的网站用什么.NET版本运行、用什么权限身份干活、进程何时回收。网站则对应你的域名和物理目录。你创建的每个网站启动时会绑定到一个应用程序池上。这意味着一个池可以挂多个网站多个网站共享同一套进程设置。如果其中一个网站挂了池崩溃这个池里所有网站都会跟着报503。我遇到过不止一次一个池里塞了七八个站点一个程序出错全部遭殃。所以后来我养成了一个习惯生产环境里一个网站一个应用程序池。资源是多占了一点但故障隔离的收益远大于那点内存开销。3. 创建和配置你的第一个网站3.1 站点目录的规划与文件系统权限在IIS里建站之前先把目录规划好。我强烈建议不要用C盘尤其是系统盘是SSD且空间不富裕的时候。最常见的做法是单独分一个数据盘比如D:\wwwroot下面按站点建子目录D:\wwwroot\mysite。创建完物理目录后右键目录属性在“安全”选项卡里能看到默认权限。这里有一个关键点IIS的应用程序池默认运行身份是IIS_IUSRS组。你需要在目录的权限列表里手动添加IIS_IUSRS组并赋予“读取和执行”、“列出文件夹目录”、“读取”以及写入权限。如果你不给这个组任何权限站点就会报500或者403非常典型。我给客户维护服务器时见过有人在目录上直接给Everyone完全控制权限图省事。这种操作短期内网站能跑风险是任何本地进程都能读写你的网站文件一旦Web程序被上传了恶意文件整个服务器基本就裸奔了。正确的做法是精确到IIS_IUSRS组读取和执行权限必须给写权限只有在网站需要上传文件或生成缓存时才给。3.2 在IIS管理器里添加网站打开IIS管理器右键“网站”选择“添加网站”。网站名称填一个便于识别的名字比如MySite这个只是管理用不影响实际访问。应用程序池默认会新建一个同名的池保持默认即可。物理路径浏览选择你创建好的站点目录。绑定类型HTTP默认是http如果你要上HTTPS就选https并指定证书。IP地址如果服务器上只有一个IP选“全部未分配”就行。端口默认80。但要注意如果你之前那个默认网站没有停止80端口被占用了这时你得先把默认网站停掉再来建新站点。主机名这里填写你的域名比如www.example.com。如果暂时没有域名可以留空届时通过http://IP访问。确认无误后点确定一个网站就创建完成了。在浏览器里输入绑定的地址如果能出现你的页面内容说明最基本的Web服务已经通了。但这里还有一个最常见的坑——默认文档问题。如果你在浏览器里看到的是一整页目录列表而不是你的首页文件不要慌多半是默认文档没有匹配上。去IIS管理器里双击“默认文档”系统默认的顺序是Default.htm、Default.asp、index.htm、index.html通常情况下够用但如果你的首页是index.php或者中文环境下的default.aspx就需要点击右侧“添加”把这个文件名加进去。添加完成后把最常用的那个文档移到列表最顶上优先级会更高。3.3 使用主机名绑定实现一机多站一台Windows Server 2012服务器上跑多个网站是再正常不过的需求。实现方式有三种不同端口比如站点A用80端口站点B用8080端口。这种方式配置简单但用户访问时需要带端口号不友好。不同IP地址一台服务器配多个IP每个网站绑定独立IP。适合公网IP多个的场景企业内部一般比较难满足。相同IP和端口用不同的主机名区分也就是虚拟主机。这是最推荐的方式。主机名绑定的操作很简单在“添加网站”或“绑定...”弹窗里给每个站点填上不同的主机名。例如站点A的主机名填web1.internal.local站点B填web2.internal.local。然后确保内网DNS把这两个名字都解析到服务器IP上。很多人在这一步碰壁判断链路就两条第一DNS解析是否指向正确服务器第二IIS绑定是否包含了这个主机名。两个节点任意一个没对上访问就会失败。我自己调试时常用的命令是nslookup确认解析再在服务器上用curl -H Host: web1.internal.local http://127.0.0.1来测试IIS是否按主机名正确路由请求。3.4 应用程序池的核心参数我这样设每个网站创建时都会自动生成对应的应用程序池点进去能看到这里有一堆参数但对运维来说优先级最高的是这三项.NET CLR版本如果你的网站在跑ASP.NET程序选v4.0如果是纯静态或者PHP选“无托管代码”。托管管道模式推荐“集成”IIS与ASP.NET集成处理管线性能和兼容性都比经典好老程序兼容性出问题时才换“经典”模式。32位应用程序启用要特别注意这一点。如果你的PHP或者某些COM组件是32位的这里必须设为True否则会给你报500。我在配置老旧的PHP站点时踩过这个坑默认是False折腾了半天才想到是这个开关的问题。至于回收策略默认的“固定时间间隔1740分钟”其实还算合理但如果你不希望站点在一个随机时间点出现短暂的请求卡顿可以改成“特定时间”比如每天凌晨四点回收一次或者干脆取消固定回收只依赖内存限制回收。生产环境我一般不管默认的1720只把“特定时间”加上凌晨低峰期并设置虚拟内存限制让进程在爆掉之前自动重启。4. PHP与数据库环境的集成部署4.1 让IIS支持PHP的FastCGI配置很多人以为Windows服务器上跑PHP一定要装Apache并不是的。IIS通过FastCGI跑PHP不仅可行而且很稳定。具体做法如下。先去PHP官方网站下载Windows版的PHP。版本选择上要注意PHP官网提供x86和x64两种版本需要跟你的系统架构一致。但这里又一个坑如果你的IIS是以32位模式运行的也就是前面说的应用程序池“32位应用程序启用”设为True那你就要用x86版本的PHP。两者一旦对不上php-cgi进程根本起不来。下载后解压到比如C:\php目录。然后打开C:\php下的php.ini-development复制一份改名为php.ini这是PHP的配置文件。用记事本打开至少要做两处修改去掉; extension_dir ext前面的分号改为extension_dir C:\php\ext。启用你需要的扩展比如连接MySQL需要的extensionmysqli和extensionpdo_mysql把前面分号去掉。回到IIS管理器双击“处理程序映射”点击右侧“添加模块映射”弹出窗口里这样填请求路径*.php模块FastCgiModule可执行文件C:\php\php-cgi.exe名称PHP-FastCGI确认后在弹窗中选“是”系统会为PHP创建一个快速CGI应用程序池的配置。这里其实是在IIS应用层配置了一个FastCGI应用IIS收到对.php文件的请求时会通过FastCGI把请求交给php-cgi.exe处理。填写时注意可执行文件一定选准确路径别自己手动敲容易敲错。我见过太多因为路径差一个字母导致CScript.exe无法完成PHP配置的反面教材了。4.2 MySQL的安装配置要点Windows Server 2012上安装MySQL建议用官方安装包或者解压版。如果你用的是安装包安装过程比较简单但有几个点要格外留意。安装类型选Server only就够了省得把一堆开发组件装到生产服务器上。到了“Type and Networking”界面端口保持默认3306但“Windows Firewall”那一项要确保勾选“Open Windows Firewall ports for network access”让安装程序自动放行3306端口。设置密码时务必设置一个够强的root密码。很多人测试环境顺手填个root就完事了结果服务器暴露到公网后被扫描工具一天爆破几十次这教训太常见了。安装完成后我通常还会做两件事第一修改默认字符集。打开MySQL配置文件my.ini在[mysqld]下加上character-set-serverutf8mb4避免中文乱码问题。第二单独创建一个业务账号比如webuser并只授予业务数据库的权限而不是什么程序都用root连接。万一网站程序被脱库至少数据库其他库的数据是安全的。4.3 连接测试与常见的PHP数据库报错环境配置完写一个测试脚本来验证整条链路是否通畅。在网站物理目录下创建一个test.php文件?php $conn new mysqli(localhost, webuser, password, mydb); if ($conn-connect_error) { die(连接失败: . $conn-connect_error); } echo PHP连接MySQL成功当前版本 . mysqli_get_server_info($conn); $conn-close(); ?浏览器访问http://你的地址/test.php。如果看到连接成功说明IIS-PHP-MySQL整条链路已经全部打通。如果报404或空页面先确认PHP模块映射是否生效如果报Class mysqli not found说明php.ini里的extensionmysqli没启用或者扩展目录配置不对如果报连接被拒绝先检查MySQL服务是否启动再用命令行工具mysql -u root -p本地连一下确认。这些问题的排查路径基本是线性的不要乱猜一步一步来。4.4 防火墙放行规则与远程访问配置服务器装好环境后默认Windows防火墙会拦截外部访问。你需要给Web服务放行端口。打开“服务器管理器”-“工具”-“高级安全Windows防火墙”在“入站规则”里新建规则选择“端口”协议选TCP特定本地端口填80, 443然后选“允许连接”把规则命名为Web Server (HTTP/HTTPS)。如果你还需要开放MySQL的远程访问再放行3306端口的TCP流量但我强烈建议生产环境不要开放3306数据库访问尽量限制在本机连接。远程管理数据库用SSH隧道或内网跳板别直接暴露公网。这里有个小经验入站规则放行后本机能访问但别的机器还是不通时先别怀疑防火墙检查一下绑定的IP。IIS绑定默认是“全部未分配”但如果你为了测试某个站点手动填了具体的IP地址其他IP地址访问时是走不到这个站点的。这个坑我踩过不止一次每次都是折腾半天最后发现绑定写死了IP。4.5 安全加固的几个低成本高收益操作在新站点跑起来之后我强烈建议花半小时做一轮基础加固。第一删除IIS默认的欢迎页和默认站点。默认站点挂在80端口上如果被你配置的站点顶掉了它的物理目录里还遗留着一堆带IIS标识的示例页面很容易泄露服务器版本信息。第二HTTP请求头里的Server信息删掉。IIS默认的响应头里带Server: Microsoft-HTTPAPI/2.0或类似信息这是探针最爱的信息。在IIS管理器里选中站点打开“HTTP响应标头”把名为“Server”的标头删掉多少能给扫描器增加一点难度。第三请求筛选规则里限制文件扩展名和HTTP方法。IIS自带请求筛选功能可以精准控制哪些扩展名允许被执行。比如.php、.asp、.aspx这些动态脚本扩展才需要执行权限静态图片、css、js不需要经过动态处理不需要特殊处理。如果你对安全性极其敏感可以在请求筛选的“HTTP谓词”中禁用PUT和DELETE方法避免恶意请求探测攻击面。第四日志不能关。IIS默认开启了日志记录在“日志”图标里可以设置日志目录。我建议把默认的C:\inetpub\logs\LogFiles改到独立的数据盘分区避免日志膨胀塞满系统盘。日志保留策略也要定期清理否则长期运行的服务器日志文件能轻松攒出十几GB。4.6 启用压缩和缓存让访问速度生效Windows Server 2012上的IIS默认没有开启压缩。对于带宽不宽裕或者静态资源较多的站点压缩带来的提升立竿见影。双击IIS站点里的“压缩”图标勾选“启用静态内容压缩”和“启用动态内容压缩”。静态压缩是对css、js、html做Gzip压缩压缩率能到70%以上动态压缩是对动态接口返回做压缩会稍微吃一点CPU但通常收益大于开销。如果你的服务器CPU本身就很紧张可以只开启静态压缩。缓存方面打开站点级的“输出缓存”功能可以对静态文件设置客户端缓存时间。在IIS管理器中选中“静态内容”在右侧操作栏找到“设置客户端缓存”勾选“启动内容过期”模式选“在此时间段后过期”默认留30天即可。这样浏览器会缓存这些文件用户二次访问时直接从本地取页面加载速度质的提升。5. 常见故障与排查实录5.1 访问503应用程序池挂了现象浏览器返回503 Service Unavailable。排查思路打开IIS管理器看对应应用程序池的状态是否变成“已停止”。如果停了右键启动再去事件查看器里看应用程序日志中的错误信息定位崩溃原因。常见原因大致这几类应用程序池所使用的身份账号密码过期如果你用了自定义域账号站点的物理路径权限不足程序本身导致进程崩溃类似访问冲突。解决路径是先查事件日志再根据日志里的异常模块排查代码和权限。如果是密码过期导致的设置池绑定的身份为内置账号ApplicationPoolIdentity可免去密码管理麻烦。5.2 访问404.4或404.3路由和扩展名问题现象网站在服务器上跑着但访问具体页面时报404.4或404.3。404.4表示请求的物理路径不存在先把URL对应的文件路径核对一遍。404.3表示扩展名没有对应的处理程序比如站点用的是.html静态文件但IIS没装“静态内容”模块或者请求.php但FastCGI映射没有配好。回到“处理程序映射”里找一下看对应的扩展名有没有对应的模块映射。5.3 访问500且提示权限错误现象页面报500系统事件日志里看到对应的错误是“无法开始监听的进程”。处理这类问题先看事件日志里有没有IIS相关错误代码。如果错误指向php-cgi.exe无法启动回到应用程序池里把“32位应用程序启用”打开如果错误指向“拒绝访问”去站点目录的权限里确认IIS_IUSRS组确实拥有读取权限一个常见的老问题就是站点文件是从另一个服务器拷贝过来的原安全权限被带了过来覆盖了不必要的权限列表这时候重置一下权限往往就好了。5.4 80端口被其他进程占用现象启动网站时提示绑定失败或访问IP时不显示你的站点。先查端口占用情况管理员身份运行命令netstat -ano | findstr :80输出最后一列是占用进程的PID。再用命令查这条PID对应的是什么程序tasklist | findstr PID号最常见的是之前的默认站点还开着或者安装了其他Web服务如Apache、Nginx抢占了80端口。找到元凶后停掉那个站点或服务即可。如果占用的确实是一个系统进程比如System或http.sys说明IIS自己已经绑定了80端口那就去IIS检查是否有站点占用了绑定停掉多余的默认站点。5.5 本机访问正常但外部无法访问现象服务器上用localhost访问一切正常但同事们从自己电脑访问服务器公网或内网IP就是打不开。按顺序排查三块Windows防火墙有没有放行80端口。这一步最容易被忽略尤其是服务器装过安全软件后入站规则往往被篡改。IIS站点绑定的IP是不是写死了。如果绑定的IP不是服务器真实IP外部流量到了服务器后IIS直接不认。把绑定改回“全部未分配”即可。路由器或云安全组有没有映射。如果是云服务器光靠Windows防火墙还不够还得去云控制台的安全组放行端口这两层防火墙少任何一个外网都进不来。5.6 站点页面中文乱码现象页面打开正常但中文全是问号或乱码。多数情况是编码问题。先在浏览器里查看页面编码然后确认HTML文件的meta charsetutf-8有没有写对。PHP文件里加一行响应头header(Content-Type: text/html; charsetutf-8);。数据库连接时在连接字符串后加上?useUnicodetruecharacterEncodingUTF8Java系或者在PHPmysqli初始化后执行set names utf8mb4。MySQL表结构的排序规则是不是utf8mb4_general_ci。如果页面上传表单部分正常但写入数据库后乱码问题基本出在PHP和MySQL之间的字符集跟IIS没有关系往PHP代码和MySQL字符集上查。5.7 常见问题快查表现象最可能原因优先处理动作浏览器无法访问但本机可以防火墙未放行或绑定IP错误检查入站规则、检查站点绑定503 Service Unavailable应用程序池停止启动池并查看事件日志404.3缺少对应扩展处理程序查询处理程序映射500目录权限缺失或PHP配置错误检查IIS_IUSRS权限、32位开关500.19配置文件语法错误检查站点根目录的web.config80端口被占用默认站点或第三方Web服务netstat查PID并停止对应服务PHP能解析但连不上数据库MySQL服务未启动或账号权限不足确认服务状态与账号权限写在最后的小建议配置Windows Server 2012的Web服务器这件事本质上没有太多高深莫测的东西核心就是把系统角色、站点绑定、目录权限、程序处理映射这几个环节逐一做扎实。我自己的体会是90%的问题都集中在权限和端口这两件事上。权限给多了不安全给少了程序跑不起来端口放行漏了外网访问不了多放了又暴露攻击面。每次配完服务器我习惯把绑定信息、目录结构、开放端口、应用池设置这些整理成一份简单的文档和服务器放一起下次出问题恢复起来效率翻倍。另外提醒一句Windows Server 2012已经停止主流技术支持了如果这服务器要暴露在公网建议尽早规划向新版本系统迁移。但在那之前通过合理的安全加固和监控它依然能稳定扛住不少业务。如果你也正在配这台老系统希望能少走点我当年踩过的弯路。