git 一个可以提高开发效率的命令:cherry-pick - 良许Linux - 博客园

mikel阅读(669)

来源: git 一个可以提高开发效率的命令:cherry-pick – 良许Linux – 博客园

各位码农朋友们一定有碰到过这样的情况:在develop分支上辛辛苦苦撸了一通代码后开发出功能模块A,B,C,这时老板过来说,年青人,我们现在先上线功能模块A,B。你一定心里一万只草泥马奔腾而过,但为了混口饭吃必须得按老板的意思办事啊。

怎么办?一个办法就是,重新建一个分支,然后再把功能模块C回退,留下功能模块A,B。这种做法不是不行,但是有更好的办法,那就是git所提供的cherry-pick功能。

cherry-pick类似于一个定制化的merge,它可以把其它分支上的commit一个个摘下来,合并到当前分支。

废话不多说,直接上实例。

比如我现在有个文件a.c,我在develop分支完成了三个功能模块:feature A,feature B,feature C。如下图:

现在,坑爹的老板只要feature A,feature B,我们现在用cherry-pick命令直接把feature A,feature B的提交合并到master分支里,如下操作:

可以看到,功能模块feature A,feature B已经被合并到master分支里。请注意,合并到master分支里的提交哈希值发生了改变,与原来的不同。

可以看出,cherry-pick命令使用方法很简单,即:

git cherry-pick commitID

刚刚是一个个提交cherry-pick到master分支,但如果有100个commit要合并到master分支呢?总不能这样一个个操作吧?git一样帮你想到了,它提供了一个区间操作方法。具体来讲是这样的:

git cherry-pick commit1..commit100

但是要注意,这是一个左开右闭的操作,也就是说,commit1不会被合并到master分支,而commit100则会。这样的话上面的需求可以如下操作来实现:

注意:上面讲到cherry-pick命令每拣选一个commit就会提交一次生成一个新的commit id。 如果我们想让每个commit 拣选后暂缓提交,等到所有commit都拣选完成后,自己手动commit,应该怎么办呢?答案是用-n 选项:

怎样,是不是很简单?学会了cherry-pick命令妈妈再也不用担心老板时不时的头脑发热了。快扫描下方二维码和良许一起学习更多git神操作!

更多精彩内容,请关注公众号良许Linux,公众内回复1024可免费获得5T技术资料,包括:Linux,C/C++,Python,树莓派,嵌入式,Java,人工智能,等等。公众号内回复进群,邀请您进高手如云技术交流群。

一篇文章搞定 Nginx 反向代理与负载均衡 - 哈喽沃德先生 - 博客园

mikel阅读(808)

来源: 一篇文章搞定 Nginx 反向代理与负载均衡 – 哈喽沃德先生 – 博客园

要想弄明白反向代理,首先要知道啥是正向代理,要搞懂正向代理只需要知道啥是代理即可。代理其实就是一个中介,在不同事物或同一事物内部起到居间联系作用的环节。比如买票黄牛,房屋中介等等。

互联网中代理更多指的是代理服务器,代理服务器位于客户端和服务器之间,它充当两者之间的中介。这种代理在生活中是比较常见的,比如我们常说的搭个梯子上网,用到的就是代理技术。

 

2|0正向代理

 

正向代理(forward proxy):是一个位于客户端和目标服务器之间的服务器(代理服务器),为了从目标服务器取得内容,客户端向代理服务器发送一个请求并指定目标,然后代理服务器向目标服务器转交请求并将获得的内容返回给客户端。

比如国内访问谷歌,直接访问是不行的,我们可以通过一个能够访问谷歌的正向代理服务器,请求发到代理服务器,由代理去谷歌获取数据并返回,这样就变相的实现了访问谷歌的需求。

一句话总结:正向代理,就是代理服务器代理了客户端,去和目标服务器进行交互。

 

 

正向代理的用途

  • 突破 IP 访问限制
  • 通过缓存加速访问资源
  • 隐藏客户端真实 IP
  • 客户端访问授权

 

3|0反向代理

 

反向代理(Reverse Proxy):与正向代理正好相反,反向代理中的代理服务器,代理的是服务器那端。代理服务器接收客户端请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给客户端,此时代理服务器对外表现为一个反向代理服务器的角色。

反向代理服务器位于用户与目标服务器之间,但是对于用户而言,反向代理服务器就相当于目标服务器,即用户直接访问反向代理服务器就可以获得目标服务器的资源。同时,用户不需要知道目标服务器的地址,也无须在用户端作任何设定。

一句话总结:反向代理,就是代理服务器代理了目标服务器,去和客户端进行交互。

 

 

反向代理的用途

  • 隐藏服务器真实 IP
  • 负载均衡
  • 通过缓存加速访问资源
  • 提供安全保障

 

4|0负载均衡

 

实际生产环境中,反向代理服务器代理的目标服务器可能不止一个。比如开发好的某个应用部署在一台 Tomcat 服务器上,而 Tomcat 的并发上限不优化情况下,默认只有两百左右,这时候为了解决高并发的问题,就只能选择更替服务器或者搭建多台服务器通过反向代理与负载均衡的技术解决并发问题。

 

 

负载均衡(Load Balance)是由多台服务器以对称的方式组成一个服务器集群,每台服务器都具有等价的地位,都可以单独对外提供服务而无须其他服务器的辅助。经过某种负载分管技术,将外部发送来的中央请求均匀分配到对称结构中的某一台服务器上。

 

5|0总结

 

正向代理,就是代理服务器代理了客户端,去和目标服务器进行交互。现实生活中的场景:黄牛买票。

反向代理,就是代理服务器代理了目标服务器,去和客户端进行交互。现实生活中的场景:房屋中介。

 

6|0Nginx 反向代理与负载均衡

 

 

前面我们提到搭建多台服务器并通过反向代理与负载均衡的技术可以解决并发问题,那么负载均衡的实现从哪来?为了避免重复造轮子,我们选择现成已有的成熟工具帮助我们完成这项工作。Nginx 就是一个不错的选择。

Nginx 是由 Igor Sysoev(伊戈尔 · 赛索耶夫)为俄罗斯访问量第二的 https://www.rambler.ru/ 站点开发的。Nginx 是一个高性能的 HTTP 和反向代理服务器,可以扛得住 5W 左右的并发。Ngnix 一方面可以做反向代理服务器,另外一方面还可以做静态资源服务器。本文主要学习如何使用 Nginx 实现反向代理与负载均衡。

官网:http://nginx.org/

 

6|1环境

 

  • 三台 CentOS 7.8.2003 机器
  • 192.168.10.101 安装 Nginx 1.18.0
  • 192.168.10.102 和 192.168.10.103 安装 Tomcat 9.0.38

 

6|2安装 Nginx

 

下载资源

 

下载 Nginx 并解压。

# 下载 nginx 压缩包 wget -P /usr/local/src http://nginx.org/download/nginx-1.18.0.tar.gz # 解压 tar -zxvf /usr/local/src/nginx-1.18.0.tar.gz -C /usr/local/src

 

安装依赖

 

Nginx 是基于 C 语言开发的,HTTP 模块使用了 pcre 来解析正则表达式,且可以使用 zlib 对 HTTP 包的内容进行 gzip 压缩,Nginx 不仅支持 HTTP 协议,还支持 HTTPS,HTTPS 需要 openssl 提供支持,所以安装 Nginx 之前必须先安装它所依赖的环境。

yum install -y gcc gcc-c++ pcre pcre-devel zlib zlib-devel openssl-devel

 

安装 Nginx

 

编译并安装。

# 切换至 nginx 的解压目录 cd /usr/local/src/nginx-1.18.0 # 创建 nginx 的安装目录 mkdir -p /usr/local/nginx # 指定 nginx 的安装路径 ./configure –prefix=/usr/local/nginx/ # 编译并安装 make && make install

 

常用命令

 

# 切换目录 cd /usr/local/nginx # 启动 sbin/nginx # 重启 sbin/nginx -s reload # 停止 sbin/nginx -s quit

 

访问

 

启动 Nginx 以后,浏览器访问:http://192.168.10.101:80/ 结果如下:

 

6|3安装 Tomcat

 

下载资源

 

下载 Tomcat 并解压。

# 下载 tomcat 压缩包 wget -P /usr/local/src https://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-9/v9.0.38/bin/apache-tomcat-9.0.38.tar.gz # 创建目录 mkdir -p /usr/local/tomcat # 解压 tar -zxvf /usr/local/src/apache-tomcat-9.0.38.tar.gz -C /usr/local/tomcat

 

修改页面

 

修改 Tomcat 自带 ROOT 项目中的 index.jsp 页面。

# 编辑 index.jsp vim /usr/local/tomcat/apache-tomcat-9.0.38/webapps/ROOT/index.jsp

在 body 标签中随便添加点内容用于区分不同的服务器。

<h1 style=“color:red”>192.169.10.102:8080</h1> <h1 style=“color:red”>192.169.10.103:8080</h1>

 

启动访问

 

/usr/local/tomcat/apache-tomcat-9.0.38/bin/startup.sh 启动 Tomcat。

启动 Tomcat 以后,浏览器访问:http://192.168.10.102:8080/ 和 http://192.168.10.103:8080/ 结果如下:

 

6|4配置 Nginx

 

vim /usr/local/nginx/conf/nginx.conf 编辑配置文件。

在 http 节点下,添加 upstream 节点。使用 upstream name{} 语法定义一组服务器。

然后在 server 节点的 80 端口下添加下图中的内容。默认情况下,Nginx 是按加权轮询的方式将请求分发到各个服务器,当权重 weight 不指定时,各服务器 weight 相同。关于 Nginx 启动用户的问题请根据自身实际环境进行配置。

 

6|5反向代理负载均衡

 

通过上面的流程,我们已经完成基于 Nginx 实现反向代理 Tomcat 服务器集群与负载均衡的需求。重启 Nginx 以后,此时再访问 Nginx 则会被路由到被代理的 Tomcat 服务器上,并且采用了轮询方式(默认)的负载均衡算法。客户端请求到 Nginx 的中央请求会每台一次的平均分配至 Tomcat 每个机器上。关于 Nginx 更多详细的配置及负载均衡算法我们后面再另开文章细说。

本文采用 知识共享「署名-非商业性使用-禁止演绎 4.0 国际」许可协议

大家可以通过 分类 查看更多关于 Nginx 的文章。

小工具開發 - 檔案實序排定器

mikel阅读(593)

最近遇到某些音樂播放器,由其是SONY的車用音響,都出現了這個問題,就是它根本不照我們放置檔案的順序或是其他排序方式(時間)去撥放。而這支程式就是用來重建他的檔案順序用的。

At some Sony music players or car audios,  it read mp3 files order is not follow filename sort or otherwise sort on the USB drive. This program will regenerate file order to the right!

假如我有一個USB隨身碟資料夾,裡面的檔案清單就如下面這張圖:

在 Windows 檔案總管下,看起來就是上面這樣子的,因為檔案總管會預設以檔案名稱來排序,正常得情況我們在 Windows 的播放軟體也會依照這個規則來執行。

然而,目前我在SONY音樂播放器上遇到這個播放順序的問題,它是照下面這種順序去撥放的:

比較前後兩張清單後注意到了嗎?

第二章的清單順序根本不知道它是依循啥麼的啊??事實上這就是我在 SONY音樂播放器上遇到的問題。

經過不斷的檢查後發現,原來第二張的檔案順序是在 FAT 表上的出現順序啊!!!!!

這啥鬼?

原來 SONY 音樂播放器是直接照 FAT 表讀出的檔案順序來播放音樂的,無怪乎我怎麼改檔案名稱,或是檔案時間都沒有用。

要是按照這種方式播放的話,如果要整理檔案,就得把 MP3 檔全部 移出 USB 隨身碟後,再依順序一個一個拷貝(搬移)回 USB 隨身碟。

真是天殺的,如果 USB 隨身碟有滿滿 16 GB音樂檔,那不就搬到天花地老了。這個會死人啊,老兄。SONY,我真服了你們了,東西又不便宜,程式卻寫得這麼爛,真不像 SONY 的產品啊。

索性,自己寫一支程式,專門來做檔案順序『重建』就可以保證在 FAT 上是依照自己訂的順序來跑了。

有興趣的就自己下載看看:

下載檔案/原始碼

這是用 dotNetFramwork 4.5 製作的,所以要執行的話,電腦至少要能支援 dotNetFramwork 4.5 ,或是到這裡下載。記得選擇您使用的語系再安裝。

程式載點(Google drive)

原始碼載點(Github)

操作方式:

點選左上方『開啟資料夾』,然後選擇你要重建的資料夾,請注意,它只支援一層檔案內容,並不會處理子資料夾內容,原因是這只是針對播放器的處理,而一般播放器比較不會支援二層以上資料夾:

 

在上圖,我選擇831的資料夾進行重建。

一開始,檔案不一定會照你所知道的順序出現,如果是這種狀況通常是 FAT 的檔案順序。

接下來你可以,依照需要選擇排序方式:

或是,手動選擇檔案,進行位置調整。

排好檔案順序後就可以按『處理』鈕進行重建了

接下來就是等待處理完成。

重建處理時會在該資料夾的磁碟機內產生一個暫存資料夾 TempF

如果發生狀況,檔案會保存在此處,您可以把狀況處理完後,在把這資料夾檔案複製回去就可以了。

重建完的檔案就可以在這些『特殊』的播放器上正常依照你指定的順序撥放了。

soulTable的小bug_qq_36307903的博客-CSDN博客

mikel阅读(677)

来源: soulTable的小bug_qq_36307903的博客-CSDN博客

layui框架有一个刷新当前页在这里插入图片描述功能,当你和soulTable一起用时就会出现一个问题,soulTable的写法是判断你是否是第一次进入,如果是重载表格的列,让你之前对表格列的处理可以记忆,但是你刷新当前页时,他就会判断你不是第一次进入,导致不对列进行处理,恢复表格最开始的情况,所以需要对代码做一下处理,先在定义一个新的变量用于判断是否是真正的第一次进入
在这里插入图片描述
在这里插入图片描述
这里改成(isFirst||aaa)随便一个变量名,并且在引入后

Angular $injector:unpr Unknown provider 问题原因汇总_大V的博客-CSDN博客

mikel阅读(602)

来源: Angular $injector:unpr Unknown provider 问题原因汇总_大V的博客-CSDN博客

Unknown provider: tProvider <- t 对于很多Angular 1.x 的使用者来说,是非常头疼的一件事情,因为使用者根本不知道原因在哪里。

本文总结了迄今为止所有导致这一个问题的可能原因,希望大家遇到此问题时,不要慌!跟着下面内容一步步排查:

问题描述:

Unknown provider 一般是由于无法解析注入的一个依赖所导致的。原因一般有如下这几种可能:

1. 依赖没有定义

  1. angular.module(‘myApp’, [])
  2. .controller(‘MyController’, [‘myService’, function (myService) {
  3. // Do something with myService
  4. }]);

上述代码,由于之前没有定义myService这个依赖,会报错 [$injector:unpr] Unknown provider。如果发现有没定义的依赖,首先要提前定义好这个依赖。

  1. angular.module(‘myApp’, [])
  2. .service(‘myService’, function () { /* … */ })
  3. .controller(‘MyController’, [‘myService’, function (myService) {
  4. // Do something with myService
  5. }]);

2. 重新使用了angular.module

  1. angular.module(‘myModule’, [])
  2. .service(‘myCoolService’, function () { /* … */ });
  3. angular.module(‘myModule’, [])
  4. // myModule has already been created! This is not what you want!
  5. .directive(‘myDirective’, [‘myCoolService’, function (myCoolService) {
  6. // This directive definition throws unknown provider, because myCoolService
  7. // has been destroyed.
  8. }]);

上述代码中,重复使用了angular.module(‘myModule’, []),会让angular重新定义myModule这个模块,导致报错。angular.module(‘myModule’, []) 这个语法一般是再次定义module,为了避免这个问题,在定义module之后直接使用angular.module(‘myModule’)或者使用一个变量代替之即可。

  1. angular.module(‘myModule’, []);
  2. .service(‘myCoolService’, function () { /* … */ });
  3. angular.module(‘myModule’)
  4. .directive(‘myDirective’, [‘myCoolService’, function (myCoolService) {
  5. // This directive definition does not throw unknown provider.
  6. }]);
  7. 或者
  8. var app = angular.module(‘myModule’, []);
  9. app.service(‘myCoolService’, function () { /* … */ });
  10. app.directive(‘myDirective’, [‘myCoolService’, function (myCoolService) {
  11. // This directive definition does not throw unknown provider.
  12. }]);

3. 把一个controller当依赖注入到另外一个controller中

  1. angular.module(‘myModule’, [])
  2. .controller(‘MyFirstController’, function() { /* … */ })
  3. .controller(‘MySecondController’, [‘MyFirstController’, function(MyFirstController) {
  4. // This controller throws an unknown provider error because
  5. // MyFirstController cannot be injected.
  6. }]);

其实如果要实例化controller,可以使用$controller服务(后续博客会更新)

4. 把$scope注入到不是controller或者directive的组件中

  1. angular.module(‘myModule’, [])
  2. .service(‘MyController’, [‘$scope’, function($scope) {
  3. // This controller throws an unknown provider error because
  4. // a scope object cannot be injected into a service.
  5. }]);

发生这个情况,也很好排查,只要牢记,只有controller和directive才能注入$scope作为依赖。

5. 使用angular压缩版导致报错

可以使用ngStrictDi

好了,希望本文能帮助到大家,遇此问题千万别慌了神!

Angular 之 ngStrictDi_大V的博客-CSDN博客

mikel阅读(575)

来源: Angular 之 ngStrictDi_大V的博客-CSDN博客

ngStrictDi主要是讲angular依赖注入的写法问题,如果写法不规范,可能会在加载压缩版Angular的时候导致Unknown provider的错误。

  1. var app = angular.module(‘ngAppStrictDemo’, []);
  2. 1. 不规范写法
  3. app.controller(‘BadController’, function($scope) {
  4. $scope.a = 1;
  5. $scope.b = 2;
  6. });
  7. 2.规范写法
  8. //使用了详细的注释,数组形式注入
  9. app.controller(‘GoodController1’, [‘$scope’, function($scope) {
  10. $scope.a = 1;
  11. $scope.b = 2;
  12. }]);
  13. //直接使用$inject服务,注入
  14. app.controller(‘GoodController2’, GoodController2);
  15. function GoodController2($scope) {
  16. $scope.name = ‘World’;
  17. }
  18. GoodController2.$inject = [‘$scope’];

在1.6.x之后,依赖注入的书写越来越严格,这是为了避免压缩代码后产生的unknown provider问题。尤其是小编使用了webpack打包Angular项目之后,这个问题尤为突出。

如果依赖过多,显示或者解读代码不时,推荐大家使用规范写法的第二种。

csredis - 在西天取经的路上…… - 博客园

mikel阅读(759)

RedisHelper

来源: csredis – 在西天取经的路上…… – 博客园

源码地址:https://github.com/2881099/csredis

1、增加了 CSRedisClient 现实集群与连接池管理,和 RedisHelper 静态类快速上手

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//普通模式
var csredis = new CSRedis.CSRedisClient("127.0.0.1:6379,password=123,defaultDatabase=13,poolsize=50,ssl=false,writeBuffer=10240,prefix=key前辍");
 
//集群模式
 
var csredis = new CSRedis.CSRedisClient(null,
  "127.0.0.1:6371,password=123,defaultDatabase=11,poolsize=10,ssl=false,writeBuffer=10240,prefix=key前辍",
  "127.0.0.1:6372,password=123,defaultDatabase=12,poolsize=11,ssl=false,writeBuffer=10240,prefix=key前辍",
  "127.0.0.1:6373,password=123,defaultDatabase=13,poolsize=12,ssl=false,writeBuffer=10240,prefix=key前辍",
  "127.0.0.1:6374,password=123,defaultDatabase=14,poolsize=13,ssl=false,writeBuffer=10240,prefix=key前辍");
//实现思路:根据key.GetHashCode() % 节点总数量,确定连向的节点
//也可以自定义规则(第一个参数设置)
 
//mvc分布式缓存注入 nuget Install-Package Caching.CSRedis
 
//初始化 RedisHelper
RedisHelper.Initialization(csredis,
  value => Newtonsoft.Json.JsonConvert.SerializeObject(value),
  deserialize: (data, type) => Newtonsoft.Json.JsonConvert.DeserializeObject(data, type));
//注册mvc分布式缓存
services.AddSingleton<IDistributedCache>(new Microsoft.Extensions.Caching.Redis.CSRedisCache(RedisHelper.Instance));
 
//提示:CSRedis.CSRedisClient 单例模式够用了,强烈建议使用 RedisHelper 静态类
RedisHelper.Set("test1""123123", 60);
RedisHelper.Get("test1");
//...函数名基本与 redis-cli 的命令相同

2、订阅与发布(分布式读写分离的场景)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//普通订阅
RedisHelper.Subscribe(
  ("chan1", msg => Console.WriteLine(msg.Body)),
  ("chan2", msg => Console.WriteLine(msg.Body)));
 
//模式订阅(通配符)
RedisHelper.PSubscribe(new[] { "test*""*test001""test*002" }, msg => {
  Console.WriteLine($"PSUB   {msg.MessageId}:{msg.Body}    {msg.Pattern}: chan:{msg.Channel}");
});
//模式订阅已经解决的难题:
//1、集群的节点匹配规则,导致通配符最大可能匹配全部节点,所以全部节点都要订阅
//2、本组 "test*", "*test001", "test*002" 订阅全部节点时,需要解决同一条消息不可执行多次
 
//发布,
RedisHelper.Publish("chan1""123123123");
//无论是集群或普通模式,RedisHelper.Publish 都能正常通信

3、缓存壳

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//不加缓存的时候,要从数据库查询
var t1 = Test.Select.WhereId(1).ToOne();
 
//一般的缓存代码,如不封装还挺繁琐的
var cacheValue = RedisHelper.Get("test1");
if (!string.IsNullOrEmpty(cacheValue)) {
    try {
        return JsonConvert.DeserializeObject(cacheValue);
    catch {
        //出错时删除key
        RedisHelper.Remove("test1");
        throw;
    }
}
var t1 = Test.Select.WhereId(1).ToOne();
RedisHelper.Set("test1", JsonConvert.SerializeObject(t1), 10); //缓存10秒
 
//使用缓存壳效果同上,以下示例使用 string 和 hash 缓存数据
var t1 = RedisHelper.CacheShell("test1", 10, () => Test.Select.WhereId(1).ToOne());
var t2 = RedisHelper.CacheShell("test""1", 10, () => Test.Select.WhereId(1).ToOne());
var t3 = RedisHelper.CacheShell("test"new [] { "1""2" }, 10, notCacheFields => new [] {
  ("1", Test.Select.WhereId(1).ToOne()),
  ("2", Test.Select.WhereId(2).ToOne())
});

.NET MVC 简单实现GZIP - 无记 - 博客园

mikel阅读(818)

来源: .NET MVC 简单实现GZIP – 无记 – 博客园

GZIP的好处大家都知道,不过一般系统来说页面不会太大,很多人也没注意过这玩意儿。前段时间做一个系统用了一个国人开发的JQuery富客户端框架DWZ(个人感觉这个框架还是蛮不错的),类似EXT的AJAX框架,框架的JS加上我自己的真不小。

 

 

打算用GZIP来做压缩,之前在IIS6上做过,这个项目用MVC做,发现在.NET MVC下有更简单好用的办法来解决:写一个ActionFilter来实现GZIP,优点大家用了就知道,呵呵

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class CompressAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var acceptEncoding = filterContext.HttpContext.Request.Headers["Accept-Encoding"];
        if (!string.IsNullOrEmpty(acceptEncoding))
        {
            acceptEncoding = acceptEncoding.ToLower();
            var response = filterContext.HttpContext.Response;
            if (acceptEncoding.Contains("gzip"))
            {
                response.AppendHeader("Content-encoding", "gzip");
                response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
            }
            else if (acceptEncoding.Contains("deflate"))
            {
                response.AppendHeader("Content-encoding", "deflate");
                response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
            }
        }
    }
}

用法:

1
2
3
4
5
6
7
[Longin]
[Compress]
public ActionResult Index()
{
    
        return View();
}

只要在打算用GZIP压缩的Action上写上[Compress]就OK了,是不是很简单,呵呵~

MVC页面加载速度优化小记 - g_cheng - 博客园

mikel阅读(779)

来源: MVC页面加载速度优化小记 – g_cheng – 博客园

 前言:

最近做一个地图展示页面,业务初期没什么问题,运行一阵后报错:

Error during serialization or deserialization using the JSON JavaScriptSerializer. 
The length of the string exceeds the value set on the maxJsonLength property.

Google 了一下,原来是由于业务数据的增多, ajax 后台返回时报错,参考网上的方法,在返回时设置一下 MaxJsonLength

            var jsonResult = Json(jsonString);
            jsonResult.MaxJsonLength = int.MaxValue;
            return jsonResult;

报错的问题是解决了,可还有一个问题就是页面加载时间过长。为了地图展示的效果,不能进行数据分页。

期间尝试了很多方法,记录如下:

 列表与地图同步:

页面的布局是左边显示数据列表,右边显示 GoogleMap 。刚开始拼列表的 html 和地图的初始化、加载是在同一个方法里面执行的,这样的效果就是列表和地图同时显示,由于地图的初始化、加载比较耗时,就想让列表先显示,地图初始化完后再显示。也就是列表显示和地图初始化同步执行,改后代码:

复制代码
                    if(pageData.length>0){
                        SetListHtml(1);
                        $("#loadGif").hide();
                        setTimeout(function () {SetMap();}, 0);
                    }
                    else{
                        $("#loadGif").hide();
                    }
复制代码

 

 存储过程和缓存:

列表与地图同步可以让用户的体验好一些,但是页面加载时间还是过长,于是就把后台取数据改成存储过程、把一些不是经常改变的数据做成缓存。在做缓存的过程中,由于不是经常改变的数据有时也会改变,因此缓存依赖要设成 SQLCacheDependency 。具体方法网上有很多。

复制代码
        public DataTable GetCacheGpsBoundary()
        {
            string cacheKey = "dtCustomerBoundary";
            DataTable dtCustomerBoundary = (DataTable)HttpRuntime.Cache.Get(cacheKey);
            if (dtCustomerBoundary == null)
            {
                log.Debug("dtCustomerBoundary从数据库中获取");
                dtCustomerBoundary = new DataTable();
                string sql = "";
                SqlCacheDependency sqlCacheDependency = null;
                string connectionString = ConfigurationManager.AppSettings[""];
                using (SqlConnection cn = new SqlConnection(connectionString))
                {
                    using (SqlCommand cmd = cn.CreateCommand())
                    {
                        cn.Open();
                        cmd.CommandText = sql;
                        sqlCacheDependency = new SqlCacheDependency(cmd);
                        //当有DML操作时,onChange事件会接收来自Sql Server通过sq_DispatcherProc存储过程发送给应用程序的消息。
                        using (SqlDataAdapter adapter = new SqlDataAdapter()) //查询数据
                        {
                            adapter.SelectCommand = cmd;
                            adapter.Fill(dtCustomerBoundary);
                        }
                    }
                }
                HttpContext.Current.Cache.Insert(cacheKey, dtCustomerBoundary, sqlCacheDependency);
            }
            else
            {
                log.Debug("dtCustomerBoundary从缓存中获取");
            }
            return dtCustomerBoundary;
        }
复制代码

 

 GZip压缩:

存储过程和缓存在本机测试的确加快了页面加载速度,可是发布到服务器后页面加载速度还是不理想。想分析具体原因在哪里,在网上找到一个工具:

HttpWatch Basic 9.2
Copyright: Copyright 2002 -2014 Simtec Limited
Version: 9.2.6

先看下图例颜色的意义:

我理解 Wait 就是服务器执行用时, Receive 就是传输用时。

没有加存储过程和缓存:

再来看下改成存储过程和加缓存后

最后是启用 GZip 后的图

通过 HttpWatch 我们可以看出压缩后数据的大小 853424 ,为压缩前 4309641 的 19.80% 、用时也由 8.623 缩短到 3.119 ,由于服务器当前资源、网络情况等每次时间会有所不同。

启用 GZip 压缩后,服务器和客户端 CPU 负担会加大,但对页面加载速度效果还是很明显的,刚开始通过 HttpWatch 看出是由于传输数据过大使页面加载时间过长时,就想到要用压缩,可在后台 ajax 方法中对返回的 Json 字符串 采用 GZipStream 压缩后,在前台 JavaScript 一直找不到好的方法去解压,尝试了很多加解压算法 Zlib、LZString 等等,加解压的时间都太长了,没什么效果。

看了 单程列车 博客上 .NET MVC 简单实现GZIP  后在后台添加一个 Filter 就可以实现服务端 gzip 压缩,客户端会自动解压,客户端 ajax 时可能要加一句

headers: { “Accept-Encoding” : “gzip” } ,其实我觉得 ajax 就是异步的去打开某一网页。

 总结:

分析、看清问题,找到问题真实原因,才有可能找到好的解决方法;

刚开始想在取数据这块优化,看 SQL 的执行计划看的一头雾水,今年要买些数据库优化方法的书补补;

JavaScript、HTTP、C#、MVC、SQL 等等掌握的是否系统、全面在综合运用时起着决定性的作用

解决一个问题的时候还是很高兴的。

 参考:

 http://stackoverflow.com/questions/5692836/maxjsonlength-exception-in-asp-net-mvc-during-javascriptserializer

http://www.cnblogs.com/zhaojingjing/archive/2011/01/20/1940357.html

http://www.cnblogs.com/willick/p/3331520.html

HTTP权威指南

windows配置mongodb开放局域网访问_qq_42783610的博客-CSDN博客

mikel阅读(1535)

来源: windows配置mongodb开放局域网访问_qq_42783610的博客-CSDN博客

重装电脑c盘后,mongodb局域网访问不了,于是去网上查找一下资料。

win10:

打开网络和internet设置

点开网络,选择专用网络

然后配置mongodb bin目录下的mongodb.cfg

然后安装mongoDB服务  (没有config局域网就无法访问)

mongod –config D:\Mongo\bin\mongod.cfg –logpath D:\Mongo\log\mongod.log
–logappend –dbpath D:\Mongo\data
–serviceName MongoDB  –install

回车执行完后执行下面命令启动mongodb服务

net start MongoDB

然后执行下面

mongo 局域网ip   例如mongo 10.11.124.78

出现下面情况代表成功

ps:

安装mongodb服务时:

若报错出现logpath 不对,就到日志文件夹下把mongod.log给删掉再执行

若报错TLS,则可以忽略

MongoDB启动服务时:

若报错误代码100,则到data目录下把mongod.lock和storage.bson文件删除

mongo 局域网ip 测试时:

若还不行.则关闭防火墙或增加防火墙入站规则开放mongodb 27017端口