以太坊中除了基于运算能力的POW(Ethash)外,还有基于权利证明的POA共识机制,Clique是以太坊的POA共识算法的实现,这里主要对POA的Clique相关源码做一个解读分析。 Clique的初始化在 Ethereum.StartMining中,如果Ethereum.engine配置为clique.Clique, 根据当前节点的矿工地址(默认是acounts[0]), 配置clique的 签名者 : clique.Authorize(eb, wallet.SignHash) ,其中签名函数是SignHash,对给定的hash进行签名。 func (s *Ethereum) StartMining(local bool) error { eb, err := s.Etherbase()//用户地址 if err != nil { log.Error("Cannot start mining without etherbase", "err", err) return fmt.Errorf("etherbase missing: %v", err) } if clique, ok := s.engine.(*clique.Clique); ok { //如果是clique共识算法 wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) // 根据用它胡地址获取wallet对象 if wallet == nil || err != nil { log.Error("Etherbase account unavailable locally", "err", err) return fmt.

阅读全文

最近体验了一下微信小程序开发,做了一个简单的刷猫片的小玩具,效果大致如下: 开始是用Laravel写了API,后来又用Go的Iris写了一套,压测了一下,Iris的性能比Laravel的高了可不是一点点,后来就换Iris版本的API了。数据通过Go写了个简单的脚本抓取入库,附件上传到七牛。 本来这个小程序还有小论坛和复制淘宝链接功能的,但是上传到微信审核以后死活不能通过审核,就阉割掉了,暂时就先放几个刷猫片的小模块玩玩吧。 说下体验开发微信小程序的感受吧: 上手不难,尤其是熟悉Vue.js这样的前端框架的话刷下文档就直接上手做了 API还算丰富,而且开放的API越来越多,脑洞大一点可以做一些有趣的小程序 从微信小程序后台统计来看,果然是用完即走,而且走了就不回来了 …… 微信小程序还是略封闭,比如我的社区板块一直审核不通过,关键也不告诉具体未通过的原因,就说未经微信授权巴拉巴拉的 源码请戳这里: https://github.com/yuansir/youmaolu-weixin-app-api https://github.com/yuansir/youmaolu-weixin-app 体验请微信扫描: 之前搭建的一个撸猫社区(有猫撸)一直放着没搞了,有空得把注册重新写一下,邮箱激活还不支持中文名这种注册方式确实太蛋疼了。。。。 转载请注明: 转载自Ryan是菜鸟 | LNMP技术栈笔记 如果觉得本篇文章对您十分有益,何不打赏一下 本文链接地址: 微信小程序【有猫撸】开发体验

阅读全文

Laravel是我最喜欢的PHP Web开发框架,所以也希望可以在Go的Web框架中选择一个类似Laravel这样的好用又全栈的框架,刷了一下Beego, Echo , Gin, 以及Iris的文档,最终还是选择Iris,当然我是没有从性能角度考虑,只是从可以快速开发,且支持的特性全还有就是看着顺眼的心理选择了Iris,应该有不少PHPer像我一样使用Laravel同时在学习Go,所以为了便于Laravel开发者可以快速的转到Iris开发,我准备写一系列这两者框架的比较文章。 基本路由 Iris构建基本路由和Laravel的基本路由很像,都只需要一个URI与一个闭包: Laravel Route::get('foo', function () { return 'Hello World'; }); Iris app.Get("/foo", func(ctx iris.Context) { ctx.WriteString("Hello World") }) 可用的路由方法 Iris和Laravel一样,能够响应任何的HTTP请求路由: Laravel Route::get($uri, $callback); Route::post($uri, $callback); Route::put($uri, $callback); Route::patch($uri, $callback); Route::delete($uri, $callback); Route::options($uri, $callback); Iris app.Post("/", func(ctx iris.Context){}) app.Put("/", func(ctx iris.Context){}) app.Delete("/", func(ctx iris.Context){}) app.Options("/", func(ctx iris.Context){}) app.Trace("/", func(ctx iris.Context){}) app.Head("/", func(ctx iris.Context){}) app.Connect("/", func(ctx iris.Context){}) app.Patch("/", func(ctx iris.Context){}) 对于注册一个可以响应多个HTTP请求的路由两者同样都支持

阅读全文

看到Laravel-China社区常有人问Laravel Passport用于密码验证方式来获取Token的问题,刚好我最近一个API项目使用Laravel Dingo Api+Passport,也是使用Oauth2 的'grant_type' => 'password'密码授权来做Auth验证,对于如何做登录登出,以及多账号系统的认证等常用场景做一下简单的使用小总结。 基本配置 基本安装配置主要参照官方文档,具体不详细说,列出关键代码段 config/auth.php 'guards' => [ 'api' => [ 'driver' => 'passport', 'provider' => 'users', ], ], 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => \App\Models\User::class ], ], Providers/AuthServiceProvider.php public function boot() { $this->registerPolicies(); //默认令牌发放的有效期是永久 //Passport::tokensExpireIn(Carbon::now()->addDays(2)); //Passport::refreshTokensExpireIn(Carbon::now()->addDays(4)); Passport::routes(function (RouteRegistrar $router) { //对于密码授权的方式只要这几个路由就可以了 config(['auth.guards.api.provider' => 'users']); $router->forAccessTokens(); }); } Middleware/AuthenticateApi.php 自定义中间件返回 <?php namespace App\Http\Middleware; use Closure; use Illuminate\Auth\Middleware\Authenticate; use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; class AuthenticateApi extends Authenticate { protected function authenticate(array $guards) { if ($this->auth->guard('api')->check()) { return $this->auth->shouldUse('api'); } throw new UnauthorizedHttpException('', 'Unauthenticated'); } } App/Http/Kernel.

阅读全文

译文GitHub https://github.com/yuansir/diving-laravel-zh 原文链接 https://divinglaravel.com/queue-system/workers 现在,我们知道了Laravel如何将作业推到不同的队列中,让我们来深入了解workers如何运作你的作业。 首先,我将workers定义为一个在后台运行的简单PHP进程,目的是从存储空间中提取作业并针对多个配置选项运行它们。 php artisan queue:work 运行此命令将指示Laravel创建应用程序的一个实例并开始执行作业,这个实例将一直存活着,启动Laravel应用程序的操作只在运行命令时发生一次,同一个实例将被用于执行你的作业,这意味着: 避免在每个作业上启动整个应用程序来节省服务器资源。 在应用程序中所做的任何代码更改后必须手动重启worker。 你也可以这样运行: php artisan queue:work --once 这将启动应用程序的一个实例,处理单个作业,然后干掉脚本。 php artisan queue:listen queue:listen 命令相当于无限循环地运行 queue:work --once 命令,这将导致以下问题: 每个循环都会启动一个应用程序实例。 分配的worker将选择一个工作并执行。 worker进程将被干掉。 使用 queue:listen 确保为每个作业创建一个新的应用程序实例,这意味着代码更改以后不必手动重启worker,同时也意味着将消耗更多的服务器资源。 queue:work 命令 我们来看看 Queue\Console\WorkCommand 类的 handle() 方法,这是当你运行 php artisan queue:work 时会执行的方法: public function handle() { if ($this->downForMaintenance() && $this->option('once')) { return $this->worker->sleep($this->option('sleep')); } $this->listenForEvents(); $connection = $this->argument('connection') ?: $this->laravel['config']['queue.default']; $queue = $this->getQueue($connection); $this->runWorker( $connection, $queue ); } 首先,我们检查应用程序是否处于维护模式,并使用 --once 选项,在这种情况下,我们希望脚本正常运行,因此我们不执行任何作业,我们只需要在完全杀死脚本前让worker在一段时间内休眠。

阅读全文

译文GitHub https://github.com/yuansir/diving-laravel-zh 原文链接 https://divinglaravel.com/task-scheduling/preventing-overlapping 有时一个预定的工作需要比我们最初预期的更多的时间运行,这样会导致另外一个工作的实例开始,而第一个还没有完成,例如,我们运行一个每分钟生成报告的工作有时候当数据变大时,报表生成可能需要1分钟以上,这样就可以在第一个还在进行时启动该作业的另一个实例。 在大多数情况下,这是很好的,但有时候应该防止这种情况,以保证正确的数据或防止高的服务器资源消耗,所以让我们看看如何防止这种情况在laravel中发生: $schedule->command('mail:send')->withoutOverlapping(); Laravel将检查 Console\Scheduling\Event::withoutOverlapping 类属性,如果设置为true,它将尝试为作业创建互斥,并且只有在创建互斥的情况下才能运行该作业。 但是上面是互斥? 这是我可以在网上找到最有趣的解释: 当我在工作中进行热烈的讨论时,我使用一只橡胶鸡,我在这样的场合放在桌子上。 持有鸡的人是唯一被允许谈话的人。 如果你不握鸡,你不会说话。 你只能指示你想要鸡,等到你说话之前才能得到它。 一旦你完成演讲,你可以将鸡回到主持人,他将把它交给下一个人说话。 这样可以确保人们互不说话,也有自己的空间。 用线替换鸡与互斥和人,你基本上有一个互斥的概念。 – https://stackoverflow.com/questions/34524/what-is-a-mutex/34558#34558 所以当作业第一次启动时,Laravel创建一个互斥,然后每次作业运行时,它检查互斥是否存在,只有在没有工作的情况下运行。 这里是 withoutOverlapping 方法中做的事 public function withoutOverlapping() { $this->withoutOverlapping = true; return $this->then(function () { $this->mutex->forget($this); })->skip(function () { return $this->mutex->exists($this); }); } 因此,Laravel创建一个filter-callback方法,指示Schedule Manager忽略任务,如果互斥仍然存在,它还会创建一个在完成任务实例后清除互斥的回调。 在运行该作业之前,Laravel会在Console\Scheduling\Event::run()方法中进行以下检查: if ($this->withoutOverlapping && ! $this->mutex->create($this)) { return; } 互斥体属性来自哪里? 当 Console\Scheduling\Schedule 的实例被实例化时,laravel会检查 Console\Scheduling\Mutex 接口的实现是否绑定到容器,如果是,则使用该实例,如果不是,使用Console\Scheduling\CacheMutex实例: $this->mutex = $container->bound(Mutex::class) ?

阅读全文

译文GitHub https://github.com/yuansir/diving-laravel-zh 原文链接 https://divinglaravel.com/task-scheduling/building-and-running-the-os-command 在启动计划任务的事件的时候,Laravel的进度管理器在Illuminate\Console\Scheduling\Event对象上调用 run() 方法,表示该事件发生在 Illuminate\Console\Scheduling\ScheduleRunCommand 内。 这个 run() 方法构建命令语法,并使用Symfony Process组件在操作系统上运行它,但在构建命令之前,它首先检查该命令是否应该在后台运行,默认情况下所有命令都在前台运行 除非你使用以下方法来调度命令: ->runInBackground() 什么时候我需要在后台运行命令? 假设如果您有几个任务应该同时运行,比如每个小时,Laravel默认设置会指示操作系统逐个运行命令: ~ php artisan update:coupons # Waiting for the command to finish # ... # Command finished, now we run the next one ~ php artisan send:mail 但是,你可以指示操作系统在后台运行命令,以便您可以继续推送更多命令,即使其他命令尚未完成: ~ php artisan update:coupons & ~ php artisan send:mail & 使用命令末尾的&符号可以继续推送命令,而无需等待初始化完成。 run() 方法检查 runInBackground 属性的值,并决定下一个调用哪个方法runCommandInForeground() 还是 runCommandInBackground()。 如果命令要在前台运行,其余部分就简单了: $this->callBeforeCallbacks($container); (new Process( $this->buildCommand(), base_path(), null, null, null ))->run(); $this->callAfterCallbacks($container); Laravel执行任意before-callbacks,将命令发送到OS,最后执行任意before-callbacks。

阅读全文

作者的图片

Ryan是菜鸟 | LNMP技术栈笔记

一步一个脚印,一直在路上! LNMP技术栈,web架构学习笔记

菜鸟码农

南京