在之前介绍了《Go实践微服务 – gRPC配置和使用》,通过gRPC直接编写微服务有点麻烦,比如都需要手动指定服务地址和端口,不便于管理,也需要自己来实现服务注册和发现的逻辑,同时对于网关以及监控等都是微服务架构和实施中不可避免的。所以引入 go-micro,go-micro是一个插件式的RPC框架,它是Micro生态的一部分,Micro是一个简化分布式开发的微服务生态系统,它为开发分布式应用程序提供了基本的构建模块。 Go Micro抽象出分布式系统的细节。以下是主要功能。 服务发现 - 通过服务发现自动注册和名称解析 负载平衡 - 基于发现构建的服务的智能客户端负载平衡 同步通信 - 基于RPC的通信,支持双向流 异步通信 - 为事件驱动架构内置的Pub/Sub接口 消息编码 - 基于带有protobuf和json的内容类型的动态编码 服务接口 - 所有功能都打包在一个简单的高级界面中,用于开发微服务 通过写一个船运的示例看下go-micro如何来写一个微服务。 安装protoc-gen-micro go get github.com/micro/protoc-gen-micro 编写proto文件来定义服务 consignment-service/proto/consignment/consignment.proto syntax = "proto3"; package go.micro.srv.consignment; // 定义货轮服务 service ShippingService { // 托运一批货物 rpc CreateConsignment (Consignment) returns (Response) { } // 查看货物信息 rpc GetConsignments (GetRequest) returns (Response) { } } // 货物信息 message Consignment { string id = 1; // ID string description = 2; // 描述 int32 weight = 3; // 重量 repeated Container containers = 4; // 集装箱,多个 string vessel_id = 5; // 承运货轮ID } // 集装箱 message Container { string id = 1; // 编号 string customer_id = 2; // 客户ID string origin = 3; // 出发地 string user_id = 4; // 集装箱所属用户ID } // 托运结果 message Response { bool created = 1; // 托运结果 Consignment consignment = 2; // 新托运的货物 repeated Consignment consignments = 3; // 所有托运的货物 } message GetRequest { } 生成 gRPC 代码 consignment-service/Makefile

阅读全文

gRPC是一个高性能、开源和通用的RPC框架,面向移动和HTTP/2 设计。 它有很多特点,如双向流、流控、头部压缩、单TCP连接上的多复用请求,节省带宽、降低TCP链接次数、节省CPU使用和延长电池寿命等。强大的IDL,默认采用Protocol Buffers数据序列化协议,支持多种开发语言以及移动端。gRPC既能够在客户端应用,也能够在服务器端应用,从而以透明的方式实现客户端和服务器端的通信和简化通信系统的构建,很容易去构建分布式应用和微服务架构模式。 各大主流的RPC框架的性能比较可以参考这一篇《流行的rpc框架benchmark 2018新春版》 我很久前写过一篇《Thrift 应用总结》 安装protobuf编译器 官方推荐使用protobuf 3,我用的是Mac,所以可以直接用brew安装 3.X 版本 brew info protobuf brew install protobuf 安装完可以看下版本号 protoc --version libprotoc 3.5.1 当然也可以通过编译安装 #去下载Protocol Buffers v3.5.1的release包 brew info automake brew info libtool # 没有这两个就安装 ./autogen.sh # 检查没问题了 ./configure make -j8 make check make install 安装Golang for protobuf插件 go get -u -v github.com/golang/protobuf/proto go get -u -v github.com/golang/protobuf/protoc-gen-go 安装grpc-go go get -u -v google.golang.org/grpc 由于墙的原因,可能你会看到下面的错误:

阅读全文

Go 实现依赖注入

为什么需要依赖注入 作为一名软件开发人员,如果我们希望使代码保持清洁和可维护性,我们将代码分割成不同的层次。 通常边界至少放置在基础设施和业务逻辑之间。当我们专门处理复杂的业务逻辑时,基础架构依赖于我们的业务逻辑是可取的,这样在更改基础架构时不会破坏我们的软件。 开发一个新的软件项目时的第一个决定是否选择一个结构来实现分层。 大多数情况下,我选择简洁的架构,但您有另一个很好的选择,例如Domain Driven Design(领域驱动设计)。 独立于您选择的架构,我们必须粘贴来自不同模块以提供新功能,而这正是依赖注入所发挥的作用。 如何实现依赖注入 理解依赖注入,没有比示例更好的了。 想象一下,我们必须为我们想象中的项目实现用户注册,并且我们将用简约的架构来实现这一点。 我们可以想出一个像这样的实体: package entity //User结构体 type User struct { email string password string name string dateOfBirth string } //业务级别的验证 func Validate() error { ... } 现在我们来创建一个用户注册的用例: package usecase import "entity" func RegisterUser(user entity.User) { //验证和保存用户逻辑 } 看起来我们需要一些基础设施模块来存储用户。 我们还没有在基础设施级别实现任何UserRepository,我们还遇到了另一个问题,通过简洁的架构原则,更高级别的层无法知道低级别层的存在。 如何来解决这个问题? 不需要触及基础设施中的任何部分,我们会对我们的用例说,有某种用户保护程序可以帮助我们的用户注册。 package usecase import "entity" type UserSaver interface { Save(user entity.User) error } //UserRegisterUseCase 存储它的依赖关系 type UserRegisterUseCase struct { userSaver UserSaver } func newUserRegisterUseCase(userSaver UserSaver) UserRegisterUseCase { return &{userSaver} } func (u UserRegisterUseCase) RegisterUser(user entity.

阅读全文

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

阅读全文

作者的图片

Ryan是菜鸟 | LNMP技术栈笔记

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

菜鸟码农

南京