May 21, 2016
理解OAuth 2.0
"\u003ch2 id=\"客户端的授权模式\"\u003e客户端的授权模式\u003c/h2\u003e\n\u003cp\u003e客户端必须得到用户的授权(authorization grant),才能获得令牌(access token)。OAuth 2.0定义了四种授权方式。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e授权码模式(authorization code)最完整、流程最严密的授权模式,如GitHub、微信等网站第三方登录方式\u003c/li\u003e\n\u003cli\u003e简化模式(implicit)\u003c/li\u003e\n\u003cli\u003e密码模式(resource owner password credentials)如目前手机APP中使用此模式\u003c/li\u003e\n\u003cli\u003e客户端模式(client credentials)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html\"\u003ehttp://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html\u003c/a\u003e\u003c/p\u003e"
May 16, 2016
Git 工具 – submodule 子模块
"\u003cp\u003e\u003ca href=\"https://git-scm.com/book/zh/v2/Git-%E5%B7%A5%E5%85%B7-%E5%AD%90%E6%A8%A1%E5%9D%97\"\u003ehttps://git-scm.com/book/zh/v2/Git 工具-子模块\u003c/a\u003e\u003c/p\u003e"
May 11, 2016
Vue.js学习资料
"\u003cp\u003e在学习vue前,建立先了解一下 webpack \u003ca href=\"https://fakefish.github.io/react-webpack-cookbook/index.html\"\u003ehttps://fakefish.github.io/react-webpack-cookbook/index.html\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e官方网站(中文版): \u003ca href=\"http://cn.vuejs.org/\"\u003ehttp://cn.vuejs.org/\u003c/a\u003e\n构建大型应用使用组件 Vue-router: \u003ca href=\"https://github.com/vuejs/vue-router\"\u003ehttps://github.com/vuejs/vue-router\u003c/a\u003e\n网络通讯插件Vue-resource: \u003ca href=\"https://github.com/vuejs/vue-resource\"\u003ehttps://github.com/vuejs/vue-resource\u003c/a\u003e\n单元测试karma: \u003ca href=\"http://karma-runner.github.io/0.12/index.html\"\u003ehttp://karma-runner.github.io/0.12/index.html\u003c/a\u003e \u003ca href=\"https://cn.vuejs.org/\"\u003ehttps://cn.vuejs.org/\u003c/a\u003e \u003ca href=\"https://cn.vuejs.org/v2/api/\"\u003ehttps://cn.vuejs.org/v2/api/\u003c/a\u003e \u003ca href=\"https://router.vuejs.org/zh-cn/\"\u003ehttps://router.vuejs.org/zh-cn/\u003c/a\u003e \u003ca href=\"https://vuex.vuejs.org\"\u003ehttps://vuex.vuejs.org\u003c/a\u003e \u003ca href=\"https://vue-loader.vuejs.org/zh-cn/\"\u003ehttps://vue-loader.vuejs.org/zh-cn/\u003c/a\u003e \u003ca href=\"https://ssr.vuejs.org\"\u003ehttps://ssr.vuejs.org …\u003c/a\u003e\u003c/p\u003e"
May 10, 2016
mysql 数据表读锁机制详解
"\u003cp\u003e为了给高并发情况下的mysql进行更好的优化,有必要了解一下mysql查询更新时的锁表机制。\n**一、概述\n** MySQL有三种锁的级别:页级、表级、行级。\nMyISAM和MEMORY存储引擎采用的是表级锁(table-level locking);BDB存储引擎采用的是页面锁(page-level locking),但也支持表级锁;InnoDB存储引擎既支持行级锁(row-level locking),也支持表级锁,但默认情况下是采用行级锁。\nMySQL这3种锁的特性可大致归纳如下:\n表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。\n行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。\n页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。\u003c/p\u003e\n\u003cp\u003e从上述特点可见,很难笼统地说哪种锁更好,只能就具体应用的特点来说哪种锁更合适!仅从锁的角度来说:表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web应用;而行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并 …\u003c/p\u003e"
May 9, 2016
修改gitlab的项目部署url地址
"\u003cp\u003e\u0026lt;刚在centos7上部署了最新版本的gitlab 8.7.3,发现在创建的git项目地址为http://localhost/username/www.git ,外网无法访问,这时我们只需要修改一个配置文件即可。我安装的时候全部使用的默认配置,路径为 /var/opt/gitlab/gitlab-rails/etc/,配置文件为 gitlab.yml ,文件顶部配置如下:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ehost: localhost\nport: 80\nhttps: false\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e修改host值为你想使用的外网域名或服务器IP地址即可,保存退出。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003egitlab-ctl restart\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e注意这里的命令是restart不是 reconfigure(根据配置文件/etc/gitlab/gitlab.rb 重新生成配置) ,否则还会恢复原来的配置。\u003c/p\u003e\n\u003cp\u003e用ps -ef | grep nginx命令看了下,发现运行的nginx的路径是/opt/gitlab/embedded/sbin/nginx,而配置文件路径是/var/opt/gitlab/nginx,怪不得我打开/etc/nginx/nginx.conf没看到gitlab …\u003c/p\u003e"
April 18, 2016
Mac上使用Brew 进行PHP多版本管理
"\u003cp\u003e\u003ca href=\"http://yansu.org/2014/09/26/use-old-version-of-brew-php.html\"\u003ehttp://yansu.org/2014/09/26/use-old-version-of-brew-php.html\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"section\"\u003e版本切换方式\u003c/h2\u003e\n\u003cp\u003e通过brew安装的php可以通过 \u003ccode\u003ebrew link\u003c/code\u003e 和 \u003ccode\u003ebrew unlink\u003c/code\u003e 来切换不同版本。\u003c/p\u003e\n\u003cp\u003e例如\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ebrew list\nbrew unlink php56\nbrew link php55\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e大版本可以用 \u003ccode\u003ebrew list\u003c/code\u003e 来查,如果是小版本的话只能去 \u003ccode\u003e/usr/local/Cellar/php55\u003c/code\u003e 看了。这个时候使用 \u003ccode\u003ephp-version\u003c/code\u003e 可以更方便一点。\u003c/p\u003e\n\u003cp\u003e我测试的此方法不行,只能使用php-verson 进行切换。\u003c/p\u003e\n\u003ch2 id=\"php-version\"\u003e安装 \u003ccode\u003ephp-version\u003c/code\u003e\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/wilmoore/php-version\"\u003ephp-version\u003c/a\u003e 是一个帮助管理从brew安装的php版本切换的工具。\u003c/p\u003e\n\u003cp\u003e安装非常简单\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ebrew install php-version\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e然后执行\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e\u0026lt;span class=\u0026#34;nb\u0026#34;\u0026gt;source\u0026lt;/span\u0026gt; \u0026lt;span class=\u0026#34;k\u0026#34;\u0026gt;$(\u0026lt;/span\u0026gt;brew --prefix …\u003c/code\u003e\u003c/pre\u003e"
April 18, 2016
HomeBrew中国镜像源
"\u003cp\u003eMac 终端跑入即可\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ecd /usr/local/\ngit remote set-url origin http://mirrors.ustc.edu.cn/homebrew.git\n#或者这个:\ngit remote set-url origin git://mirrors.tuna.tsinghua.edu.cn/homebrew.git\nbrew update\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e如果还是感觉慢,看看这个: \u003ca href=\"https://mirrors.tuna.tsinghua.edu.cn/help/homebrew/\"\u003ehttps://mirrors.tuna.tsinghua.edu.cn/help/homebrew/\u003c/a\u003e\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ecd ~/tmp\ngit clone git://mirrors.tuna.tsinghua.edu.cn/homebrew.git\nrm -rf /usr/local/.git\nrm -rf /usr/local/Library\ncp -R homebrew/.git /usr/local/\ncp -R homebrew/Library /usr/local/\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e然后重试update。\u003c/p\u003e\n\u003ch3 id=\"使用homebrew-science或者homebrew-python\"\u003e使用homebrew-science或者homebrew-python\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ecd …\u003c/code\u003e\u003c/pre\u003e"
April 13, 2016
JWT介绍
"\u003cp\u003e\u003cstrong\u003eJWT是什么\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eJWT全称是JSON Web Tokens,是RFC 7519标准,用于安全校验两方可信性的安全措施。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eJWT解决了哪些问题?\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eJWT本身设计是用于解决Session机制不能够很好的在SPA/API类型(restful)应用中处理身份认证问题。通常API的调用是无状态(stateless)的,使用Session等形式会有上下文要求。如当用户登录完成后,可以通过下发JWT的形式进行无状态的API调用。在此之前通常是使用的方式包括不限于如Basic Auth、Oauth2或Token形式进行。\u003c/p\u003e\n\u003cp\u003eJWT相比是额外添加了签名校验方式,本质上来说对抗如暴力碰撞等形式有一些作用。但是由于本身长度的限制,存储的信息量有限。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eJWT处理方式\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eJWT内容主要分为三段,分别对应头部信息,存储数据和签名信息三部分,中间使用『.』符号连接,三段信息均进行Base64编码。\u003c/p\u003e\n\u003cp\u003e具体实现方式可参考如下伪代码实现:\u003c/p\u003e\n\u003cp\u003eencodeBase64(header) + ‘.’ + encodeBase64(payload) + ‘.’ + Sign(key + encodeBase64(header) + …\u003c/p\u003e"
April 3, 2016
[翻译]理解 GO 语言的内存使用
"\u003cp\u003e许多人在刚开始接触 Go 语言时,经常会有的疑惑就是“为什么一个 Hello world 会占用如此之多的内存?”。 \u003ca href=\"https://deferpanic.com/blog/understanding-golang-memory-usage/\" title=\"Understanding Go Lang Memory Usage\"\u003eUnderstanding Go Lang Memory Usage\u003c/a\u003e 很好的解释了这个问题。不过“简介”就是“简介”,更加深入的内容恐怕要读者自己去探索了。另外,文章写到最后,作者飘了,估计引起了一些公愤,于是又自己给自己补刀,左一刀,右一刀……\u003c/p\u003e\n\u003cp\u003e————翻译分隔线————\u003c/p\u003e\n\u003ch1 id=\"理解-go-语言的内存使用\"\u003e理解 Go 语言的内存使用\u003c/h1\u003e\n\u003cp\u003e\u003cem\u003e2014年12月22日,星期一\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e温馨提示\u003c/strong\u003e:这仅是关于 Go 语言内存的简介,俗话说不入虎穴、焉得虎子,读者可以进行更加深入的探索。\u003c/p\u003e\n\u003cp\u003e大多数 Go 开发者都会尝试像这样简单的 hello world 程序:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003epackage main\n\nimport (\n\u0026#34;fmt\u0026#34;\n\u0026#34;time\u0026#34;\n)\n\nfunc main() {\nfmt.Println(\u0026#34;hi\u0026#34;)\n\ntime.Sleep(30 * time.Second)\n}\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e然后他们就完全崩溃了。\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"http://blog.haohtml.com/wp-content/uploads/2016/04/high_mem-300x38.png\"\u003e\u003cimg src=\"http://blog.haohtml.com/wp-content/uploads/2016/04/high_mem-300x38.png\" alt=\"high_mem-300x38\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e这个笔记本也只有 16 G 内存!\u003c/p\u003e\n\u003ch2 id=\"虚拟内存-vs-常驻内存\"\u003e虚拟内存 vs 常驻内存\u003c/h2\u003e\n\u003cp\u003eGo 管理内存的方式可能与你以 …\u003c/p\u003e"
March 25, 2016
Profiling Go Programs
"\u003cp\u003e转自: \u003ca href=\"http://blog.golang.org/profiling-go-programs\"\u003ehttp://blog.golang.org/profiling-go-programs\u003c/a\u003e (需翻墙)\u003c/p\u003e\n\u003ch1 id=\"the-go-blog\"\u003e\u003ca href=\"http://blog.golang.org/\"\u003eThe Go Blog\u003c/a\u003e\u003c/h1\u003e\n\u003ch3 class=\"title\" id=\"profiling-go-programs\"\u003e\u003ca href=\"http://blog.golang.org/profiling-go-programs\"\u003eProfiling Go Programs\u003c/a\u003e\u003c/h3\u003e\n\u003cp\u003e24 June 2011\u003c/p\u003e\n\u003cp\u003eAt Scala Days 2011, Robert Hundt presented a paper titled \u003ca href=\"http://research.google.com/pubs/pub37122.html\"\u003eLoop Recognition in C++/Java/Go/Scala.\u003c/a\u003e The paper implemented a specific loop finding algorithm, such as you might use in a flow analysis pass of a compiler, in C++, Go, Java, Scala, and then used those programs to draw conclusions about typical performance concerns in these languages. The Go program presented in that paper runs quite …\u003c/p\u003e"
March 24, 2016
golang中并发实例
"\u003cpre tabindex=\"0\"\u003e\u003ccode\u003epackage main\n\nimport (\n\t\u0026#34;fmt\u0026#34;\n\t//\u0026#34;runtime\u0026#34;\n\t\u0026#34;os\u0026#34;\n\t\u0026#34;runtime/pprof\u0026#34; // 引用pprof package\n\t\u0026#34;time\u0026#34;\n)\n\nfunc main() {\n\tf, _ := os.Create(\u0026#34;profile_file\u0026#34;)\n\tpprof.StartCPUProfile(f) // 开始cpu profile,结果写到文件f中\n\tdefer pprof.StopCPUProfile() // 结束profile\n\n\tstartTime := time.Now().Second()\n\t//runtime.GOMAXPROCS(runtime.NumCPU())\n\n\t// 注意这里的缓存大小\n\tch := make(chan int, 100)\n\tquit := make(chan bool)\n\n\t// 注意这里把读取chan操作放在了写入chan之前了(为了安全建议对chan的goroutines读取放在前面,写入放在后 …\u003c/code\u003e\u003c/pre\u003e"
March 24, 2016
在Golang中使用json
"\u003cblockquote\u003e\n\u003cp\u003e由于要开发一个小型的web应用,而web应用大部分都会使用json作为数据传输的格式,所以有了这篇文章。\u003c/p\u003e\u003c/blockquote\u003e\n\u003ch4 id=\"包引用\"\u003e包引用\u003c/h4\u003e\n\u003cp\u003eimport (\n\u0026ldquo;encoding/json\u0026rdquo;\n\u0026ldquo;github.com/bitly/go-simplejson\u0026rdquo; // for json get\n)\u003c/p\u003e\n\u003ch4 id=\"用于存放数据的结构体\"\u003e用于存放数据的结构体\u003c/h4\u003e\n\u003cp\u003etype MyData struct {\nName string \u003ccode\u003ejson:\u0026quot;item\u0026quot;\u003c/code\u003e\nOther float32 \u003ccode\u003ejson:\u0026quot;amount\u0026quot;\u003c/code\u003e\n}\u003c/p\u003e\n\u003cp\u003e这里需要注意的就是后面单引号中的内容。\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003ejson:\u0026quot;item\u0026quot;\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e这个的作用,就是Name字段在从结构体实例编码到JSON数据格式的时候,使用item作为名字。算是一种重命名的方式吧。\u003c/p\u003e\n\u003ch4 id=\"编码json\"\u003e编码JSON\u003c/h4\u003e\n\u003cp\u003evar detail MyData\u003c/p\u003e\n\u003cp\u003edetail.Name = \u0026ldquo;1\u0026rdquo;\ndetail.Other = \u0026ldquo;2\u0026rdquo;\u003c/p\u003e\n\u003cp\u003ebody, err := json.Marshal(detail)\nif err != nil …\u003c/p\u003e"
March 24, 2016
golang的json操作
"\u003cpre tabindex=\"0\"\u003e\u003ccode\u003epackage main\n\nimport (\n \u0026#34;encoding/json\u0026#34;\n \u0026#34;fmt\u0026#34;\n \u0026#34;os\u0026#34;\n)\n\ntype ConfigStruct struct {\n Host string `json:\u0026#34;host\u0026#34;`\n Port int `json:\u0026#34;port\u0026#34;`\n AnalyticsFile string `json:\u0026#34;analytics_file\u0026#34;`\n StaticFileVersion int `json:\u0026#34;static_file_version\u0026#34;`\n StaticDir string `json:\u0026#34;static_dir\u0026#34;`\n TemplatesDir string `json:\u0026#34;templates_dir\u0026#34;`\n SerTcpSocketHost …\u003c/code\u003e\u003c/pre\u003e"
March 23, 2016
golang中的md5的用法
"\u003cp\u003e代码\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003epackage main\n\nimport (\n\t\u0026#34;crypto/md5\u0026#34;\n\t\u0026#34;encoding/hex\u0026#34;\n\t\u0026#34;fmt\u0026#34;\n)\n\nfunc main() {\n\t// md5 加密的第一种方法\n\tsrcData := []byte(\u0026#34;iyannik0215\u0026#34;)\n\tcipherText1 := md5.Sum(srcData)\n\tfmt.Printf(\u0026#34;md5 encrypto is \u0026#34;iyannik0215\u0026#34;: %x n\u0026#34;, cipherText1)\n\n\t// md5 加密的第二种方法\n\thash := md5.New()\n\thash.Write(srcData)\n\tcipherText2 := hash.Sum(nil)\n\thexText := make([]byte, 32)\n\thex.Encode(hexText, cipherText2)\n\tfmt.Println(\u0026#34;md5 encrypto is \u0026#34;iyannik0215\u0026#34;:\u0026#34;, …\u003c/code\u003e\u003c/pre\u003e"
March 21, 2016
如何优雅的在 koa 中处理错误
"\u003cp\u003e\u003ca href=\"http://taobaofed.org/blog/2016/03/18/error-handling-in-koa/\"\u003ehttp://taobaofed.org/blog/2016/03/18/error-handling-in-koa/\u003c/a\u003e\u003c/p\u003e"