3.1 Introduction to Service Governance
With the actions in the previous chapter, we can already make calls between micro services.But we take the network address of the service provider
- Once the service provider address changes, you need to modify the code manually
- Once multiple service providers are present, load balancing cannot be achieved
- As micro-services become more and more numerous, it is difficult to maintain call relationships manually
- Service registration: In the framework of service governance, a registry is built, and each service unit registers with the registry the details of its services.And form a list of services in the registry. The service registry needs to monitor the availability of services in the list in a heartbeat way. If not, it needs to exclude the unavailable services from the list.
- Service discovery: A service invokes a service consulting service with the service registry and obtains a list of instances of all services to access a specific service instance.
- Service registration: Save information about service providers and service callers
- Service subscription: A service caller subscribes to information from a service provider, and the registry pushes information from the provider to the subscriber
- Configuring subscriptions: Service providers and service callers subscribe to microservice-related configurations
- Configuration Download: Actively push configuration to service providers and service callers
- Detect the health of service providers and perform service culling if exceptions are found
- Zookeeper
- Eureka
- Consul
- Nacos
Introduction to 3.2 nacos
3.3 Introduction to Nacos
3.3.1 Setting up a nacos environment
Double-click startup.cmd to start nacos
Step 3: Visit nacos
3.3.2 Register commodity microservices with nacos
spring: cloud: nacos: discovery: server-addr: 127.0.0.1:8848
3.3.3 Register order microservices with nacos
spring: cloud: nacos: discovery: server-addr: 127.0.0.1:8848
package com.itheima.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import com.alibaba.fastjson.JSON; import com.itheima.entity.Order; import com.itheima.entity.Product; import com.itheima.service.OrderService; @RestController @Slf4j public class OrderController { @Autowired private RestTemplate restTemplate; @Autowired private DiscoveryClient discoveryClient; @Autowired private OrderService orderService; //Ready to buy one item @GetMapping("/order/prod/{pid}") public Order order(@PathVariable("pid") Integer pid) { //Get service address from nacos ServiceInstance serviceInstance = discoveryClient.getInstances("service-product").get(0); String url = serviceInstance.getHost() + ":" + serviceInstance.getPort(); //Calling commodity microservices through restTemplate Product product = restTemplate.getForObject( "http://" + url +"/product/" + pid, Product.class); log.info(">>Commodity Information,Query Results:" + JSON.toJSONString(product)); Order order = new Order(); order.setUid(1); order.setUsername("Test User"); order.setPid(product.getPid()); order.setPname(product.getPname()); order.setPprice(product.getPprice()); order.setNumber(1); orderService.save(order); return order; } }
6 Then the call succeeds by accessing the consumer service validation
3.4 Implement load balancing for service calls
3.4.1 What is load balancing
In a microservice invocation relationship, we generally choose client load balancing, that is, when one side of a service invocation decides which provider the service is to be executed by.
3.4.2 Customize Load Balancing
2 View microservice startup via nacos
You can also view service details
3 Modify the shop-order code to achieve load balancing (we use random numbers to achieve load balancing ourselves)
package com.itheima.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import com.alibaba.fastjson.JSON; import com.itheima.entity.Order; import com.itheima.entity.Product; import com.itheima.service.OrderService; import java.util.List; import java.util.Random; @RestController @Slf4j public class OrderController { @Autowired private RestTemplate restTemplate; @Autowired private DiscoveryClient discoveryClient; @Autowired private OrderService orderService; //Ready to buy one item @GetMapping("/order/prod/{pid}") public Order order(@PathVariable("pid") Integer pid) { // Get service address from nacos // Custom Rules Implement Random Selection Service List<ServiceInstance> instances = discoveryClient.getInstances("service-product"); int index = new Random().nextInt(instances.size()); ServiceInstance serviceInstance = instances.get(index); String url = serviceInstance.getHost() + ":" + serviceInstance.getPort(); log.info(">>from nacos The microservice address obtained in is:" + url); //Calling commodity microservices through restTemplate Product product = restTemplate.getForObject( "http://" + url +"/product/" + pid, Product.class); log.info(">>Commodity Information,Query Results:" + JSON.toJSONString(product)); Order order = new Order(); order.setUid(1); order.setUsername("Test User"); order.setPid(product.getPid()); order.setPname(product.getPname()); order.setPprice(product.getPprice()); order.setNumber(1); orderService.save(order); return order; } }
3.4.3 Load Balancing Based on Ribbon
package com.itheima.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import com.alibaba.fastjson.JSON; import com.itheima.entity.Order; import com.itheima.entity.Product; import com.itheima.service.OrderService; import java.util.List; import java.util.Random; @RestController @Slf4j public class OrderController { @Autowired private RestTemplate restTemplate; @Autowired private OrderService orderService; @GetMapping("/order/prod/{pid}") public Order order(@PathVariable("pid") Integer pid) { //Get the service address from nacos by using the microservice name directly String url = "service-product"; //Calling commodity microservices through restTemplate Product product = restTemplate.getForObject( "http://" + url +"/product/" + pid, Product.class); log.info(">>Commodity Information,Query Results:" + JSON.toJSONString(product)); Order order = new Order(); order.setUid(1); order.setUsername("Test User"); order.setPid(product.getPid()); order.setPname(product.getPname()); order.setPprice(product.getPprice()); order.setNumber(1); orderService.save(order); return order; } }
We can adjust Ribbon's load balancing strategy by modifying the configuration as follows
service-product: # Name of the provider invoked ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
3.5 Feign-based implementation of service calls
3.5.1 What is Feign
Use of 3.5.2 Feign
2 Add Fegin's comment on the main class
package com.itheima.service; import com.itheima.entity.Product; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient("service-product") //Declare the provider name of the call public interface ProductService { // Specify which method to invoke the provider // @FeignClient+@GetMapping is a complete request pathhttp://service- Product/product/{pid} @GetMapping(value = "/product/{pid}") Product findByPid(@PathVariable("pid") Integer pid); }
package com.itheima.controller; import com.itheima.service.ProductService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import com.alibaba.fastjson.JSON; import com.itheima.entity.Order; import com.itheima.entity.Product; import com.itheima.service.OrderService; import java.util.List; import java.util.Random; @RestController @Slf4j public class OrderController { @Autowired private OrderService orderService; @Autowired private ProductService productService; @GetMapping("/order/prod/{pid}") public Order order(@PathVariable("pid") Integer pid) { //Calling commodity microservices through fegin Product product = productService.findByPid(pid); log.info(">>Commodity Information,Query Results:" + JSON.toJSONString(product)); Order order = new Order(); order.setUid(1); order.setUsername("Test User"); order.setPid(product.getPid()); order.setPname(product.getPname()); order.setPprice(product.getPprice()); order.setNumber(1); orderService.save(order); return order; } }
5 Restart order micro-service to see the effect