博客 (81)

本文不定时更新中……


具备 RESTful 相关知识会更有利于学习 ASP.NET Web API:RESTful API 学习笔记

ASP.NET Web API 官网:https://www.asp.net/web-api


服务 URI Pattern

ActionHttp verbURI说明
Get contact listGET/api/contacts列表
Get filtered contactsGET/api/contacts?$top=2筛选列表
Get contact by IDGET/api/contacts/id获取一项
Create new contactPOST/api/contacts增加一项
Update a contactPUT/api/contacts/id修改一项
Delete a contactDELETE/api/contacts/id
删除一项


返回类型Web API 创建响应的方式
void返回空 204 (无内容)
HttpResponseMessage转换为直接 HTTP 响应消息。
IHttpActionResult调用 ExecuteAsync 来创建 HttpResponseMessage,然后将转换为 HTTP 响应消息。
其他类型将序列化的返回值写入到响应正文中;返回 200 (正常)。

HttpResponseMessage

可提供大量控制的响应消息。 例如,以下控制器操作设置的缓存控制标头。

public class ValuesController : ApiController
{
    public HttpResponseMessage Get()
    {
        HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, "value");
        response.Content = new StringContent("hello", Encoding.Unicode);
        response.Headers.CacheControl = new CacheControlHeaderValue()
        {
            MaxAge = TimeSpan.FromMinutes(20)
        };
        return response;
    } 
}

IHttpActionResult

public IHttpActionResult Get (int id)
{
    Product product = _repository.Get (id);
    if (product == null)
    {
        return NotFound(); // Returns a NotFoundResult
    }
    return Ok(product);  // Returns an OkNegotiatedContentResult
}

其他的返回类型

响应状态代码为 200 (正常)。此方法的缺点是,不能直接返回错误代码,如 404。 但是,您可以触发 HttpResponseException 的错误代码


完善 Help 页

一般都是通过元数据注释(Metadata Annotations)来实现的描述的。


显示接口和属性的描述:

打开 HelpPage 区域的 App_Start 目录下的 HelpPageConfig.cs 文件,在 Register 方法的首行取消注释行:

config.SetDocumentationProvider(new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml")));

在项目右键属性“生成”页,勾选“XML 文档文件”,并填写与上述一致的路径(App_Data/XmlDocument.xml)。


给接口加上 ResponseType 显示响应描述和示例:[ResponseType(typeof(TEntity))]


在实体模型的属性上加入 RequiredAttribute 特性可提供请求或响应中的实体的属性描述,如:[Required]


推荐使用:Swashbuckle

关于格式


在 WebApiConfig.Register() 中加入以下代码以禁止以 XML 格式输出(请按需设置):

GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();

Json 序列化去掉 k__BackingField

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver { IgnoreSerializableAttribute = true };

如果属性值为 null 则不序列化该属性

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };



xoyozo 7 年前
6,082

附加消息:暂无该开发者或未上传过应用

原因: 没有上架应用(隐藏的不算上架),应用设置显示后记得在版本管理中将版本也设为显示。


附加消息:抱歉,开发者验证无效

原因:可能是没有达到认证要求,不允许加群(譬如:需应用最低总安装量 1000 次)


DZ 水很深,慎入:http://open.discuz.net/?ac=document&page=xootan


2018.8.14 踩坑:

还有,加群要开发者中填写的 QQ 才能加,因为验证是全自动程序判断的。

如果要跳过安装量 1000 次的要求,就直接花钱购买会员,不过购买会员也是一件非常艰难的事情,在与“Q群管家”这个机器人 QQ 的对话中发送“@购买vip”,绝对能让你体验到一种有钱也花不出去的感受。

做这么多花哨的东西,不如踏踏实实把产品做好。


2018.8.15 踩坑:

跟Q群管家对话,@login 时,由于密码过于复杂,消息没反应,特殊符号别提了,连纯大小写字母数字也不行,后改成纯数字密码登录成功。

加群完全看基本信息中填写的 QQ 客服 号,群主是机器人,只要应用是上架显示的,版本是显示的,就可以用这个QQ客服申请入群,(可以改)。

xoyozo 8 年前
4,159

工作这几年碰到的版本检测升级的接口也算是五花八门,啥样的都有,但肯定有的功能是有个 apk 的下载链接,能间接或直接提示你是强制还是非强制更新:

  • 间接是指提供你后台最新版本号,让你自己与本地版本号通过比较得出是否升级;

  • 直接就是后台接口直接返回个 Boolean 类型告诉你是强制或者非强制更新。

个人认为一个好的版本检测接口需要设计的更灵活更清晰用起来更方便,下面就我理解的接口设计如下(如思路有误,欢迎指正):

总字段如下(并不是所有字段都要返回给客户端):
  1.最新版本号 :newVersion
  2.最小支持版本号 : minVersion
  3.apk 下载 url : apkUrl
  4.更新文案 : updateDescription
  5.是否有更新 : isUpdate
  6.是否强制更新 : forceUpdate 可选字段:
  7.apk 文件大小:apkSize
  8.apk 的文件 MD5 值:md5

方案一(后端处理逻辑):
在客户端请求参数中添加当前版本号 currentVersion 传输给后台,由后台根据客户端传过来的当前版本号 currentVersion 做相应的判断后给出是否强制更新。
后端逻辑如下:

  1. 如果 currentVersion < newVersion, 则 isUpdate = true;

    • 如果 currentVersion < minVersion, 则 forceUpdate = true;

    • 如果 currentVersion >= minVersion, 则 forceUpdate = false;

    • 如果有特殊需求可指定某个版本必须强制更新,如 currentVersion == XXX, 则 forceUpdate = true;

  2. 如果 currentVersion == newVersion,则 isUpdate = false.

结论:
返回客户端的字段仅需要 apk 下载 url : apkUrl更新文案 : updateDescription是否有更新 : isUpdate是否强制更新 : forceUpdate 这四个字段即可。

方案二(前端处理逻辑):
逻辑和后端处理逻辑大体上一致,只是把逻辑判断移到前台,故需要后端提供最新版本号 :newVersion最小支持版本号 : minVersionapk下载url : apkUrl更新文案 : updateDescription 这四个字段。

客户端逻辑如下:

  1. 如果 currentVersion < newVersion, 则有更新信息;

    • 如果 currentVersion < minVersion, 则需要强制更新;

    • 如果 currentVersion >= minVersion, 则不需要强制更新;

  2. 如果 currentVersion == newVersion,则没有更新信息。


总结:
细心的你可能会发现上面的可选字段 apkSize 和 md5 并没有用到,既然是可选字段也就是可用可不用,根据需要决定是否采用,这里来讲下他们的用处。

  • apk 文件大小 apkSize
    这个用处可以说出于考虑用户体验,需要在升级弹框出来展示给用户将要更新的内容多大,让用户决定在非 WIFI 状态是否要更新,不能为了拉用户下载量或所谓的 UV 数直接让用户在不知道大小的情况下去直接下载(土豪用户绕路)

  • apk 的文件 MD5 值
    这个主要是出于安全考虑吧,因为文件内容固定的话对应的 md5 是一样的,我们可以通过这个 md5 值来和下载的 apk 的 md5 值进行比较去保证我们从服务器更新下载的 apk 是一个完整的未被篡改的安装包,也就是说如果我们下载的 apk 的 md5 值和服务器返回的 md5 值相等,则说明我们下载的 apk 是完整的,且没有被相关有心人处理过的 apk。

综上所述,这个版本更新的处理逻辑客户端和后端谁来做都可以,无关乎懒不懒的问题,个人感觉灵活性后端比客户端方便多了,毕竟后端可以指定 minVersion 与 newVersion 中间的任意一个版本强制更新,而客户端做起来就没有那么灵活了,个人见解,如有更好的方案,欢迎指教。



转自 闲庭CC 8 年前
4,190

原因:在调用 DownloadFile 方法前未创建目标目录或目录无写入权限。

xoyozo 8 年前
7,959

“/”应用程序中的服务器错误。


The host xxx does not support SSL connections.

说明: 执行当前 Web 请求期间,出现未经处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。 

异常详细信息: MySql.Data.MySqlClient.MySqlException: The host xxx does not support SSL connections.



在 Web.config  的 connectionStrings 节点找到相关数据库连接,在 connectionString 中增加属性值:SslMode=none

xoyozo 8 年前
6,166

“/”应用程序中的服务器错误。


指定的参数已超出有效值的范围。
参数名: site

说明: 执行当前 Web 请求期间,出现未经处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。 

异常详细信息: System.ArgumentOutOfRangeException: 指定的参数已超出有效值的范围。
参数名: site

解决方法:安装 IIS

xoyozo 8 年前
7,450
  1. 下载 Senparc 官方 Sample


  2. 打开:\WeiXinMPSDK-master\src\Senparc.Weixin.MP.Sample\Senparc.Weixin.MP.Sample.sln


  3. 工具 - NuGet 包管理器 - 管理解决方案的 NuGet 程序包 - 更新

    选择所有的包(Microsoft.Net.Http 无法更新,暂不勾选),更新

    Microsoft.Net.Http 是个老顽固,无法更新也无法卸载,原因是它的语言包 Microsoft.Net.Http.zh-Hans 无法安装。我们切换到“已安装”选项卡,搜索“Microsoft.Net.Http”,选中 Microsoft.Net.Http.zh-Hans 并卸载它,现在我们可以更新 Microsoft.Net.Http 了。


  4. 【可能】运行报错:

    “/”应用程序中的服务器错误。

    配置错误

    说明: 在处理向该请求提供服务所需的配置文件时出错。请检查下面的特定错误详细信息并适当地修改配置文件。 

    分析器错误消息: 创建 system.web.webPages.razor/host 的配置节处理程序时出错: 未能加载文件或程序集“System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)

    源错误: 

    行 4:    <configSections>
    行 5:      <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
    行 6:        <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    行 7:        <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    行 8:      </sectionGroup>


    源文件: E:\WeiXinMPSDK-master\src\Senparc.Weixin.MP.Sample\Senparc.Weixin.MP.Sample\views\web.config    行: 


    展开 Senparc.Weixin.MP.Sample 引用,查看 System.Web.Razor 的属性,复制版本号。打开 \views\web.config,修改 System.Web.WebPages.Razor 的 Version(有 3 处)。


  5. 对于小型开发项目来说,我习惯将所有代码放在同一个项目(Project)中来,所以做了以下处理:(盛派官方分离这些代码是为了同时供 MVC 和 WebForms 重用)

    在 Senparc.Weixin.MP.Sample 中添加文件夹 CommonService,将 Senparc.Weixin.MP.Sample.CommonService 项目中的文件夹和文件(.config 除外)拖到 CommonService 文件夹中。

    卸载 Senparc.Weixin.MP.Sample.CommonService 项目并删除引用。


  6. 在解决方案的 Libraries 文件夹中,我们看到 Sample 项目了以下功能模块,这些就是 Senparc.Weixin 的源代码,如果不需要修改,可以卸载它们改为使用从 NuGet 获取,以便随时更新到最新版本:

    Senparc.WebSocket

    Senparc.Weixin

    Senparc.Weixin.MP

    Senparc.Weixin.MP.MvcExtension NuGet 中对应的包名为:Senparc.Weixin.MP.MVC

    Senparc.Weixin.Open

    Senparc.Weixin.Work

    Senparc.Weixin.WxOpen

    Senparc.Weixin.Cache.Memcached

    Senparc.Weixin.Cache.Redis

    卸载这些项目,并在 NuGet 中安装这些模块(搜索“Senparc.Weixin”第一页都在了,认准作者 Jeffrey Su)

    单元测试项目中的引用也按需更换,当然也可以卸载这些单元测试项目(视情况保留 Senparc.Weixin.MP.Sample.Tests) 。


  7. 【可能】运行报错


    HTTP Error 500.19 - Internal Server Error

    无法访问请求的页面,因为该页的相关配置数据无效。

    配置源:

    134:     </sessionState>

    135:   <sessionState customProvider="Memcached" mode="Custom">

    136: <providers>


    可以在 Global.asax 的 RegisterWeixinCache() 中修改 Memcached 配置。

    或者打开 Web.config,找到 Memcached 所在的 sessionState 标签,注释掉,这样程序自动使用上方的 InProc(应用进程内)。

    如果开启了 ASP.NET State Service 服务,那么建议改用 StateServer,与 Custom 一样需要序列化,方便日后改用 Memcached 或 Redis。


  8. 再次更新 NuGet,否则会提示无法加载 Enyim.Caching 的错误(报错行:MemcachedObjectCacheStrategy.RegisterServerList(memcachedConfig);)。


  9. 接下来,进入微信公众平台,在左侧 开发 - 基本配置 中设置相关参数(填写“服务器地址(URL)”如“https://weixin.xoyozo.net/weixin/”),打开 Sample 项目中的 Web.config,配置我们的公众号参数。


  10. 将项目发布到服务器上,尝试向公众号发送消息吧。


  11. 单元测试

    设置单元测试中的公众号配置项:打开 Senparc.Weixin.MP.Test/CommonAPIs/CommonApiTest.cs,在 AppConfig 方法中可以看到支持两种配置方式,在 Senparc.Weixin.MP.Test/Config/test.config 配置文件中配置,或直接在 CommonApiTest.cs 文件中配置,前者格式如下,后者建议只在个人测试项目中使用。

    <Config>
      <AppId>YourAppId</AppId>
      <Secret>YourSecret</Secret>
      <MchId>YourMchId</MchId>
      <TenPayKey>YourTenPayKey</TenPayKey>
      <TenPayCertPath>YourTenPayCertPath</TenPayCertPath>
      <!-- 小程序 -->
      <WxOpenAppId>YourOpenAppId</WxOpenAppId>
      <WxOpenSecret>YourWxOpenSecret</WxOpenSecret>
    </Config>

    另外,将 _testOpenId 值改为自己的微信号在本公众号上的 openid。


  12. 微信网页授权(OAuth2)

    打开 OAuth2Controller 控制器,将“Index”Action 中的盛派的网址(有 2 处)改成:

    Request.Url.Scheme + "://" + Request.Url.Authority + "/Oauth2/……


  13. 未完待续……

xoyozo 8 年前
8,365

上一篇介绍了如何创建用于 https 的 SSL 证书,本文讲述如何将创建好的 SSL 证书配置到 nginx 中。

 

导入证书

将 .key 文件和 .crt 文件上传到服务器,位置如:/etc/ssl/

 

配置 .conf

打开网站配置文件 *.conf,一般在 /usr/local/nginx/conf/vhost/

添加监听 443 端口:

listen 443 ssl;

添加 ssl 配置信息:

ssl_certificate /etc/ssl/yourdomain.com.crt;
ssl_certificate_key /etc/ssl/yourdomain.com.key;
ssl_prefer_server_ciphers on;

yourdomain.com.crt 和 yourdomain.com.key 改成真实的文件名

 

实现 http 自动跳转 https

配置非 443 端口请求跳转 443 端口访问:

if ($server_port !~ 443)
{
    rewrite ^(/.*)$ https://$host$1 permanent;
}

如果要求仅将 GET/HEAD 请求自动跳转(POST 请求自动跳转会丢失表单数据),那么改成:

set $redirect_https 0;
if ($server_port !~ 443)
{
    set $redirect_https 1;
}
if ($request_method ~ ^(GET|HEAD)$)
{
    set $redirect_https "${redirect_https}2";
}
if ($redirect_https = 12)
{
    rewrite ^(/.*)$ https://$host$1 permanent;
}


验证

最后来检查一下配置得对不对:https://www.geocerts.com/ssl_checker


扩展阅读

在 IIS 中部署 SSL

安装 SSL 证书遇到的一些问题

 


xoyozo 8 年前
6,797

一、概述

    重定向常常和请求转发放在一起讨论(前者是两次不相关的请求,后者是一次请求服务器端转发),然而本文并不讨论两者的区别,而是HTTP 1.0规范和HTTP 1.1规范中关于重定向的区别,以及实际使用中的情况。

    重定向实际使用是一个响应码(301或302或303或307)和一个响应头location,当浏览器收到响应的时候check响应码是3xx,则会取出响应头中location对应的url(重定向中url的编码问题,请参看点击打开链接),然后将该url替换浏览器地址栏并发起另一次HTTP事务。

    关于301、302、303、307的区别,找不到好的文章,因此打算直撸HTTP 1.0规范和HTTP 1.1规范,结合一些实际的案例和tomcat实现,来说清楚这几个状态码的差异。

1. 百度https重定向

    如下图所示,原请求访问的是http://www.baidu.com,然后返回302和location=https://www.baidu.com,从http转到https。不过关于响应行中302状态码的描述存在争议,在下文中会详细讨论。

20160302023117361.png

20160302022905326.png

20160302022920077.png

2. tomcat重定向源码

20160302023539001.png

二、详细

    http 1.0规范中有2个重定向——301和302,在http 1.1规范中存在4个重定向——301、302、303和307,其中302是值得讨论讨论的。

1. http 1.0

301

    301状态码在HTTP 1.0和HTTP 1.1规范中均代表永久重定向,对于资源请求,原来的url和响应头中location的url而言,资源应该对应location中的url。对于post请求的重定向,还是需要用户确认之后才能重定向,并且应该以post方法发出重定向请求。

    关于post请求重定向用户确认的问题,实际上浏览器都没有实现;而且post请求的重定向应该发起post请求,这里浏览器也并不一定遵守,所以说HTTP规范的实现并未严格按照HTTP规范的语义。

    在301中资源对应的路径修改为location的url,在SEO中并未出现问题,但是在302中就出现了302劫持问题,请往下看。

20160302031823754.png

302

    在http 1.0规范中,302表示临时重定向,location中的地址不应该被认为是资源路径,在后续的请求中应该继续使用原地址。

    规范:原请求是post,则不能自动进行重定向;原请求是get,可以自动重定向;

    实现:浏览器和服务器的实现并没有严格遵守HTTP中302的规范,服务器不加遵守的返回302,浏览器即便原请求是post也会自动重定向,导致规范和实现出现了二义性,由此衍生了一些问题,譬如302劫持,因此在HTTP 1.1中将302的规范细化成了303和307,希望以此来消除二义性。

    补充:302劫持——A站通过重定向到B站的资源xxoo,A站实际上什么都没做但是有一个比较友好的域名,web资源xxoo存在B站并由B站提供,但是B站的域名不那么友好,因此对搜索引擎而言,可能会保存A站的地址对应xxoo资源而不是B站,这就意味着B站出了资源版权、带宽、服务器的钱,但是用户通过搜索引擎搜索xxoo资源的时候出来的是A站,A站什么都没做却被索搜引擎广而告之用户,B站做了一切却不被用户知道,价值被A站窃取了。

20160302024330129.png

2. http 1.1

301

    和http 1.0规范中保持一致,注意资源对应的路径应该是location中返回的url,而不再是原请求地址。

302

    在HTTP 1.1中,实际上302是不再推荐使用的,只是为了兼容而作保留。规范中再次重申只有当原请求是GET or HEAD方式的时候才能自动的重定向,为了消除HTTP 1.0中302的二义性,在HTTP 1.1中引入了303和307来细化HTTP 1.0中302的语义。

20160302034048122.png

303

    在HTTP 1.0的时候,302的规范是原请求是post不可以自动重定向,但是服务器和浏览器的实现是运行重定向。

    把HTTP 1.0规范中302的规范和实现拆分开,分别赋予HTTP 1.1中303和307,因此在HTTP 1.1中,303继承了HTTP 1.0中302的实现(即原请求是post,也允许自动进行重定向,结果是无论原请求是get还是post,都可以自动进行重定向),而307则继承了HTTP 1.0中302的规范(即如果原请求是post,则不允许进行自动重定向,结果是post不重定向,get可以自动重定向)。

20160302050017182.png

307

    在http 1.1规范中,307为临时重定向,注意划红线的部分,如果重定向307的原请求不是get或者head方法,那么浏览器一定不能自动的进行重定向,即便location有url,也应该忽略。

    也就是307继承了302在HTTP 1.0中的规范(303继承了302在HTTP 1.0中的实现)。

20160302045035716.png

3. 小结

    在HTTP 1.0规范中,302的规范并没有被服务器和浏览器遵守,即规范和实现出现了二义性,因此在HTTP 1.1中,将302的规范和实现拆分成了303和307。


20160304095217787.png

三、结论

    虽然在不同版本的http规范中对重定向赋予了不同的语义,但是因为使用历史和服务器实现等原因,在实际中并不一定安全按照http规范实现,因此我个人感觉上述讨论只是一个了解,在实际写代码中302还是继续用吧···


参考:

1. 《http 1.0规范》
2. 《http 1.1规范》

3. 博客:点击打开链接


附注:

    本文如有错漏,烦请不吝指正,谢谢!


转自 唐无敌 8 年前
6,397

本文不定时更新!


A: MySQL 执行 SHOW FULL PROCESSLIST 

Q: 查看连接数和慢查询,适用于 MySQL 数据库无法连接 1040


A: iftop -i eth0

Q: 查看占用带宽的IP(命令:iftop -i eth0 -F ip/24),添加到安全组、防火墙、宝塔的黑名单中。

命令 grep -l "x.x.x.x" /www/wwwlogs/*.log 可以在 wwwlogs 目录下的所有 .log 文件中查找指定的恶意 IP。


A: goaccess -f xxx.log

Q: 实时分析网站日志,查看请求最多的IP


A: net.xoyozo.weblog 日志分析工具

Q: 自制的 Web 日志分析工具,可按多种方式排序,纠出可疑访问


A: 重启 web 服务器

Q: 有时候能解决 CPU 和内存消耗的问题,如果一会儿又升高,则需要找另外的原因


Q: 500 服务器内部错误

502 Bad Gateway

504 Gateway Time-out

A: 查看 php 日志,可能的路径:

/usr/local/php/var/log/php-fpm.log

/www/server/php/[版本]/var/log/php-fpm.log


Q: RDS MySQL IOPS 使用率高的原因和处理

A: 根据时间点查看慢查询


Q: Discuz! 论坛界面错乱、表情不显示、模块缺失、登录失败、发帖失败等等

A: 进入管理中心 - 工具 - 更新缓存,能解决大部分问题


Q: Discuz! 浏览帖子提示“没有找到帖子

A: 进入数据库,修复表 pre_forum_post 或分表


Q: CPU 100% 或内存 100%,负载100+

A: 原因有很多,以下是一些建议:

Windows 在任务管理器中查看进程

当前是否有正常的大流量访问(譬如民生类论坛的某个帖子突然火了)特别是重启无效的情况

对比网站日志大小可大致确定哪个网站被大量恶意请求。

观察:命令 top

排查:通过关闭网站来确定是某网站的问题,通过关闭功能确定是某功能的问题,如果 nginx 崩溃请参下条

案例:通过修改 mobcent 文件夹名确定是安米的文件被疯狂请求导致的,更新插件和 mobcent 包解决问题。

如果都是正常访问,top 看到很多 php-fpm,而且个个占用 CPU 还不小,那么根据服务器硬件配置来修改 php 的并发量,如宝塔面板在 php 设置 - 性能调整 页,300 并发方案的推荐配置是:

max_children:300
start_servers:30
min_spare_servers:30
max_spare_servers:180

另外,memcached 或 redis 的配置也可以进行相应的修改。

另一个案例是 kswapd0 进程占满 CPU,原因是内存不足导致 swap 分区与内存频繁交换数据。同样调整 php 的设置即可。

也可以通过 iftop 来查询占用带宽较多的 IP 并封禁(出方向),如果 CPU 能降下来,那这个 IP 就是罪魁祸首。

* 使用 WAF 的审计 WAF 日志,未使用 WAF 的审计 Web 日志。


Q: 阿里云 ECS 的 CPU 突然达到 100%,并持续到次日 0:00 左右

A: 可能 ECS 是 t5 规格,受 CPU 积分制度限制,积分耗尽时 CPU 不工作。解决方法是更换其它规格产品或升配。


Q: ASP.NET 所在服务器 CPU 突然达到 50% 或 100%,并持续

A: 首先确定哪个网站,再依次排查网站各功能。可能是 HttpWebRequest 请求远程数据时长时间未返回结果导致的程序阻塞。


Q: nginx 服务停止

A: 查看 nginx 日志

WDCP 路径:/www/wdlinux/nginx-1.0.15/logs/error.log


Q: 公网出带宽 100%,其它指标正常

A: Windows 在任务管理器-性能-资源监视器-网络 查看占用带宽的进程PID,然后在任务管理器-详细信息中的找到对应的用户(如果为每个网站分别创建了用户,就能知道是哪个网站占用了带宽);如果是被 PID 为 4 的 System 占用大部分带宽,也可以尝试重启 IIS 来解决。

CentOS 使用 nethogs 查看占用带宽的进程PID和USER,如果为每个网站分别创建了用户,就能知道是哪个网站占用了带宽,否则只能一个个关闭网站来判断,不知道大家有没有好的方法?当然还可以直接用 iftop 命令查看占用带宽的 IP。另外,查看每个网站在那个时间段的日志文件的大小也能大概看出是哪个网站被采集了。


A: Linux 显示每个用户会话的登入和登出信息

utmpdump /var/log/wtmp

参考:http://www.tulaoshi.com/n/20160331/2050641.html


Q: RDS 的 CPU 100%

A: 如果是突然持续占满(同时伴随 ECS 资源使用率下降,页面出现 502),很大可能是受攻击(或社交网站推送突发事件等),查看“慢查询”,添加相关索引;如果是 Discuz! 论坛,可尝试修复优化表 pre_common_session。

如果是数日缓步上升,或新项目上线,考虑 SQL 慢查询,思路:MySQL / SQL Server

MySQL:SHOW FULL PROCESSLIST

SQL Server:sp_who


Q: php 网站的服务器,内存在数天内缓慢上升

A: 大概是 php-fpm 占用过多,或进程数太多

更改 php 的配置(如 max_spare_servers),执行:service php-fpm reload


Q: 进程 cloudfs 占用内存过多

A: 参:https://xoyozo.net/Blog/Details/cloudfs-cache


Q: RDS 磁盘占用过大

A: 参:https://xoyozo.net/Blog/Details/how-to-use-rds


Q: ECS 受到 DDoS 攻击怎么办?

A: 参:https://xoyozo.net/Blog/Details/aliyun-ddos-without-bgp


Q: 如果 ECS 和 RDS 各项指标都没有异常,但网页打开慢或打不开502,TTFB 时间很长,是什么原因?(ECS 的 CPU 100%,RDS 的连接数上升,也可参考此条)

A: 数据库有坏表,尝试优化/修复表(慢 SQL 日志中锁等待时间较长的表?),或主备切换。show full processlist 时看到许多

DELETE FROM pre_common_session WHERE  sid='******'  OR lastactivity<******  OR (uid='0' AND ip1='*' AND ip2='*' AND ip3='*' AND ip4='*' AND lastactivity>******)


Q: Discuz! 创始人(站长)密码被改

A: 数据库找到 pre_ucenter_members 表,复制其它的已知登录密码的账号,复制其 password 和 salt 两个字段的值到创始人账号中,创始人账号即可用该密码登录了。


Q: 通过 iftop 观察到,Discuz! 网站从 RDS 数据库到 ECS 网站服务器私网流量非常大,远大于公网流量

A: 可能是缓存出问题了,尝试卸载重装 Redis 来解决。


Q: 宝塔面板中安装的 Redis 经常自动停止

A: 尝试卸载重装 Redis 来解决。


Q: 马甲客户端出现“您的网络有些问题”

A: 原因有许多,其中一个就是新建了一个数据表,然后 /source/class/table/ 下面丢失了对应的文件,具体可以找官方排查原因。


Q: 排查服务器安全需要检查哪些日志?

A: Web日志、登录日志(/var/log/secure)等。


Q: 带宽波形以几分钟为周期呈锯齿状波动是什么原因?

A: 该现象主要由防火墙流量管控机制与检测周期设置共同作用所致。防火墙基于预设的带宽阈值执行安全防护策略,当检测到流量峰值超过设定阈值时,将自动触发限流策略拒绝后续请求。待流量回落至安全阈值后,系统自动恢复服务访问权限。若防火墙的带宽采样检测周期设置过长(如以分钟为单位的检测间隔),将导致系统对实时流量变化的响应出现迟滞。这种周期性的检测机制会使带宽监控数据在阈值临界点附近呈现规律性的锯齿状波动特征。

优化建议:可通过调整防火墙的流量检测周期至更小时间粒度(如10-15秒),或采用动态流量整形策略,以实现更平滑的带宽控制效果。

补充说明:对于阿里云监控数据的调用,建议注意接口调用频率管控。高频调用云监控API接口将触发阿里云的API计费策略,可能产生额外的资源消耗成本。


其它案例

  1. 某台 ECS 上的多个网站出现 502,查询到 CPU / 内存 / 带宽 都比平时高,但都未满。用 iftop 看到连接的一个远程 Redis 占用内网带宽非常高。尝试重启远程 Redis 未果。尝试重启 ECS 上的 nginx 未果。尝试重启 ECS 未果。进入 ECS 的宝塔面板,重启 PHP 有效。

  2. DDos攻击看这篇,现象是入流量大,CC攻击看这篇,现象是出流量大。

xoyozo 9 年前
10,124