github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/docs/getting-started/README.md (about) 1 --- 2 title: Getting Started with Micro 3 keywords: micro 4 tags: [micro] 5 sidebar: home_sidebar 6 permalink: /getting-started 7 summary: A getting started guide for Micro 8 --- 9 10 ## Getting Started 11 12 This is a getting started guide for Micro which teaches you how to go from install to helloworld and beyond. 13 14 ## Contents 15 {: .no_toc } 16 17 18 * TOC 19 {:toc} 20 21 ## Dependencies 22 23 You will need protoc-gen-micro for code generation 24 25 - [protobuf](https://github.com/golang/protobuf) 26 - [protoc-gen-go](https://github.com/golang/protobuf/tree/master/protoc-gen-go) 27 - [protoc-gen-micro](https://github.com/tickoalcantara12/micro/tree/master/cmd/protoc-gen-micro) 28 29 ``` 30 # Download latest proto releaes 31 # https://github.com/protocolbuffers/protobuf/releases 32 go get github.com/golang/protobuf/protoc-gen-go 33 go get github.com/tickoalcantara12/micro/v3/cmd/protoc-gen-micro 34 ``` 35 36 ## Install 37 38 ### Go Get 39 40 Using Go: 41 42 ```sh 43 go install github.com/tickoalcantara12/micro/v3@latest 44 ``` 45 46 ### Release Binary 47 48 Or by downloading the binary 49 50 ```sh 51 # MacOS 52 curl -fsSL https://raw.githubusercontent.com/micro/micro/master/scripts/install.sh | /bin/bash 53 54 # Linux 55 wget -q https://raw.githubusercontent.com/micro/micro/master/scripts/install.sh -O - | /bin/bash 56 57 # Windows 58 powershell -Command "iwr -useb https://raw.githubusercontent.com/micro/micro/master/scripts/install.ps1 | iex" 59 ``` 60 61 ### Docker Image 62 63 ``` 64 docker pull ghcr.io/micro/micro:latest 65 ``` 66 67 ### Helm Chart 68 69 ``` 70 helm repo add micro https://micro.github.io/helm 71 helm install micro micro/micro 72 ``` 73 74 ## Running a service 75 76 Before diving into writing a service, let's run an existing one, because it's just a few commands away! 77 78 79 First, we have to start the `micro server`. The command to do that is: 80 81 ```sh 82 micro server 83 ``` 84 85 Or using docker 86 87 ``` 88 sudo docker run -p 8080:8080 -p 8081:8081 ghcr.io/micro/micro:latest server 89 ``` 90 91 Before interacting with the `micro server`, we need to log in with the username 'admin' and password 'micro': 92 93 ```sh 94 $ micro login 95 Enter username: admin 96 Enter password: 97 Successfully logged in. 98 ``` 99 100 If all goes well you'll see log output from the server listing the services as it starts them. Just to verify that everything is in order, let's see what services are running: 101 102 ```sh 103 $ micro services 104 api 105 auth 106 broker 107 config 108 events 109 network 110 proxy 111 registry 112 runtime 113 server 114 store 115 ``` 116 117 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/services](https://github.com/micro/services), we see a bunch of services written by micro authors. One of them is the `helloworld`. Try our luck, shall we? 118 119 The command to run services is `micro run`. 120 121 Simply issue the following command 122 123 ```sh 124 $ micro run github.com/micro/services/helloworld 125 ``` 126 127 Now check the status of the running service 128 129 ```sh 130 $ micro status 131 NAME VERSION SOURCE STATUS BUILD UPDATED METADATA 132 helloworld latest github.com/micro/services/helloworld running n/a 4s ago owner=admin, group=micro 133 ``` 134 135 We can also have a look at logs of the service to verify it's running. 136 137 ```sh 138 $ micro logs helloworld 139 2020-10-06 17:52:21 file=service/service.go:195 level=info Starting [service] helloworld 140 2020-10-06 17:52:21 file=grpc/grpc.go:902 level=info Server [grpc] Listening on [::]:33975 141 2020-10-06 17:52:21 file=grpc/grpc.go:732 level=info Registry [service] Registering node: helloworld-67627b23-3336-4b92-a032-09d8d13ecf95 142 ``` 143 144 So since our service is running happily, let's try to call it! That's what services are for. 145 146 ## Calling a service 147 148 We have a couple of options to call a service running on our `micro server`. 149 150 ### With the CLI 151 152 Micro auto-generates CLI commands for your service in the form: `micro [service] [method]`, with the 153 default method being "Call". Arguments can be passed as flags, hence we can call our service using: 154 155 ```sh 156 $ micro helloworld --name=Jane 157 { 158 "msg": "Hello Jane" 159 } 160 161 ``` 162 163 That worked! If we wonder what endpoints a service has we can run the following command: 164 165 ```sh 166 $ micro helloworld --help 167 NAME: 168 micro helloworld 169 170 VERSION: 171 latest 172 173 USAGE: 174 micro helloworld [command] 175 176 COMMANDS: 177 call 178 ``` 179 180 To see the flags for subcommands of `helloworld`: 181 182 ```sh 183 $ micro helloworld call --help 184 NAME: 185 micro helloworld call 186 187 USAGE: 188 micro helloworld call [flags] 189 190 FLAGS: 191 --name string 192 ``` 193 194 ### With the API 195 196 Micro exposes a http API on port 8080 so you can just curl your service like so. 197 198 ``` 199 curl "http://localhost:8080/helloworld?name=John" 200 ``` 201 202 ### With the Framework 203 204 Let's write a small client we can use to call the helloworld service. 205 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](#creating-a-service). 206 207 Let's take the following file: 208 209 ```go 210 package main 211 212 import ( 213 "context" 214 "fmt" 215 "time" 216 217 "github.com/tickoalcantara12/micro/v3/service" 218 proto "github.com/micro/services/helloworld/proto" 219 ) 220 221 func main() { 222 // create and initialise a new service 223 srv := service.New() 224 225 // create the proto client for helloworld 226 client := proto.NewHelloworldService("helloworld", srv.Client()) 227 228 // call an endpoint on the service 229 rsp, err := client.Call(context.Background(), &proto.CallRequest{ 230 Name: "John", 231 }) 232 if err != nil { 233 fmt.Println("Error calling helloworld: ", err) 234 return 235 } 236 237 // print the response 238 fmt.Println("Response: ", rsp.Message) 239 240 // let's delay the process for exiting for reasons you'll see below 241 time.Sleep(time.Second * 5) 242 } 243 ``` 244 245 Save the example locally. For ease of following this guide, name the folder `example`. 246 After doing a `cd example && go mod init example`, we are ready to run this service with `micro run`: 247 248 ``` 249 micro run . 250 ``` 251 252 `micro run`s, when successful, do not print any output. A useful command to see what is running, is `micro status`. At this point we should have two services running: 253 254 ``` 255 $ micro status 256 NAME VERSION SOURCE STATUS BUILD UPDATED METADATA 257 example latest example.tar.gz running n/a 2s ago owner=admin, group=micro 258 helloworld latest github.com/micro/services/helloworld running n/a 5m59s ago owner=admin, group=micro 259 ``` 260 261 Now, since our example service client is also running, we should be able to see it's logs: 262 ```sh 263 $ micro logs example 264 # some go build output here 265 Response: Hello John 266 ``` 267 268 Great! That response is coming straight from the helloworld service we started earlier! 269 270 ### Multi-Language Clients 271 272 Soon we'll be releasing multi language grpc generated clients to query services and use micro also. 273 274 ## Creating a service 275 276 To create a new service, use the `micro new` command. It should output something reasonably similar to the following: 277 278 ```sh 279 $ micro new helloworld 280 Creating service helloworld 281 282 . 283 ├── main.go 284 ├── handler 285 │ └── helloworld.go 286 ├── proto 287 │ └── helloworld.proto 288 ├── Makefile 289 ├── README.md 290 ├── .gitignore 291 └── go.mod 292 293 294 download protoc zip packages (protoc-$VERSION-$PLATFORM.zip) and install: 295 296 visit https://github.com/protocolbuffers/protobuf/releases 297 298 download protobuf for micro: 299 300 go get -u github.com/golang/protobuf/proto 301 go get -u github.com/golang/protobuf/protoc-gen-go 302 go get github.com/tickoalcantara12/micro/v3/cmd/protoc-gen-micro 303 304 compile the proto file helloworld.proto: 305 306 cd helloworld 307 make proto 308 ``` 309 310 As can be seen from the output above, before building the first service, the following tools must be installed: 311 * [protoc](http://google.github.io/proto-lens/installing-protoc.html) 312 * [protobuf/proto](github.com/golang/protobuf/protoc-gen-go) 313 * [protoc-gen-micro](github.com/golang/protobuf/protoc-gen-go) 314 315 They are all needed to translate proto files to actual Go code. 316 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. 317 318 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: 319 320 ```sh 321 make proto 322 ``` 323 324 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). 325 326 At this point, we know how to write a service, run it, and call other services too. 327 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. 328 329 ## Storage 330 331 Amongst many other useful built-in services Micro includes a persistent storage service for storing data. 332 333 ### With the CLI 334 335 First, let's go over the more basic store CLI commands. 336 337 To save a value, we use the write command: 338 339 ```sh 340 $ micro store write key1 val1 341 ``` 342 343 The UNIX style no output meant it was happily saved. What about reading it? 344 345 ``` 346 $ micro store read key1 347 val1 348 ``` 349 350 Or to display it in a fancier way, we can use the `--verbose` or `-v` flags. 351 352 ``` 353 $ micro store read -v key1 354 KEY VALUE EXPIRY 355 key1 val1 None 356 ``` 357 358 This view is especially useful when we use the `--prefix` or `-p` flag, which lets us search for entries which key have certain prefixes. 359 360 To demonstrate that first let's save an other value: 361 362 ``` 363 $ micro store write key2 val2 364 ``` 365 366 After this, we can list both `key1` and `key2` keys as they both share common prefixes: 367 368 ``` 369 $ micro store read --prefix --verbose key 370 KEY VALUE EXPIRY 371 key1 val1 None 372 key2 val2 None 373 ``` 374 375 There is more to the store, but this knowledge already enables us to be dangerous! 376 377 ### With the Framework 378 379 Accessing the same data we have just manipulated from our Go Micro services could not be easier. 380 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: 381 382 383 ``` 384 micro store write --table=example mykey "Hi there" 385 ``` 386 387 Let's modify [the example service we wrote previously](#calling-a-service) so instead of calling a service, it reads the above value from a store. 388 389 ```go 390 package main 391 392 import ( 393 "fmt" 394 "time" 395 396 "github.com/tickoalcantara12/micro/v3/service" 397 "github.com/tickoalcantara12/micro/v3/service/store" 398 ) 399 400 func main() { 401 srv := service.New(service.Name("example")) 402 srv.Init() 403 404 records, err := store.Read("mykey", func(r *store.ReadOptions) { 405 r.Table = "example" 406 }) 407 if err != nil { 408 fmt.Println("Error reading from store: ", err) 409 } 410 411 if len(records) == 0 { 412 fmt.Println("No records") 413 } 414 for _, record := range records { 415 fmt.Printf("key: %v, value: %v\n", record.Key, string(record.Value)) 416 } 417 418 time.Sleep(1 * time.Hour) 419 } 420 ``` 421 422 ## Updating a service 423 424 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. 425 426 We can simply issue the update command (remember to switch back to the root directory of the example service first): 427 428 ```sh 429 micro update . 430 ``` 431 432 And verify both with micro status: 433 434 ```sh 435 $ micro status example 436 NAME VERSION SOURCE STATUS BUILD UPDATED METADATA 437 example latest n/a running n/a 7s ago owner=admin, group=micro 438 ``` 439 440 that it was updated. 441 442 If things for some reason go haywire, we can try the time tested "turning it off and on again" solution and do: 443 444 ```sh 445 micro kill example 446 micro run . 447 ``` 448 449 to start with a clean slate. 450 451 So once we did update the example service, we should see the following in the logs: 452 453 ```sh 454 $ micro logs example 455 key: mykey, value: Hi there 456 ``` 457 458 ## Config 459 460 Configuration and secrets is an essential part of any production system - let's see how the Micro config works. 461 462 ### With the CLI 463 464 The most basic example of config usage is the following: 465 466 ```sh 467 $ micro config set key val 468 $ micro config get key 469 val 470 ``` 471 472 While this alone is enough for a great many use cases, for purposes of organisation, Micro also support dot notation of keys. Let's overwrite our keys set previously: 473 474 ```sh 475 $ micro config del key 476 $ micro config set key.subkey val 477 $ micro config get key.subkey 478 val 479 ``` 480 481 This is fairly straightforward, but what happens when we get `key`? 482 483 ```sh 484 $ micro config get key 485 {"subkey":"val"} 486 ``` 487 488 As it can be seen, leaf level keys will return only the value, while node level keys return the whole subtree as a JSON document: 489 490 ```sh 491 $ micro config set key.othersubkey val2 492 $ micro config get key 493 {"othersubkey":"val2","subkey":"val"} 494 ``` 495 496 ### With the Framework 497 498 Micro configs work very similarly when being called from [Go code too](https://pkg.go.dev/github.com/micro/go-micro/v3/config?tab=doc): 499 500 ```go 501 package main 502 503 import ( 504 "fmt" 505 506 "github.com/tickoalcantara12/micro/v3/service" 507 "github.com/tickoalcantara12/micro/v3/service/config" 508 ) 509 510 func main() { 511 // setup the service 512 srv := service.New(service.Name("example")) 513 srv.Init() 514 515 // read config value 516 val, _ := config.Get("key.subkey") 517 fmt.Println("Value of key.subkey: ", val.String("")) 518 } 519 ``` 520 521 Assuming the folder name for this service is still `example` (to update the existing service, [see updating a service](#updating-a-service)): 522 ``` 523 $ micro logs example 524 Value of key.subkey: val 525 ``` 526 527 ## Further Resources 528 529 This is just a brief getting started guide for quickly getting up and running with Micro. 530 Come back from time to time to learn more as this guide gets continually upgraded. If you're 531 interested in learning more Micro magic, have a look at the following sources: 532 533 - Read the [docs](../) 534 - Learn by [example](https://github.com/micro/services)