go-micro+php+consul简单的微服实现
<p> </p><div>
<p>首先我们用go-micro构建一个服务。(关于go-micro的使用可以参照官方实例或者文档)</p>
<div class="highlight">
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">新建一个微服务</span>
micro <span style="color: rgba(0, 0, 255, 1)">new</span> --type "srv" user-srv</pre>
</div>
<p> </p>
<pre><span style="font-family: "PingFang SC", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px">定义我们的服务,这里定义两个rpc服务,Register和User</span></pre>
</div>
<div class="highlight">
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 修改proto</span>
<span style="color: rgba(0, 128, 128, 1)"> 2</span> syntax = "proto3"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> package go.micro.srv.<span style="color: rgba(0, 0, 0, 1)">user;
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 0, 1)">service User {
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 0, 0, 1)"> rpc Register(RegisterRequest) returns (UserInfo) {}
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 0, 1)"> rpc User(UserInfoRequest) returns (UserInfo) {}
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 0, 0, 1)"> rpc Stream(StreamingRequest) returns (stream StreamingResponse) {}
</span><span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 0, 0, 1)"> rpc PingPong(stream Ping) returns (stream Pong) {}
</span><span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">13</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 0, 0, 1)">message UserInfoRequest {
</span><span style="color: rgba(0, 128, 128, 1)">15</span> int64 userId= 1<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">16</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">17</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">18</span> <span style="color: rgba(0, 0, 0, 1)">message RegisterRequest {
</span><span style="color: rgba(0, 128, 128, 1)">19</span> <span style="color: rgba(0, 0, 255, 1)">string</span> username= 1<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">20</span> <span style="color: rgba(0, 0, 255, 1)">string</span> email = 2<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">21</span> <span style="color: rgba(0, 0, 255, 1)">string</span> password= 3<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">22</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">23</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">24</span> <span style="color: rgba(0, 0, 0, 1)">message UserInfo {
</span><span style="color: rgba(0, 128, 128, 1)">25</span> int64id =1<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">26</span> <span style="color: rgba(0, 0, 255, 1)">string</span> username =2<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">27</span> <span style="color: rgba(0, 0, 255, 1)">string</span> email =3<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">28</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">29</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">30</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">31</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">32</span> <span style="color: rgba(0, 0, 0, 1)">message StreamingRequest {
</span><span style="color: rgba(0, 128, 128, 1)">33</span> int64 <span style="color: rgba(0, 128, 128, 1)">count</span> = 1<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">34</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">35</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">36</span> <span style="color: rgba(0, 0, 0, 1)">message StreamingResponse {
</span><span style="color: rgba(0, 128, 128, 1)">37</span> int64 <span style="color: rgba(0, 128, 128, 1)">count</span> = 1<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">38</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">39</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">40</span> <span style="color: rgba(0, 0, 0, 1)">message Ping {
</span><span style="color: rgba(0, 128, 128, 1)">41</span> int64 stroke = 1<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">42</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">43</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">44</span> <span style="color: rgba(0, 0, 0, 1)">message Pong {
</span><span style="color: rgba(0, 128, 128, 1)">45</span> int64 stroke = 1<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">46</span> }</pre>
</div>
<p> </p>
</div>
<p>然后生成执行下面命令我们就可以发现在proto文件中多出两个文件。这个proto为我们生成的,后面会用到。</p>
<div class="highlight">
<div class="cnblogs_code">
<pre>protoc --proto_path=${GOPATH}/src:. --micro_out=. --go_out=. proto/user/user.proto</pre>
</div>
<p> </p>
</div>
<p>写我们的业务逻辑,修改handle/user.go文件</p>
<div class="highlight">
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 0, 1)">type User struct{}
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Call is a single request handler called via client.Call or the generated client code</span>
<span style="color: rgba(0, 128, 128, 1)"> 4</span> func (e *User) Register(ctx context.Context, req *user.RegisterRequest, rsp *user.<span style="color: rgba(0, 0, 0, 1)">UserInfo) error {
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 128, 128, 1)">log</span>.<span style="color: rgba(0, 128, 128, 1)">Log</span>("Received User.Register request"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> rsp.Id = 1
<span style="color: rgba(0, 128, 128, 1)"> 7</span> rsp.Email = req.<span style="color: rgba(0, 0, 0, 1)">Email
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> rsp.Username = req.<span style="color: rgba(0, 0, 0, 1)">Username
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> nil
</span><span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">13</span> func (e *User) User(ctx context.Context, req *user.UserInfoRequest, rsp *user.<span style="color: rgba(0, 0, 0, 1)">UserInfo) error {
</span><span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 128, 128, 1)">log</span>.<span style="color: rgba(0, 128, 128, 1)">Log</span>("Received User.Register request"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">15</span> rsp.Id = 1
<span style="color: rgba(0, 128, 128, 1)">16</span> rsp.Email = "741001560@qq.com"
<span style="color: rgba(0, 128, 128, 1)">17</span> rsp.Username = "chensi"
<span style="color: rgba(0, 128, 128, 1)">18</span> <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> nil
</span><span style="color: rgba(0, 128, 128, 1)">19</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">20</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">21</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Stream is a server side stream handler called via client.Stream or the generated client code</span>
<span style="color: rgba(0, 128, 128, 1)">22</span> func (e *User) Stream(ctx context.Context, req *user.StreamingRequest, stream user.<span style="color: rgba(0, 0, 0, 1)">User_StreamStream) error {
</span><span style="color: rgba(0, 128, 128, 1)">23</span> <span style="color: rgba(0, 128, 128, 1)">log</span>.Logf("Received User.Stream request with count: %d", req.<span style="color: rgba(0, 128, 128, 1)">Count</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">24</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">25</span> <span style="color: rgba(0, 0, 255, 1)">for</span> i := 0; i < int(req.<span style="color: rgba(0, 128, 128, 1)">Count</span>); i++<span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">26</span> <span style="color: rgba(0, 128, 128, 1)">log</span>.Logf("Responding: %d",<span style="color: rgba(0, 0, 0, 1)"> i)
</span><span style="color: rgba(0, 128, 128, 1)">27</span> <span style="color: rgba(0, 0, 255, 1)">if</span> err := stream.Send(&user.<span style="color: rgba(0, 0, 0, 1)">StreamingResponse{
</span><span style="color: rgba(0, 128, 128, 1)">28</span> <span style="color: rgba(0, 128, 128, 1)">Count</span>: int64(i),
<span style="color: rgba(0, 128, 128, 1)">29</span> }); err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
</span><span style="color: rgba(0, 128, 128, 1)">30</span> <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> err
</span><span style="color: rgba(0, 128, 128, 1)">31</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">32</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">33</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">34</span> <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> nil
</span><span style="color: rgba(0, 128, 128, 1)">35</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">36</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">37</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> PingPong is a bidirectional stream handler called via client.Stream or the generated client code</span>
<span style="color: rgba(0, 128, 128, 1)">38</span> func (e *User) PingPong(ctx context.Context, stream user.<span style="color: rgba(0, 0, 0, 1)">User_PingPongStream) error {
</span><span style="color: rgba(0, 128, 128, 1)">39</span> <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">40</span> req, err := stream.<span style="color: rgba(0, 0, 0, 1)">Recv()
</span><span style="color: rgba(0, 128, 128, 1)">41</span> <span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
</span><span style="color: rgba(0, 128, 128, 1)">42</span> <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> err
</span><span style="color: rgba(0, 128, 128, 1)">43</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">44</span> <span style="color: rgba(0, 128, 128, 1)">log</span>.Logf("Got ping %v", req.<span style="color: rgba(0, 0, 0, 1)">Stroke)
</span><span style="color: rgba(0, 128, 128, 1)">45</span> <span style="color: rgba(0, 0, 255, 1)">if</span> err := stream.Send(&user.Pong{Stroke: req.Stroke}); err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
</span><span style="color: rgba(0, 128, 128, 1)">46</span> <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> err
</span><span style="color: rgba(0, 128, 128, 1)">47</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">48</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">49</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">50</span></pre>
</div>
<p> </p>
</div>
<p>最后修改我们的main.go文件,服务发现使用时consul。</p>
<div class="highlight">
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 0, 1)">func main() {
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">initCfg()
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 128, 0, 1)"> // New Service</span>
<span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> micReg := consul.<span style="color: rgba(0, 0, 0, 1)">NewRegistry()
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> service := micro.<span style="color: rgba(0, 0, 0, 1)">NewService(
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> micro.Server(s.NewServer()),
<span style="color: rgba(0, 128, 128, 1)"> 9</span> micro.Name("go.micro.srv.user"),
<span style="color: rgba(0, 128, 128, 1)">10</span> micro.Version("latest"),
<span style="color: rgba(0, 128, 128, 1)">11</span> micro.Registry(micReg),
<span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 0, 1)"> )
</span><span style="color: rgba(0, 128, 128, 1)">13</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Initialise service</span>
<span style="color: rgba(0, 128, 128, 1)">15</span> service.<span style="color: rgba(0, 0, 0, 1)">Init()
</span><span style="color: rgba(0, 128, 128, 1)">16</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">17</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Run service</span>
<span style="color: rgba(0, 128, 128, 1)">18</span> <span style="color: rgba(0, 0, 255, 1)">if</span> err := service.Run(); err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
</span><span style="color: rgba(0, 128, 128, 1)">19</span> <span style="color: rgba(0, 128, 128, 1)">log</span>.<span style="color: rgba(0, 0, 0, 1)">Fatal(err)
</span><span style="color: rgba(0, 128, 128, 1)">20</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">21</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">22</span></pre>
</div>
<p> </p>
</div>
<p>我们使用consul做微服务发现,当然首先你需要安装consul</p>
<div class="highlight">
<div class="cnblogs_code">
<pre>wget https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">releases.hashicorp.com/consul/1.2.0/consul_1.6.1_linux_amd64.zip</span>
unzip consul_1.6.1_linux_amd64.<span style="color: rgba(0, 0, 0, 1)">zip
mv consul </span>/usr/local/bin/</pre>
</div>
<p> </p>
</div>
<p>启动consul的时候由于在是本地虚拟机上面,所以我们可以简单处理</p>
<div class="highlight">
<div class="cnblogs_code">
<pre>consul agent -dev-client 0.0.0.0 -ui</pre>
</div>
<p> </p>
</div>
<p>这时候可以启动consul的ui了,我本地vagrant的虚拟机192.168.10.100,那么我们打开的是<span class="invisible">http://<span class="visible">192.168.10.100:8500/ui/<span class="invisible">dc1/services</span></span></span></p>
<p>启动user-srv的服务发现consul里面出现 go.micro.srv.user 的服务注册信息了</p>
<p>下面来写hyperf的代码了。按照官方文档安装框架,安装的时候rpc需要选择grpc,需要注意的是你的系统上面需要安装php7.2以上的版本,swoole版本也需要4.3的版本以上,我用的是最新homestead,所以相对而言安装这些依赖比较简单,所以在此强烈推荐。</p>
<p>第一次启动时候官方会要求修改一些php.ini的参数,大家安装要求走就是了。</p>
<p>这部分的流程自己参照官方文档,至于一些扩展的安装可以谷歌或者百度。</p>
<p>安装好框架之后再根目录下面新建一个grpc和proto的目录,把go-micro里面user.proto文件复制到hyperf项目的proto的目录之下。然后在目录下执行命令</p>
<div class="highlight">
<div class="cnblogs_code">
<pre>protoc --php_out=plugins=grpc:../grpc user.proto</pre>
</div>
<p> </p>
</div>
<p>执行成功之后会发现在grpc目录下多出两个文件夹。</p>
<p>接下来我们开始编写client的代码,在hyperf项目的app目录下新建一个Grpc的目录并且新建一个UserClient.php的文件</p>
<div class="highlight">
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 0, 1)">namespace App\Grpc;
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(0, 0, 255, 1)">use</span><span style="color: rgba(0, 0, 0, 1)"> Go\Micro\Srv\User\RegisterRequest;
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 0, 255, 1)">use</span><span style="color: rgba(0, 0, 0, 1)"> Go\Micro\Srv\User\UserInfo;
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 255, 1)">use</span><span style="color: rgba(0, 0, 0, 1)"> Hyperf\GrpcClient\BaseClient;
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 255, 1)">class</span> UserClient <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> BaseClient
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> Register(RegisterRequest <span style="color: rgba(128, 0, 128, 1)">$argument</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">simpleRequest(
</span><span style="color: rgba(0, 128, 128, 1)">13</span> '/user.User/Register',
<span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(128, 0, 128, 1)">$argument</span>,
<span style="color: rgba(0, 128, 128, 1)">15</span>
</span><span style="color: rgba(0, 128, 128, 1)">16</span> <span style="color: rgba(0, 0, 0, 1)"> );
</span><span style="color: rgba(0, 128, 128, 1)">17</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">18</span> </pre>
</div>
<p> </p>
</div>
<p>关于这一块的代码,其实官方文档写得特别详细,具体可以参照官方文档。</p>
<p>新建一个路由</p>
<div class="highlight">
<div class="cnblogs_code">
<pre>Router::addRoute(['GET', 'POST', 'HEAD'], '/grpc', 'App\Controller\IndexController@grpc');</pre>
</div>
</div>
<p>编写控制器</p>
<div class="highlight">
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> grpc ()
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(128, 0, 128, 1)">$client</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> \App\Grpc\UserClient('127.0.0.1:9527',<span style="color: rgba(0, 0, 0, 1)"> [
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> 'credentials' => <span style="color: rgba(0, 0, 255, 1)">null</span>,
<span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 0, 1)"> ]);
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(128, 0, 128, 1)">$request</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> RegisterRequest();
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(128, 0, 128, 1)">$request</span>->setEmail("741001560@qq.com"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(128, 0, 128, 1)">$request</span>->setUsername("chensi"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(128, 0, 128, 1)">$request</span>->setPassword("123456"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">13</span> <span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
</span><span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 128, 0, 1)"> * @var \Grpc\HiReply $reply
</span><span style="color: rgba(0, 128, 128, 1)">15</span> <span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 128, 128, 1)">16</span> <span style="color: rgba(0, 0, 255, 1)">list</span>(<span style="color: rgba(128, 0, 128, 1)">$reply</span>, <span style="color: rgba(128, 0, 128, 1)">$status</span>) = <span style="color: rgba(128, 0, 128, 1)">$client</span>->Register(<span style="color: rgba(128, 0, 128, 1)">$request</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">17</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">18</span> <span style="color: rgba(128, 0, 128, 1)">$message</span> = <span style="color: rgba(128, 0, 128, 1)">$reply</span>-><span style="color: rgba(0, 0, 0, 1)">getId();
</span><span style="color: rgba(0, 128, 128, 1)">19</span> <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> [
</span><span style="color: rgba(0, 128, 128, 1)">20</span> 'id' => <span style="color: rgba(128, 0, 128, 1)">$message</span>
<span style="color: rgba(0, 128, 128, 1)">21</span> <span style="color: rgba(0, 0, 0, 1)"> ];
</span><span style="color: rgba(0, 128, 128, 1)">22</span> }</pre>
</div>
<p> </p>
</div>
<p>这时候还需要吧根目录下的grpc目录加载进来。修改composer.json文件</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">```
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> psr-4 下面新增两个行</span>
"autoload":<span style="color: rgba(0, 0, 0, 1)"> {
</span>"psr-4":<span style="color: rgba(0, 0, 0, 1)"> {
</span>"App\\": "app/",
"GPBMetadata\\": "grpc/GPBMetadata",
"Go\\": "grpc/Go"<span style="color: rgba(0, 0, 0, 1)">
}</span>,
"files":<span style="color: rgba(0, 0, 0, 1)"> []
}</span></pre>
</div>
<p> </p>
<p>然后执行composer dump-autoload命令。然后启动hyperf项目,打开浏览器输入<span class="invisible">http://<span class="visible">192.168.10.100:9501/grp<span class="invisible">c</span></span></span>回车,这时候我们就能看到结果了。</p>
<p>这时候我们会发现一个问题,那就是consul在client端压根没用到,在代码中我们还是需要指明我们的端口号。然后再看看官方文档其实是支持consul的,那么将代码改造下。</p>
<p>在app下新建一个Register的目录创建一个文件ConsulServices.php,然后开始编写服务发现的代码,安装consul包以后,由于官方提供的consul包没有文档所以需要自己去看源代码。官方在consul提供的api上面做了简单的封装,如KV、Health等,在实例化话的时候需要穿一个客户端过去。下面提供一个简单的实例。</p>
<div class="highlight">
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <?<span style="color: rgba(0, 0, 0, 1)">php
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 255, 1)">declare</span>(strict_types=1<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(0, 0, 0, 1)">namespace App\Register;
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 255, 1)">use</span><span style="color: rgba(0, 0, 0, 1)"> Hyperf\Consul\Health;
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 0, 255, 1)">use</span><span style="color: rgba(0, 0, 0, 1)"> Psr\Container\ContainerInterface;
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 255, 1)">use</span><span style="color: rgba(0, 0, 0, 1)"> Hyperf\Guzzle\ClientFactory;
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ConsulServices
</span><span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">13</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$servers</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(128, 0, 128, 1)">$container</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">15</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">16</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">17</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> __construct(ContainerInterface <span style="color: rgba(128, 0, 128, 1)">$container</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">18</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">19</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>->container = <span style="color: rgba(128, 0, 128, 1)">$container</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">20</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">21</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">22</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> getServers()
</span><span style="color: rgba(0, 128, 128, 1)">23</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">24</span> <span style="color: rgba(128, 0, 128, 1)">$health</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> Health(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (){
</span><span style="color: rgba(0, 128, 128, 1)">25</span> <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>->container->get(ClientFactory::<span style="color: rgba(0, 0, 255, 1)">class</span>)-><span style="color: rgba(0, 0, 0, 1)">create([
</span><span style="color: rgba(0, 128, 128, 1)">26</span> 'base_uri' => 'http://127.0.0.1:8500',
<span style="color: rgba(0, 128, 128, 1)">27</span> <span style="color: rgba(0, 0, 0, 1)"> ]);
</span><span style="color: rgba(0, 128, 128, 1)">28</span> <span style="color: rgba(0, 0, 0, 1)"> });
</span><span style="color: rgba(0, 128, 128, 1)">29</span> <span style="color: rgba(128, 0, 128, 1)">$resp</span> = <span style="color: rgba(128, 0, 128, 1)">$health</span>->service("go.micro.srv.user"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">30</span> <span style="color: rgba(128, 0, 128, 1)">$servers</span> = <span style="color: rgba(128, 0, 128, 1)">$resp</span>-><span style="color: rgba(0, 0, 0, 1)">json();
</span><span style="color: rgba(0, 128, 128, 1)">31</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">empty</span>(<span style="color: rgba(128, 0, 128, 1)">$servers</span><span style="color: rgba(0, 0, 0, 1)">)){
</span><span style="color: rgba(0, 128, 128, 1)">32</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>->servers =<span style="color: rgba(0, 0, 0, 1)"> [];
</span><span style="color: rgba(0, 128, 128, 1)">33</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">34</span> <span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(128, 0, 128, 1)">$servers</span> <span style="color: rgba(0, 0, 255, 1)">as</span> <span style="color: rgba(128, 0, 128, 1)">$server</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 128, 128, 1)">35</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>->servers[] = <span style="color: rgba(0, 128, 128, 1)">sprintf</span>("%s:%d",<span style="color: rgba(128, 0, 128, 1)">$server</span>['Service']['Address'],<span style="color: rgba(128, 0, 128, 1)">$server</span>['Service']['Port'<span style="color: rgba(0, 0, 0, 1)">]);
</span><span style="color: rgba(0, 128, 128, 1)">36</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">37</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">38</span> }</pre>
</div>
<p> </p>
</div>
<p>这时候发现一个问题如果每次请求过来都去请求一次必然给consul造成很大的负荷。既然用到了swoole框架可以在每次swoole启动的时候去请求一次,然后把服务发现的信息存起来。修改配置文件server。</p>
<div class="highlight">
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> 'callbacks' =><span style="color: rgba(0, 0, 0, 1)"> [
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> SwooleEvent::ON_BEFORE_START => ,</span>
<span style="color: rgba(0, 128, 128, 1)"> 3</span> SwooleEvent::ON_BEFORE_START => [\App\Bootstrap\ServerStartCallback::<span style="color: rgba(0, 0, 255, 1)">class</span>, 'beforeStart'],
<span style="color: rgba(0, 128, 128, 1)"> 4</span> SwooleEvent::ON_WORKER_START => ,
<span style="color: rgba(0, 128, 128, 1)"> 5</span> SwooleEvent::ON_PIPE_MESSAGE => ,
<span style="color: rgba(0, 128, 128, 1)"> 6</span> ],
<span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 0, 0, 1)">可以在ServerStartCallback类里面请求consul进行服务发现 后面拿到参数就好了。
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span>
<span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 0, 0, 1)">namespace App\Bootstrap;
</span><span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(0, 0, 255, 1)">use</span><span style="color: rgba(0, 0, 0, 1)"> App\Register\ConsulServices;
</span><span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 128, 1)">13</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ServerStartCallback
</span><span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 128, 128, 1)">15</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> beforeStart()
</span><span style="color: rgba(0, 128, 128, 1)">16</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">17</span> <span style="color: rgba(128, 0, 128, 1)">$container</span> = \Hyperf\Utils\ApplicationContext::<span style="color: rgba(0, 0, 0, 1)">getContainer();
</span><span style="color: rgba(0, 128, 128, 1)">18</span> <span style="color: rgba(128, 0, 128, 1)">$container</span>->get(ConsulServices::<span style="color: rgba(0, 0, 255, 1)">class</span>)-><span style="color: rgba(0, 0, 0, 1)">getServers();
</span><span style="color: rgba(0, 128, 128, 1)">19</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">20</span> }</pre>
</div>
<p> </p>
</div>
<p class="ztext-empty-paragraph"> </p>
<p>改造一下原来的控制器</p>
<div class="highlight">
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> grpc ()
{
</span><span style="color: rgba(128, 0, 128, 1)">$container</span> = \Hyperf\Utils\ApplicationContext::<span style="color: rgba(0, 0, 0, 1)">getContainer();
</span><span style="color: rgba(128, 0, 128, 1)">$servers</span> = <span style="color: rgba(128, 0, 128, 1)">$container</span>->get(ConsulServices::<span style="color: rgba(0, 0, 255, 1)">class</span>)-><span style="color: rgba(0, 0, 0, 1)">servers;
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">empty</span>(<span style="color: rgba(128, 0, 128, 1)">$servers</span><span style="color: rgba(0, 0, 0, 1)">)) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> [
</span>'errCode' => 1000,
'msg' => '服务不存在',<span style="color: rgba(0, 0, 0, 1)">
];
}
</span><span style="color: rgba(128, 0, 128, 1)">$key</span> = <span style="color: rgba(0, 128, 128, 1)">array_rand</span>(<span style="color: rgba(128, 0, 128, 1)">$servers</span>,1); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 哈哈哈一个简单的负载均衡</span>
<span style="color: rgba(128, 0, 128, 1)">$hostname</span> = <span style="color: rgba(128, 0, 128, 1)">$servers</span>[<span style="color: rgba(128, 0, 128, 1)">$key</span><span style="color: rgba(0, 0, 0, 1)">];
</span><span style="color: rgba(128, 0, 128, 1)">$client</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> \App\Grpc\UserClient(<span style="color: rgba(128, 0, 128, 1)">$hostname</span>,<span style="color: rgba(0, 0, 0, 1)"> [
</span>'credentials' => <span style="color: rgba(0, 0, 255, 1)">null</span>,<span style="color: rgba(0, 0, 0, 1)">
]);
</span><span style="color: rgba(128, 0, 128, 1)">$request</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> RegisterRequest();
</span><span style="color: rgba(128, 0, 128, 1)">$request</span>->setEmail("741001560@qq.com"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$request</span>->setUsername("chensi"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$request</span>->setPassword("123456"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* @var \Grpc\HiReply $reply
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">list</span>(<span style="color: rgba(128, 0, 128, 1)">$reply</span>, <span style="color: rgba(128, 0, 128, 1)">$status</span>) = <span style="color: rgba(128, 0, 128, 1)">$client</span>->Register(<span style="color: rgba(128, 0, 128, 1)">$request</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$message</span> = <span style="color: rgba(128, 0, 128, 1)">$reply</span>-><span style="color: rgba(0, 0, 0, 1)">getId();
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> [
</span>'id' => <span style="color: rgba(128, 0, 128, 1)">$message</span><span style="color: rgba(0, 0, 0, 1)">
];
}</span></pre>
</div>
<p> </p>
</div>
<p>重启服务,这时候然后刷新浏览器试试。这时候一个简单基于go rpc server和php client的微服务就搭建完成了。当然了这时候还没有心跳机制,hyperf官网提供了一个定时器的功能,我们定时去刷服务发现就好了。</p>
</div><br><br>
来源:https://www.cnblogs.com/a609251438/p/11811761.html
頁:
[1]