github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/docs/blog/_posts/2020-05-05-getting-started-with-microservices.md (about)

     1  ---
     2  layout:	post
     3  author: Janos Dobronszki
     4  title:	Micro Server - Getting started with microservices
     5  date:	2020-05-05 10:00:00
     6  ---
     7  <br />
     8  In this post we will have a look at how to run and manage microservices locally with `micro server` and the Micro CLI in general.
     9  The Micro CLI consists of both the server command and other client commands that enable us to interact with the server.
    10  `micro server` can run microservices in different environments - binaries locally for speed and simplicity, or containers in a more production ready environment.
    11  
    12  ## Installation
    13  
    14  Using Go:
    15  
    16  ```sh
    17  go install github.com/tickoalcantara12/micro/v2
    18  ```
    19  
    20  Or by downloading the binary
    21  
    22  ```sh
    23  # MacOS
    24  curl -fsSL https://raw.githubusercontent.com/micro/micro/master/scripts/install.sh | /bin/bash
    25  
    26  # Linux
    27  wget -q  https://raw.githubusercontent.com/micro/micro/master/scripts/install.sh -O - | /bin/bash
    28  
    29  # Windows
    30  powershell -Command "iwr -useb https://raw.githubusercontent.com/micro/micro/master/scripts/install.ps1 | iex"
    31  ```
    32  
    33  ## Running a service
    34  
    35  Before diving into writing a service, let's run an existing one, because it's just a few commands away!
    36  
    37  
    38  First, we have to start the `micro server`. The command to do that is:
    39  
    40  ```sh
    41  micro server
    42  ```
    43  
    44  To talk to this server, we just have to tell Micro CLI to address our server instead of using the default implementations - micro can work without a server too, but [more about that later](#-environments).
    45  
    46  The following command tells the CLI to talk to our server:
    47  
    48  ```
    49  micro env set server
    50  ```
    51  
    52  Great! We are ready to roll. Just to verify that everything is in order, let's see what services are running:
    53  
    54  ```
    55  $ micro list services
    56  go.micro.api
    57  go.micro.auth
    58  go.micro.bot
    59  go.micro.broker
    60  go.micro.config
    61  go.micro.debug
    62  go.micro.network
    63  go.micro.proxy
    64  go.micro.registry
    65  go.micro.router
    66  go.micro.runtime
    67  go.micro.server
    68  go.micro.web
    69  ```
    70  
    71  All those services are ones started by our `micro server`. This is pretty cool, but still it's not something we launched! Let's start a service for which existence we can actually take credit for. If we go to [github.com/micro](https://github.com/micro), we see a bunch of services written by micro authors. One of them is the `helloworld`. Try our luck, shall we?
    72  
    73  The command to run services is `micro run`. This command may take a while as it checks out
    74  the repository from GitHub. (@todo this actually fails currently, fix)
    75  
    76  ```
    77  micro run github.com/micro/helloworld
    78  ```
    79  
    80  
    81  If we take a look at the running `micro server`, we should see something like
    82  
    83  ```
    84  Creating service helloworld version latest source /tmp/github.com-micro-services/helloworld
    85  Processing create event helloworld:latest
    86  ```
    87  
    88  We can also have a look at logs of the service to verify it's running.
    89  
    90  ```sh
    91  $ micro logs helloworld
    92  Starting [service] go.micro.service.helloworld
    93  Server [grpc] Listening on [::]:36577
    94  Registry [service] Registering node: go.micro.service.helloworld-213b807a-15c2-496f-93ac-7949ad38aadf
    95  ```
    96  
    97  So since our service is running happily, let's try to call it! That's what services are for.
    98  
    99  ## Calling a service
   100  
   101  We have a couple of options to call a service running on our `micro server`.
   102  
   103  ### Calling a service from CLI
   104  
   105  The easiest is perhaps with the CLI:
   106  
   107  ```sh
   108  $ micro call go.micro.service.helloworld Helloworld.Call '{"name":"Jane"}'
   109  {
   110  	"msg": "Hello Jane"
   111  }
   112  
   113  ```
   114  
   115  That worked! If we wonder what endpoints a service has we can run the following command:
   116  
   117  ```sh
   118  micro get service go.micro.service.helloworld
   119  ```
   120  
   121  Otherwise the best place to look is at the [proto definition](https://github.com/micro/blob/master/helloworld/proto/helloworld/helloworld.proto). You can also browse to the UI at [http://localhost:8082](http://localhost:8082/service/go.micro.service.helloworld) to see live info.
   122  
   123  ### Calling a service with Go Micro
   124  
   125  Let's write a small client we can use to call the helloworld service.
   126  Normally you'll make a service call inside another service so this is just a sample of a function you may write. We'll [learn how to write a full fledged service soon](#-writing-a-service).
   127  
   128  Let's take the following file:
   129  
   130  ```go
   131  package main
   132  
   133  import (
   134  	"context"
   135  	"fmt"
   136  
   137  	"github.com/micro/go-micro/v2"
   138  	proto "github.com/micro/helloworld/proto"
   139  )
   140  
   141  func main() {
   142  	// create and initialise a new service
   143  	service := micro.NewService()
   144  	service.Init()
   145  
   146  	// create the proto client for helloworld
   147  	client := proto.NewHelloworldService("go.micro.service.helloworld", service.Client())
   148  
   149  	// call an endpoint on the service
   150  	rsp, err := client.Call(context.Background(), &proto.Request{
   151  		Name: "John",
   152  	})
   153  	if err != nil {
   154  		fmt.Println("Error calling helloworld: ", err)
   155  		return
   156  	}
   157  
   158  	// print the response
   159  	fmt.Println("Response: ", rsp.Msg)
   160  	
   161  	// let's delay the process for exiting for reasons you'll see below
   162  	time.Sleep(time.Second * 5)
   163  }
   164  ```
   165  
   166  Save the example locally. For ease of following this guide, name the folder `example-service`.
   167  After doing a `cd example-service && go mod init example`, we are ready to run this service with `micro run`:
   168  
   169  ```
   170  micro run .
   171  ```
   172  
   173  An other useful command to see what is running, is `micro status`. At this point we should have two services running:
   174  
   175  ```
   176  $ micro status
   177  NAME			VERSION	SOURCE										STATUS		BUILD	UPDATED		METADATA
   178  example-service	latest	/home/username/example-service				starting	n/a		4s ago		owner=n/a,group=n/a
   179  helloworld		latest	/tmp/github.com-micro-services/helloworld	running		n/a		6m5s ago	owner=n/a,group=n/a
   180  ```
   181  
   182  Now, since our example-service client is also running, we should be able to see it's logs:
   183  ```sh
   184  $ micro logs example-service
   185  # some go build output here
   186  Response:  Hello John
   187  ```
   188  
   189  Great! That response is coming straight from the helloworld service we started earlier!
   190  
   191  ### From other languages
   192  
   193  In the [clients repo](https://github.com/micro/clients) there are Micro clients for various languages and frameworks. They are designed to connect easily to the live Micro environment or your local one, but more about environments later.
   194  
   195  ## Writing a service
   196  
   197  To scaffold a new service, the `micro new` command can be used. It should output something
   198  reasonably similar to the following:
   199  
   200  ```sh
   201  $ micro new foobar
   202  Creating service go.micro.service.foobar in foobar
   203  
   204  .
   205  ├── main.go
   206  ├── generate.go
   207  ├── plugin.go
   208  ├── handler
   209  │   └── foobar.go
   210  ├── subscriber
   211  │   └── foobar.go
   212  ├── proto/foobar
   213  │   └── foobar.proto
   214  ├── Dockerfile
   215  ├── Makefile
   216  ├── README.md
   217  ├── .gitignore
   218  └── go.mod
   219  
   220  
   221  download protobuf for micro:
   222  
   223  brew install protobuf
   224  go get -u github.com/golang/protobuf/proto
   225  go get -u github.com/golang/protobuf/protoc-gen-go
   226  go get github.com/tickoalcantara12/micro/v2/cmd/protoc-gen-micro@master
   227  
   228  compile the proto file foobar.proto:
   229  
   230  cd foobar
   231  protoc --proto_path=.:$GOPATH/src --go_out=. --micro_out=. proto/foobar/foobar.proto
   232  ```
   233  
   234  As can be seen from the output above, before building the first service, the following tools must be installed:
   235  * [protoc](http://google.github.io/proto-lens/installing-protoc.html)
   236  * [protobuf/proto](github.com/golang/protobuf/protoc-gen-go)
   237  * [protoc-gen-micro](github.com/golang/protobuf/protoc-gen-go)
   238  
   239  They are all needed to translate proto files to actual Go code.
   240  Protos exist to provide a language agnostic way to describe service endpoints, their input and output types, and to have an efficient serialization format at hand.
   241  
   242  Currently Micro is  Go focused (apart from the [clients](#-from-other-languages) mentioned before), but this will change soon.
   243  
   244  So once all tools are installed, being inside the service root, we can issue the following command to generate the Go code from the protos:
   245  
   246  ```
   247  protoc --proto_path=.:$GOPATH/src --go_out=. --micro_out=. proto/foobar/foobar.proto
   248  ```
   249  
   250  The generated code must be committed to source control, to enable other services to import the proto when making service calls (see previous section [Calling a service](#-calling-a-service).
   251  
   252  At this point, we know how to write a service, run it, and call other services too.
   253  We have everything at our fingertips, but there are still some missing pieces to write applications. One of such pieces is the store interface, which helps with persistent data storage even without a database.
   254  
   255  ## Storage
   256  
   257  Amongst many other useful built-in services Micro includes a persistent storage service for storing data.
   258  
   259  ### Interfaces as building blocks
   260  
   261  A quick side note. Micro (the server/CLI) and Go Micro (the framework) are centered around strongly defined interfaces which are pluggable and provide an abstraction for underlying distributed systems concepts. What does this mean?
   262  
   263  Let's take our current case of the [store interface](https://github.com/micro/go-micro/blob/master/store/store.go). It's aimed to enable service writers data storage with a couple of different implementations:
   264  
   265  * in memory
   266  * file storage (default when running `micro server`)
   267  * cockroachdb
   268  
   269  Similarly, the [runtime](https://github.com/micro/go-micro/blob/master/runtime/runtime.go) interface, that allows you to run services in a completely runtime agnostic way has a few implementations:
   270  
   271  * local, which just runs actual processes - aimed at local development
   272  * kubernetes - for running containers in a highly available and distributed way
   273  
   274  This is a recurring theme across Micro interfaces. Let's take a look at the default store when running `micro server`.
   275  
   276  ### Using the Store
   277  
   278  #### Using the store with CLI
   279  
   280  First, let's go over the more basic store CLI commands.
   281  
   282  To save a value, we use the write command:
   283  
   284  ```sh
   285  micro store write key1 value1
   286  ```
   287  
   288  The UNIX style no output meant it was happily saved. What about reading it?
   289  
   290  ```
   291  $ micro store read key1
   292  val1
   293  ```
   294  
   295  Or to display it in a fancier way, we can use the `--verbose` or `-v` flags:
   296  
   297  ```
   298  KEY    VALUE   EXPIRY
   299  key1   val1    None
   300  ```
   301  
   302  This view is especially useful when we use the `--prefix` or `-p` flag, which lets us search for entries which key have certain prefixes.
   303  
   304  To demonstrate that first let's save an other value:
   305  
   306  ```
   307  micro store write key2 val2
   308  ```
   309  
   310  After this, we can list both `key1` and `key2` keys as they both share commond prefixes:
   311  
   312  ```
   313  $ micro store read --prefix --verbose key
   314  KEY    VALUE   EXPIRY
   315  key1   val1    None
   316  key2   val2    None
   317  ```
   318  
   319  There are more to the store, but this knowledge already enables us to be dangerous!
   320  
   321  #### Using the Store with Go-Micro
   322  
   323  Accessing the same data we have just manipulated from our Go Micro services could not be easier.
   324  First let's create an entry that our service can read. This time we will specify the table for the `micro store write` command too, as each service has its own table in the store:
   325  
   326  
   327  ```
   328  micro store write --table go.micro.service.example mykey "Hi there"
   329  ```
   330  
   331  Let's modify [the example service we wrote previously](#-calling-a-service-with-go-micro) so instead of calling a service, it reads the above value from a store.
   332  
   333  ```go
   334  package main
   335  
   336  import (
   337  	"fmt"
   338  	"time"
   339  
   340  	"github.com/micro/go-micro/v2"
   341  )
   342  
   343  func main() {
   344  	service := micro.NewService()
   345  
   346  	service.Init(micro.Name("go.micro.service.example"))
   347  
   348  	records, err := service.Options().Store.Read("mykey")
   349  	if err != nil {
   350  		fmt.Println("Error reading from store: ", err)
   351  	}
   352  
   353  	if len(records) == 0 {
   354  		fmt.Println("No records")
   355  	}
   356  	for _, record := range records {
   357  		fmt.Printf("key: %v, value: %v\n", record.Key, string(record.Value))
   358  	}
   359  
   360  	time.Sleep(1 * time.Hour)
   361  }
   362  
   363  ```
   364  
   365  We are almost done! But first we have to learn how to update a service.
   366  
   367  ## Updating and killing a service
   368  
   369  Now since the example service is running (can be easily verified by `micro status`), we should not use `micro run`, but rather `micro update` to deploy it.
   370  
   371  We can simply issue
   372  
   373  ```
   374  micro update .
   375  ```
   376  
   377  And verify both with the micro server output:
   378  
   379  ```
   380  Updating service example-service version latest source /home/username/example-service
   381  Processing update event example-service:latest in namespace default
   382  ```
   383  
   384  and micro status:
   385  
   386  ```
   387  $ micro status example-service
   388  NAME			VERSION	SOURCE							STATUS		BUILD	UPDATED		METADATA
   389  example-service	latest	/home/username/example-service	starting	n/a		10s ago		owner=n/a,group=n/a
   390  ```
   391  
   392  that it was updated.
   393  
   394  If things for some reason go haywire, we can try the time tested "turning it off and on again" solution and do:
   395  
   396  ```
   397  micro kill .
   398  micro run .
   399  ```
   400  
   401  to start with a clean slate.
   402  
   403  So once we did update the example service, we should see the following in the logs:
   404  
   405  ```
   406  $ micro logs example-service
   407  key: mykey, value: Hi there
   408  ```
   409  
   410  Nice! The example service read the value from the store successfully.
   411  
   412  ## Clients
   413  
   414  Beyond this we're working on multi-language clients which you can find and contribute to 
   415  on github at [github.com/micro/clients](https://github.com/micro/clients). We'd love to 
   416  discuss this further but it's not quite ready.
   417  
   418  ## Further reading
   419  
   420  This is just a brief getting started guide for quickly getting up and running with Micro. 
   421  Come back from time to time to learn more as this guide gets continually upgraded. If you're 
   422  interested in learning more Micro magic, have a look at the following sources:
   423  
   424  - Read the [docs](https://m3o.com.docs)
   425  - Learn by [examples](https://github.com/micro/examples)
   426  - Come join us on [Slack](https://slack.m3o.com) and ask quesions
   427  
   428  Cheers
   429  
   430  From the team at Micro