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