1. Introduction to springcloud
1.1 INTRODUCTION
spring cloud is a collection of frameworks. Taking advantage of the development convenience of spring boot, it cleverly simplifies the development of distributed system infrastructure, such as service discovery and registration, configuration center, message bus, load balancing, circuit breaker, data monitoring, etc., which can be started and deployed with one click with the development style of spring boot. spring cloud does not repeatedly manufacture wheels. It just combines the relatively mature and practical service frameworks developed by various companies, repackages them through the spring boot style, shields the complex configuration and implementation principles, and finally leaves a set of distributed system development kit that is easy to understand, deploy and maintain for developers.
Spring cloud is a blessing for small and medium-sized Internet companies, because such companies often do not have the strength or sufficient capital investment to develop their own distributed system infrastructure. Using spring cloud one-stop solution can not only calmly deal with business development, but also greatly reduce development costs. At the same time, with the popularity of microservice architecture and docker container concept in recent years, spring cloud will also have a place in the future more and more "cloud" software development style. In particular, it provides standardized and one-stop technical solutions in the current variety of distributed solutions, which may be as meaningful as the birth of servlet specification in that year, Effectively promote the progress of the technical level of the server software system.
1.2 technical composition
Insert picture description here
explain:
eureka microservice governance, service registration and discovery
ribbon load balancing, request retry
hystrix circuit breaker, service degradation, fusing
feign ribbon + hystrix integration and declarative client
hystrix dashboard and turbine hystrix data monitoring
zuul API gateway provides a unified entrance to microservices and unified permission verification
config configuration center
Bus message bus, configuration refresh
sleuth+zipkin link tracking
2. Microservice architecture
2.1 Spring Cloud vs. Dubbo
! [insert picture description here]( https://img-blog.csdnimg.cn/a5950a6672a445c4ab73c7683285c566.png?x-oss-process=image/watermark,t
ype_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAbHlkb244ODg=,size_20,color_FFFFFF,t_70,g_se,x_16)
2.2 service microservice invocation process
3. Project code
3.1 service creation process
1. Create project
2. Configuration dependency
Make a series of corresponding configurations in the pom.xml file
Parent project dependency (Description: automatically generated after the project is created)
3. Configure writing source files
4. Write goods and services
ItemServiceImpl
ItemController
Access test
3.2 common items
1.pom.xml
<dependencies> <dependency> <groupId>com.fasterxml.jackson.module</groupId> <artifactId>jackson-module-parameter-names</artifactId> <version>2.9.8</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jdk8</artifactId> <version>2.9.8</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> <version>2.9.8</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-guava</artifactId> <version>2.9.8</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.6</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.26</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.9</version> </dependency> </dependencies>
explain:
2. Project structure (same as above)
3.util layer
cookieutil
public class CookieUtil { /** * @param response * @param name * @param value * @param maxAge */ public static void setCookie(HttpServletResponse response, String name, String value, String domain, String path, int maxAge) { Cookie cookie = new Cookie(name, value); if (domain != null) { cookie.setDomain(domain); } cookie.setPath(path); cookie.setMaxAge(maxAge); response.addCookie(cookie); } public static void setCookie(HttpServletResponse response, String name, String value, int maxAge) { setCookie(response, name, value, null, "/", maxAge); } public static void setCookie(HttpServletResponse response, String name, String value) { setCookie(response, name, value, null, "/", 3600); } public static void setCookie(HttpServletResponse response, String name) { setCookie(response, name, "", null, "/", 3600); } /** * @param request * @param name * @return */ public static String getCookie(HttpServletRequest request, String name) { String value = null; Cookie[] cookies = request.getCookies(); if (null != cookies) { for (Cookie cookie : cookies) { if (cookie.getName().equals(name)) { value = cookie.getValue(); } } } return value; } /** * @param response * @param name * @return */ public static void removeCookie(HttpServletResponse response, String name, String domain, String path) { setCookie(response, name, "", domain, path, 0);
jsonresult
@Getter @Setter public class JsonResult<T> { /** success */ public static final int SUCCESS = 200; /** not logged on */ public static final int NOT_LOGIN = 400; /** exception occurred */ public static final int EXCEPTION = 401; /** System error */ public static final int SYS_ERROR = 402; /** Parameter error */ public static final int PARAMS_ERROR = 403; /** Unsupported or obsolete */ public static final int NOT_SUPPORTED = 410; /** AuthCode error */ public static final int INVALID_AUTHCODE = 444; /** Too frequent calls */ public static final int TOO_FREQUENT = 445; /** unknown error */ public static final int UNKNOWN_ERROR = 499; private int code; private String msg; private T data; public static JsonResult build() { return new JsonResult(); } public static JsonResult build(int code) { return new JsonResult().code(code); } public static JsonResult build(int code, String msg) { return new JsonResult<String>().code(code).msg(msg); } public static <T> JsonResult<T> build(int code, T data) { return new JsonResult<T>().code(code).data(data); } public static <T> JsonResult<T> build(int code, String msg, T data) { return new JsonResult<T>().code(code).msg(msg).data(data); } public JsonResult<T> code(int code) { this.code = code; return this; } public JsonResult<T> msg(String msg) { this.msg = msg; return this; } public JsonResult<T> data(T data) { this.data = data; return this; } public static JsonResult ok() { return build(SUCCESS); } public static JsonResult ok(String msg) { return build(SUCCESS, msg); } public static <T> JsonResult<T> ok(T data) { return build(SUCCESS, data); } public static JsonResult err() { return build(EXCEPTION); } public static JsonResult err(String msg) { return build(EXCEPTION, msg); } @Override public String toString() { return JsonUtil.to(this); } }
4. Test
3.3 item service
1.pom.xml
<dependency> <groupId>com.lydon</groupId> <artifactId>sp01-commons1</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
2. Project structure
ItemserviceImpl
@Slf4j @Service public class ItemServiceImpl implements ItemService { @Override public List<Item> getItems(String orderId) { log.info("Get goods,orderId="+orderId); List<Item> items=new ArrayList<>(); items.add(new Item(1,"Commodity 1",1)); items.add(new Item(2,"Commodity 2",5)); items.add(new Item(3,"Commodity 3",2)); items.add(new Item(4,"Commodity 4",3)); items.add(new Item(5,"Commodity 5",4)); return items; } @Override public void decreaseNumbers(List<Item> items) { for (Item item : items){ log.info("reduce stock:"+item); } } }
ItemController
@RestController @Slf4j public class ItemController { @Autowired private ItemService itemService; @GetMapping("/{orderId}") public JsonResult<List<Item>> getItems( @PathVariable String orderId) throws InterruptedException { List<Item> items=itemService.getItems(orderId); //Random blocking if(Math.random()<0.9){ //Random extension duration, 0 ~ 5 seconds int t=new Random().nextInt(5000); log.info("delay"+t); Thread.sleep(t); } return JsonResult.ok().data(items); } //Testing post requests with postman @PostMapping("/decreaseNumber") public JsonResult<?>decreaseNumber( @RequestBody List<Item> items){ itemService.decreaseNumbers(items); return JsonResult.ok().msg("Self increasing"); }
3.application.yml
spring: application: name: item-service #Registry name #item 8001 #user 8181 #order 8201 server: port: 8001 eureka: client: service-url: defaultZone: http://eureka1:2001/eureka
4. Test
3.4 user service
1.pom.xml
<dependency> <groupId>com.lydon</groupId> <artifactId>sp01-commons1</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
2. Project structure
ItemserviceImpl
@Service @Slf4j public class UserServiceImpl implements UserService { @Value("${sp.user-service.users}") private String userJson; @Override public User getUser(Integer userId) { //userJson-->List<User> List<User> list = JsonUtil.from( userJson, new TypeReference<List<User>>() {}); for (User u:list){ if(u.getId().equals(userId)){ return u; } } return new User (userId,"user name="+userId,"password="+userId); } @Override public void addScore(Integer userId, Integer score) { log.info("Increase user points","userId="+userId,"score="+score); } }
ItemController
@RestController @Slf4j public class UserController { @Autowired private UserService userService; @GetMapping("/{userId}") public JsonResult<User> getUser(@PathVariable Integer userId) { User user = userService.getUser(userId); return JsonResult.ok().data(user); } // /8/score?score=1000 @GetMapping("/{userId}/score") public JsonResult<?> addScore(@PathVariable Integer userId, Integer score) { userService.addScore(userId, score); return JsonResult.ok().msg("Points increased successfully!"); } @GetMapping("/favicon.ico") public void ico(){} }
3.application.yml
sp: user-service: users: "[{\"id\":7, \"username\":\"abc\",\"password\":\"123\"}, {\"id\":8, \"username\":\"def\",\"password\":\"456\"}, {\"id\":9, \"username\":\"ghi\",\"password\":\"789\"}]" spring: application: name: user-service server: port: 8101 eureka: client: service-url: defaultZone: http://eureka1:2001/eureka
4. Test
3.5 order service
1.pom.xml
<dependency> <groupId>com.lydon</groupId> <artifactId>sp01-commons1</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> <version>1.4.2.RELEASE</version> </dependency>
2. Project structure
ItemserviceImpl
@Slf4j @Service public class OrderServiceImpl implements OrderService { @Autowired private ItemClient itemClient; @Autowired private UserClient userClient; @Override public Order getOrder(String orderId) { log.info("Get order,orderId="+orderId); // Remotely call the product to get the product list JsonResult<List<Item>> items = itemClient.getItems(orderId); //TODO: call item service to get product information //Remotely call the product to obtain the user list JsonResult<User> user = userClient.getUser(8);//In a real project, you want to get the login user information Order order = new Order(); order.setId(String.valueOf(user.getData())); order.setItems(items.getData()); return order; } @Override public void addOrder(Order order) { //log.info("save order:" + order); log.info("Add order: "+order); //TODO: call item service to reduce commodity inventory //TODO: call user service to increase user points //TODO: call commodities remotely to reduce inventory itemClient.decreaseNumber(order.getItems()); //TODO: call users remotely to increase points userClient.addScore(order.getUser().getId(),1000); } }
ItemController
@Slf4j @RestController public class OrderController { @Autowired private OrderService orderService; @GetMapping("/{orderId}") public JsonResult<Order> getOrder(@PathVariable String orderId) { log.info("get order, id="+orderId); // TODO: call commodities remotely to obtain commodity list // TODO: call the user remotely to obtain user data Order order = orderService.getOrder(orderId); return JsonResult.ok(order); } @GetMapping("/add") public JsonResult addOrder() { //Simulate data submitted by post Order order = new Order(); order.setId("saf1234"); order.setUser(new User(8,null,null)); order.setItems(Arrays.asList(new Item[] { new Item(1,"aaa",2), new Item(2,"bbb",1), new Item(3,"ccc",3), new Item(4,"ddd",1), new Item(5,"eee",5), })); orderService.addOrder(order); return JsonResult.ok().msg("Order added successfully~~"); } @GetMapping("/favicon.ico") public void ico(){ } }
3.application.yml
spring: application: name: order-service server: port: 8201 #Client application request address: / eureka sub path #View erueka console address with browser:/ #defaultZone: if you use cloud services, you can purchase servers in non-stop locations, #Your own server must be defaultZone eureka: client: service-url: defaultZone: http://eureka1:2001/eureka,http://eureka2:2002/eureka
4. Test
3.6 service access test summary
1. item-service
Query the goods according to orderid: http://localhost:3001/item-service/
Reduce commodity inventory: http://localhost:8001/decreaseNumber
2.user-service
Query user information according to userid: http://localhost:8101/7
Add points for users according to userid: http://localhost:8101/7/score?score=100
3.order-service
According to orderid, get the order: http://localhost:8201/123abc
Save the order and observe the console log output: http://localhost:8201/
4. Summary
This chapter briefly studies the implementation of some basic services of microservices, and briefly introduces the use of eureka. Through eureka, network companies can easily obtain or manage various services. Its role is similar to that of nacos, but its use has a greater amount of concurrency. The specific implementation will be introduced later.