以太坊中除了基于运算能力的 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 !

阅读全文

最近体验了一下微信小程序开发,做了一个简单的刷猫片的小玩具,效果大致如下: 开始是用 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 技术栈笔记 如果觉得本篇文章对您十分有益,何不 打赏一下 本文链接地址: 微信小程序【有猫撸】开发体验 本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可

阅读全文

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

阅读全文

看到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.

阅读全文

译文 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') ?

阅读全文

译文 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实例:

阅读全文

译文 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()。

阅读全文

译文 GitHub https://github.com/yuansir/diving-laravel-zh 原文链接 https://divinglaravel.com/task-scheduling/properties-of-an-event 你添加的每个记录都将转换为 Illuminate\Console\Scheduling\Event 的实例,并存储在 Scheduler 的 $events 类属性中,Event 对象由以下内容组成: 命令运行 CRON 表达式 用于评估时间的时区 操作系统运行该命令的用户 命令应该运行的环境列表 维护模式配置 事件重叠配置 命令前台/后台运行配置 用于决定该命令是否运行的检查列表 如何处理输出的配置 命令运行后运行的回调 在命令运行前运行的回调 命令说明 命令的唯一 Mutex 命令可能像下面一种方式运行: 回调 在操作系统上运行的命令 artisan 命令 被调度的作业 使用回调 在回调的情况下,Container::call() 方法用于运行我们传递的值,这意味着我们可以传递一个可以调用或表示方法的字符串: protected function schedule(Schedule $schedule) { $schedule->call(function () { DB::table('recent_users')->delete(); })->daily(); } Or: protected function schedule(Schedule $schedule) { $schedule->call('MetricsRepository@cleanRecentUsers')->daily(); } 调用操作系统的命令 如果要运行操作系统的命令,可以使用 exec(): $schedule->exec('php /home/sendmail.php --user=10 --attachInvoice')->monthly(); 您还可以将数组作为参数:

阅读全文

译文 GitHub https://github.com/yuansir/diving-laravel-zh 原文链接 https://divinglaravel.com/task-scheduling/before-the-dive 想象这种情况,作为一个大型 SaaS 的开发者,您需要找到一种在周末每分钟选择 10 个随机客户的方式,并提供折扣升级,发送折扣的工作可能非常简单,但我们需要每分钟运行一次,为此我分享一些 CRON 的简要介绍给还不熟悉人。 CRON CRON 是一个守护进程,它驻留在你的 linux 服务器中,大部分时间都没有唤醒,但是每一分钟它都会睁开双眼,看看是否运行任何给定的任务,你使用 crontab 文件与该守护进程通信,在大多数常见的设置文件可以位于/etc/crontab,crontab 文件可能看起来像这样: 0 0 1 * * /home/full-backup 0 0 * * * /home/partial-backup 30 5 10 * * /home/check-subscriptions 在 crontab 文件中,每行表示一个计划任务作业,每个作业定义包含两部分: *部分代表该作业运行的计时器。 第二部分是应运行的命令 CRON 时序语法 5 个星号按顺序排列如下: 一小时内的分钟 一天内的小时 一个月内的日期 一年内的月份 一周的内的天 示例: 0 0 1 * * 在第一个例子中,表示该工作应在每月,每个月的第一个天,上午 12 点,每小时第一分钟运行。 或者简单地说,它应该在每月的第一天上午 12:00 运行。 0 * * * * 在第二个例子中,表示该工作应该每小时运行一次。 30 5 10 * * 表示该工作应该在每个月 10 日上午 5:30 运行 这里还有一些其他的示例:

阅读全文

译文 GitHub https://github.com/yuansir/diving-laravel-zh 原文链接https://divinglaravel.com/queue-system/pushing-jobs-to-queue 有几种方法可以将作业推送到队列中: Queue::push(new InvoiceEmail($order)); Bus::dispatch(new InvoiceEmail($order)); dispatch(new InvoiceEmail($order)); (new InvoiceEmail($order))->dispatch(); 调用Queue facade 是对应用程序使用的队列驱动的调用,如果你使用数据库队列驱动,调用push方法是调用Queue\DatabaseQueue类的push方法。 有几种有用的方法可以使用: // 将作业推送到特定的队列 Queue::pushOn('emails', new InvoiceEmail($order)); // 在给定的秒数之后推送作业 Queue::later(60, new InvoiceEmail($order)); // 延迟后将作业推送到特定的队列 Queue::laterOn('emails', 60, new InvoiceEmail($order)); // 推送多个作业 Queue::bulk([ new InvoiceEmail($order), new ThankYouEmail($order) ]); // 推送特定队列上的多个作业 Queue::bulk([ new InvoiceEmail($order), new ThankYouEmail($order) ], null, 'emails'); 调用这些方法之后,所选择的队列驱动会将给定的信息存储在存储空间中,供 workers 按需获取。 使用命令总线 使用命令总线调度作业进行排队可以给你额外控制权; 您可以从作业类中设置选定的connection, queue, and delay 来决定命令是否应该排队或立即运行,在运行之前通过管道发送作业,实际上你甚至可以从你的作业类中处理整个队列过程。 Bug facade 代理到Contracts\Bus\Dispatcher 容器别名,此别名解析为Bus\Dispatcher内的Bus\BusServiceProvider的一个实例: $this->app->singleton(Dispatcher::class, function ($app) { return new Dispatcher($app, function ($connection = null) use ($app) { return $app[QueueFactoryContract::class]->connection($connection); }); }); 所以Bus::dispatch() 调用的 dispatch() 方法是 Bus\Dispatcher 类的:

阅读全文

作者的图片

Ryan是菜鸟 | LNMP技术栈笔记

一步一个脚印,一直在路上!记录LNMP技术栈,Web架构,区块链等笔记

菜鸟码农

南京