首页
在线工具
搜索
1
使用Metrics指标度量工具监控Java应用程序性能(Gauges, Counters, Histograms, Meters和 Timers实例)
2
如何将Virtualbox和VMware虚拟机相互转换
3
Jumpserver的MFA配置
4
Kuboard与KubeSphere的区别:Kubernetes管理平台对比
5
Markdown正确使用姿势
杂谈与随笔
工具与效率
源码阅读
技术管理
运维
数据库
前端开发
后端开发
Search
标签搜索
Angular
Docker
Phabricator
SpringBoot
Java
Chrome
SpringSecurity
SpringCloud
DDD
Git
Mac
K8S
Kubernetes
ESLint
SSH
高并发
Eclipse
Javascript
Vim
Centos
Jonathan
累计撰写
86
篇文章
累计收到
0
条评论
首页
栏目
杂谈与随笔
工具与效率
源码阅读
技术管理
运维
数据库
前端开发
后端开发
页面
搜索到
86
篇与
的结果
2016-07-05
AngularJS 中的 $apply 和 $digest
AngularJS 中的 $apply 和 $digest 避免在控制器中使用 $watch 永远不要在控制器中使用 $watch,因为它会使控制器难以测试。Angular 提供了 $watchCollection 方法来对对象属性或数组元素设置浅监控,只要属性发生变化就会触发监听器回调。 $watchCollection 示例 $watchCollection() 函数也返回一个注销函数。调用这个注销函数时,也会取消集合上的监听。 手动调用 $apply() 如果你使用了 JavaScript 中的 setTimeout() 来更新一个 scope model,那么 AngularJS 就没有办法知道你更改了什么。这种情况下,调用 $apply() 是你的责任,通过调用它来触发一轮 $digest 循环。 示例代码 HTML <body ng-app="myApp"> <div ng-controller="MessageController"> Delayed Message: {{message}} </div> </body> JavaScript (不使用 $apply()) angular.module('myApp', []).controller('MessageController', function($scope) { $scope.getMessage = function() { setTimeout(function() { $scope.message = 'Fetched after 3 seconds'; console.log('message:' + $scope.message); }, 2000); } $scope.getMessage(); }); 这段代码会在控制台显示更新后的 model,但视图不会更新。 使用 $apply() 修改后的代码 angular.module('myApp', []).controller('MessageController', function($scope) { $scope.getMessage = function() { setTimeout(function() { $scope.$apply(function() { // wrapped this within $apply $scope.message = 'Fetched after 3 seconds'; console.log('message:' + $scope.message); }); }, 2000); } $scope.getMessage(); }); 现在视图会在两秒钟后更新。 注意: 应该使用 $timeout service 而不是 setTimeout(),因为前者会自动调用 $apply()。 $digest 循环 当 $digest 循环运行时,watchers 会被执行来检查 scope 中的 models 是否发生了变化。如果发生了变化,相应的 listener 函数就会被执行。为了处理 listener 函数可能修改 scope model 的情况,AngularJS 实现了脏检查机制(Dirty Checking)。这意味着 $digest 循环会持续运行直到 models 不再发生变化,或者循环次数达到10次。 结语 总是将要执行的代码和函数传递给 $apply 去执行。 使用 $apply 时,应该像下面这样: $scope.$apply(function() { $scope.variable1 = 'some value'; executeSomeAction(); }); 而不是这样: $scope.variable1 = 'some value'; executeSomeAction(); $scope.$apply(); 这两种方式虽然都能工作,但是第一个方法更安全,因为它能确保异常被正确捕获并处理。
2016年07月05日
2016-06-21
Angular-UI-Router 学习笔记
Angular-UI-Router 学习笔记 路由 (Route) 为什么用 Route AJAX 请求不会留下 History 记录 用户无法直接通过 URL 进入应用中的指定页面(无法保存书签、链接分享给朋友) AJAX 对 SEO 是个灾难 AngularJS 路由配置示例 var bookStoreApp = angular.module('bookStoreApp', [ 'ngRoute', 'ngAnimate', 'bookStoreCtrls', 'bookStoreFilters', 'bookStoreServices', 'bookStoreDirectives' ]); bookStoreApp.config( function($routeProvider) { $routeProvider .when('/hello', { templateUrl: 'tpls/hello.html', controller: 'HelloCtrl' }) .when('/list/:bookId', { templateUrl: 'tpls/bookList.html', controller: 'BookListCtrl' }) .otherwise({ redirectTo: '/hello' }); } ); 嵌套 View (Nested Routing for AngularJS) AngularUI-Router (AngularUI) <div ui-view></div> 前端路由的基本原理 哈希 (#) HTML5 中新的 history API 路由的核心 是给应用定义 "状态" 使用路由机制会影响应用的整体编码方式 (需预先定义好状态) 考虑兼容性问题与 "优雅降级" Angular-UI-Router ui-sref 指令 <a ui-sref="home">Home</a> <a ui-sref="about">About</a> <a ui-sref="contacts.list">Contacts</a> $state.includes 返回 true / false <li ng-class="{active: $state.includes('contacts')}"> <a ui-serif="contacts.list">Contacts</a> </li> ui-sref-active <li ui-sref-active="active"> <a ui-sref="about">About</a> </li> 包含模块 angular.module('uiRouter', ['ui.router']); 方便获得当前状态的方法 (绑到根作用域) app.run(['$rootScope', '$state', '$stateParams', function($rootScope, $state, $stateParams) { $rootScope.$state = $state; $rootScope.$stateParams = $stateParams; } ]); 路由重定向 ($urlRouterProvider) app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) { $urlRouterProvider .when('/c?id', '/contacts/:id') .when('/user/:id', '/contacts/:id') .otherwise('/'); } ]); 状态配置 $stateProvider. state('about', { url: '/about', template: '<h1>Welcome to UI-Router Demo</h1>', // 使用 templateProvider 处理异步加载 templateProvider: ['$timeout', function($timeout) { return $timeout(function() { return '<p class="lead">UI-Router Resource</p>' + '<p>The second line</p>'; }, 100); } ], templateUrl: 'about.html', controller: 'UIRouterCtrl', controller: ['$scope', '$state', 'contacts', 'utils', function ($scope, $state, contacts, utils) { $scope.contacts = contacts; $scope.goToRandom = function () { var randId = utils.newRandomKey($scope.contacts, 'id', $state.params.contactId); $state.go('contacts.details', { contactId: randId }); } } ] }); 嵌套路由 (Nested Router) 父级路由 (Parent Router) $stateProvider. state('contacts', { abstract: true, url: '/contacts', templateUrl: 'contacts.html', // 处理异步数据调用 resolve: { contacts: ['contacts', function(contacts) { return contacts.all(); } ] }, controller: ['$scope', '$state', 'contacts', 'utils', function ($scope, $state, contacts, utils) { $scope.contacts = contacts; $scope.goToRandom = function () { var randId = utils.newRandomKey($scope.contacts, 'id', $state.params.contactId); $state.go('contacts.details', { contactId: randId }); } } ] }); 子级路由 (Children Router) $stateProvider .state('contacts.list', { url: '', templateUrl: 'contacts.list.html' }) .state('contacts.detail', { url: '/{contactId:[0-9]{1,4}}', views: { // 默认 view '': { templateUrl: 'contacts.detail.html', controller: ['$scope', '$stateParams', 'utils', function ($scope, $stateParams, utils) { $scope.contact = utils.findById($scope.contacts, $stateParams.contactId); } ] }, // 其他 view 'hint@': { template: 'This is contacts.detail populating the "hint" ui-view' }, 'menuTip': { templateProvider: ['$stateParams', function($stateParams) { return '<hr><small class="muted">Contact ID: ' + $stateParams.contactId + '</small>'; } ] } } }); HTML 代码 <h2>All Contacts</h2> <ul> <li ng-repeat="contact in contacts"> <a ui-sref="contacts.detail({contactId:contact.id})">{{contact.name}}</a> </li> </ul>
2016年06月21日
2016-06-15
Windows下Phabricator Arcanist的安装与使用
Windows下Phabricator Arcanist的安装与使用 Arcanist是Phabricator提交代码评审的客户端工具,虽然可以直接在Differential界面手动创建Diff和Revision,但使用Arcanist会更加方便,特别是对于习惯命令行操作的开发者。 注意事项 如果遇到错误 ERR-CONDUIT-CORE: Invalid parameter information was passed to method 'differential.creatediff',请确保所有文件名均为英文。 安装步骤 1. 安装PHP 需要安装PHP 5.2或以上版本,推荐下载PHP 5.4 VC9 x86 Non Thread Safe版。具体步骤如下: 解压到指定目录:例如解压到 C:\PHP。 加入环境变量:将PHP安装目录(如 C:\PHP)添加到系统的 PATH 环境变量中。 配置php.ini: 复制 php.ini-development 文件为 php.ini。 在 php.ini 中取消以下几行的注释: extension_dir = "ext" extension=php_curl.dll extension=php_mbstring.dll 注册PHP文件类型(可选): 将 .php 扩展名添加到 PATHEXT 环境变量中。 关联 .php 文件类型: assoc .php=phpfile ftype phpfile="C:\PHP\php.exe" -f "%1" -- %~2 需要以管理员权限运行上述命令。 2. 安装SVN客户端 需要安装支持命令行的SVN客户端(不是TortoiseSVN)。可以从Subversion官方网站选择合适的版本,推荐安装CollabNet的Subversion 1.8.0,下载地址(需要注册):CollabNet Subversion。 测试安装是否成功 打开命令提示符并输入以下命令进行测试: C:> svn Type 'svn help' for usage.
2016年06月15日
2016-05-18
大话程序猿眼里的高并发
大话程序猿眼里的高并发 简单理解高并发 高并发指的是在同一时间点,有很多用户同时访问某个URL地址。例如淘宝的双11、双12活动,贴吧的爆吧事件(恶意的高并发请求,即DDOS攻击)。简单来说,就像玩游戏中被ADC暴击了一样,伤害巨大。 高并发带来的后果 服务端:站点服务器/DB服务器资源被占满崩溃,数据存储和更新结果与理想设计不一致(如重复的数据记录,多次添加用户积分等)。 用户角度:页面卡顿,用户体验差,可能导致用户流失。 我的经历:在开发公司产品网站时,经常会有类似抽奖、签到、积分竞拍等功能需求。如果未考虑高并发下的数据处理,可能会导致数据异常,影响用户体验。 实例分析 并发下的数据处理 通过表设计(如记录表添加唯一约束)、使用事务防止并发下的数据错乱问题,以及通过服务端锁进程防止并发下的数据错乱问题。 例子1:签到功能 需求:一天一个用户只能签到一次,签到成功后用户获取一个积分。 已知表:用户表,包含积分字段。 设计: 添加一张签到记录表,并将用户唯一标识字段(ID, Token)和签到日期字段设为唯一约束或索引。 在代码逻辑中,先执行签到数据的添加,再进行积分的添加。 所有操作写在一个SQL事务里,确保数据一致性。 例子2:抽奖功能 需求:抽奖一次消耗一个积分,抽奖中奖后编辑剩余奖品总数。当剩余奖品总数为0或用户积分为0时无法进行抽奖。 已知表:用户表(包含积分字段),奖品表(包含奖品剩余数量字段)。 设计: 在事务中,通过WITH (UPDLOCK)锁住商品表,或更新表的奖品剩余数量和最后编辑时间字段来锁定数据行。 进行用户积分的消耗,完成后提交事务,失败则回滚。 例子3:缓存数据到Cache 需求:当缓存不存在时从数据库获取并保存到缓存中;每天10点必须更新一次,其他时间点缓存两小时更新一次。 问题:10点时有很多并发请求同时过来,导致大量SQL查询操作,增加服务器压力。 解决:C#通过lock机制,在从数据库读取到缓存的代码前加上锁,确保只有一个请求是从数据库获取数据,其他都从缓存中获取。 访问量大的数据统计接口 需求:用户行为数据统计接口,记录商品展示次数等。 问题:大量用户同时在线访问页面会导致大量请求,给服务器带来巨大压力。 解决:通过Node.js写一个数据处理接口,把统计数据先存到Redis的list里,然后再同步到MySQL数据库中。这样可以减少数据库压力,加快响应速度。 高并发下的服务器压力均衡 服务器代理Nginx:做服务器的负载均衡,分散压力到多台服务器。 集群部署:MySQL数据库、Redis服务器或MongoDB服务器,常用查询数据保存到NoSQL DB中,减少数据库压力。 数据缓存:使用Cache。 编程语言选择:使用具有高并发能力的语言(如Node.js)开发Web接口。 服务器部署:图片服务器分离,静态文件走CDN。 数据库优化:优化查询条件和索引。 消息队列:将数据添加到信息队列(如Redis list)中,再写工具入库。 脚本控制请求:防止用户重复点击导致多余的AJAX请求。 并发测试神器推荐 Apache JMeter Microsoft Web Application Stress Tool Visual Studio 性能负载 文章来源
2016年05月18日
2016-04-13
ssh 速度慢的问题
解决 SSH 速度慢的问题 SSH 连接速度慢是一个常见问题,主要原因通常是 sshd 服务器在尝试进行 DNS 反向查询,将客户端 IP 解析为主机名,这个过程如果 DNS 不可用或没有相关记录,会导致长时间等待。以下是几种解决方法: 方法一:基本配置修改 在服务器的 /etc/hosts 文件中添加客户端 IP 和主机名 在服务器的 /etc/ssh/sshd_config 文件中添加或修改 UseDNS=no 重启 SSH 服务 sudo systemctl restart sshd # 或 sudo service sshd restart # 或 sudo /etc/init.d/sshd restart 方法二:完整解决方案 如果方法一不能完全解决问题,可以尝试以下更全面的配置: 在服务器的 /etc/hosts 文件中添加: 127.0.0.1 localhost # 添加客户端 IP 和主机名 192.168.1.100 client-hostname 修改服务器的 /etc/ssh/sshd_config 文件: UseDNS no GSSAPIAuthentication no 编辑服务器的 /etc/resolv.conf 文件: # 方法1:使用本地 DNS nameserver 127.0.0.1 # 方法2:注释掉所有行 # nameserver 8.8.8.8 修改服务器的 /etc/nsswitch.conf 文件中的 hosts 行: hosts: files 修改 /etc/sysconfig/network 文件(如果存在): HOSTNAME=localhost 重启服务器或重启 SSH 服务: sudo systemctl restart sshd # 或完全重启服务器 sudo reboot 方法三:客户端配置优化 除了服务器端配置外,也可以在客户端的 SSH 配置中进行优化: 编辑 ~/.ssh/config 文件(若不存在则创建): Host * GSSAPIAuthentication no Compression yes ControlMaster auto ControlPath ~/.ssh/control:%h:%p:%r ControlPersist yes # 针对特定服务器的优化 Host server-name Hostname server-ip-address User username PreferredAuthentications publickey IdentityFile ~/.ssh/id_rsa 额外排查步骤 如果以上方法仍不能解决 SSH 连接慢的问题,可以尝试以下步骤: 使用 -v 选项启用详细输出来诊断问题: ssh -v user@server 检查服务器的防火墙设置 检查 ~/.ssh/known_hosts 文件是否过大: wc -l ~/.ssh/known_hosts 如果文件过大,可以备份并创建新文件 检查连接延迟: time ssh user@server exit 如果问题与 GSSAPI 认证相关,也可以在客户端禁用: ssh -o GSSAPIAuthentication=no user@server 以上配置和修改应该能解决大多数 SSH 连接缓慢的问题。请根据自己的具体环境选择合适的方法。
2016年04月13日
1
...
16
17
18