This session will focus on the evolution of the architecture, the advantages and disadvantages of the microservices architecture, and the Ribbon and Feign components

Architecture evolution

The development course of architecture corresponds to the development of business requirements, such as the increase of system access brought by the Internet, and the higher requirements of decoupling put forward by the agile development mode and enterprise cooperation development mode

Architecture serves business, so choosing an appropriate architecture makes our development responsibilities clear and boundaries clear, but excessive design of architecture will bring unnecessary trouble. We learn microservices to understand its advantages and disadvantages, and use them in the most suitable business scenarios instead of using microservices for the sake of using microservices

Technology is updated, ideas are updated quickly. Grasp the idea of architecture upgrade, that is, adapt to the business scenario, and choose the most suitable architecture for the future development of the business

Servlet

Let’s start with the first project, the Servlet project, which is what JavaWeb looks like stripped of layers of encapsulation. Create class, and implement Servlet interface to implement class enhancement, rewrite Servlet five life cycle, to complete a JavaWeb

In the servlet approach we can even write database interactions, data processing, and even HTML pages together,

  • Disadvantages: strong coupling, no stratification,
  • Pros: Simple enough, complete control

Simplicity here is not what SpringBoot calls simplicity, which means that we can control all the details of the project. SpringBoot uses Starter to introduce dependencies, uses convention over configuration, writes configuration classes for us, and provides a large number of default configurations to achieve out of the box.

That is, beans have been injected for us to use, and if you want to customize them for your project, you need to rewrite the beans or peruse the configuration items provided by each application.yML

As we often use MyBatis, if not with Spring, as shown in the figure

Single MVC stage

For servlet encapsulation, code stratification, representative framework SpringMVC, core class DispatchServlet responsible for the unified distribution of requests,handler processing, the final view of the return, the business logic layer, data access layer, presentation layer division

Although the software structure is divided, business scenarios are not divided. A typical scenario is to put MVC of various business scenarios in a project, compile, package and deploy it on a server, as shown in the figure

  • Advantages: Fast development, clear structure and easy deployment in the early stage of the project
  • Disadvantages: As the business gradually complex
  1. More and more single code, readability, maintainability, scalability decline
  2. Individual projects run on the same JVM, and with business complexity, user growth, performance degradation, and vertical scaling costs are huge
  3. Pull a start the whole body, individual bugs, resulting in the entire system can not operate
  4. As individual WAR packages become larger, the compilation and deployment time increases

In the later stage of springMVC, some vertical split will be made, that is, the system that has no business connection will be split to form an independent system that provides services externally. At this time, the services are independent and RPC is carried out all the time. Many basic codes cannot be reused and must be copied and used

Or change the application server to the application server cluster, through nginx reverse proxy + load balancing on the server, add cache service, mysql read and write separation to improve performance, but still does not change the single application itself is difficult to expand and maintain the problem.

However, if the business relationship is very close, will not be large-scale expansion of the system, using SpringBoot development as a single application, it is very suitable

SOA practices – Microservices

Microservices architecture is an application system based on a large monolithic system divided into a set of reusable services. On the left is an early monolithic application architecture, in which modules call and couple with each other, and all the systems and modules are packaged together to form a giant system. On the right is the microservices architecture, which breaks down services based on their granularity and level of reuse to provide external service calls as independently deployed services. According to different uses and scenarios, application systems rely on these reusable services for logical combination to build their own business systems.

In this way, the system becomes relatively simple, and the reuse level is relatively high. At the same time, it also solves several important problems of the single giant mentioned above. Because the code for each service or application system is relatively simple, compiling and deploying, developing and testing are relatively simple and fast. Moreover, these services are independently maintained and deployed, and their code branches are also independent and not managed together with other code branches, reducing the possibility of code conflicts. When released, each service is released independently. As long as the version control and interface compatibility of the service are well done, the application system does not need to be updated and released with the service.

In the microservice system, the specific service is connected to the database, and the application system does not need to connect to the database itself, but only needs to call the composite service and arrange the service. So there are fewer connections to the database than before. The most important thing is that when new business needs to be developed, it does not need to carry out various reconstructions and code modifications on the original single system in this way. Instead, it only needs to develop a new business system and combine and call the existing micro-services, so that a new product function can be combined and new products can be developed quickly.

  1. First as a business scenario micro service should be how to divide, is a clear boundary, how dependencies between services, this determines the degree of a micro service reuse, the convenience degree of the development, so the transition with a business first incognito, clarify dependencies and boundary, design good coupling relationship, less dependent on clear module, can build a good micro service system If the module itself is chaotic and seriously coupled, disassembling it into a microservice architecture is to make things more complicated
  2. Unlike other technologies, microservices have strong business attributes. If the business itself is disorganized, its goals are not clear, and the hasty use of microservices may make the whole system more complex and difficult to control. Therefore, before using microservices, the most important thing is to first clarify their own needs: what do we want to achieve with microservices? Once the requirements are clear, consider specific solutions and technologies. This is how most technologies should be used. When using microservices architecture, it is important to understand the purpose of implementing microservices. Is it for business reuse, clear development boundaries, distributed cluster performance, or simply using microservices? Be clear about your purpose.

Disadvantages of microservices architecture

  1. The architecture is complex and the components are numerous
  2. Distributed transactions, not ACID transaction control like a stand-alone system, can only choose AP or CP,CAP–BASE

  1. How to divide modules with clear boundaries and low coupling?

  2. Deployment is complex and requires learning the DevOps fully automated deployment stack

  3. Propagation of failures (avalanches) If a service has an exception or network error, continuing to invoke the service instance while its response latency or failure rate increases can cause requesters to block. Blocked requests lead to increased resource consumption, which may eventually lead to requesters failing and crashing, leading to cascading crashes of services, in which requesters of service requesters fail, and finally the entire system fails, which is an avalanche. Hystrix can be used in Spring Cloud to implement circuit breakers and fail-fast mechanisms for services to prevent further spread of failures and automatically recover when conditions recover.

Component sharing

Spring-Boot-starter-actuator+Springboot admin

SpringBoot Actuator+SpringBoot Admin

The starter+ configuration is the standard springBoot configuration

1. Introduce dependencies

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> < version > 2.2.6. RELEASE < / version > < / dependency >Copy the code

2. Application. Yml configuration

Build: artifact: "@project.artifactid @" name: "@project.name@" version: "@project.version@" # Expose all endpoints management: endpoints: web: exposure: include: "*" Always # Remote shutdown: enabled: trueCopy the code

Once configured, we can view the parent context of the current application in IDEA, and see the beans and dependencies in it

You can also access the /actuator using web pages

In the gateway, you can initiate GET on endpoints in the actuator/gateway/routes to obtain all the routing information configured on the current gateway

Next, springboot-Admin can monitor all kinds of information of the micro-services that we register with it in real time. In fact, most of the information is the visualized information of the actuator that we just mentioned

We have just talked about two common communication methods for microservices, RPC-based Dubbo and HTTP-based SpringCloud. Today we share two HTTP-based web request frameworks in SpringCloud, Ribbon, and Dubbo, which we use in demos and applications learning

RestTemplate

RestTemplate is a network request framework in Spring that accesses third-party Restful apis. It is designed to provide a simple way to perform complex behavior, similar to other Spring Templates such as JdbcTemplate and JmsTemplate

RestTemplate is used to consume RestFul services, so the main methods of RestTemplate are closely related to Rest methods, such as GET,POST, and PUT corresponding to getForObject(),postForObject(), PUT (), and delete(). ) etc.

Used alone (example in Microservice-01)

  1. Injection of Bean
/** * Spring Boot version 1.4 no longer provides RestTemplate * Defines a RestTemplateBuilder that allows you to have more control over the objects created by the RestTemplate. * You can RestTemplateBuilder in your@BeanMethod to create a RestTemplate: *@author zhaoxu
 */
@Configuration
public class RestTemplateConfig {

    @Resource
    RestTemplateBuilder restTemplateBuilder;

    @Bean(name = "restTemplate")
    public RestTemplate getRestTemplate(a) {
        returnrestTemplateBuilder.build(); }}Copy the code
  1. The declared good Bean injection use, here to get baidu home PAGE HTML code
/** * RestTemplateController RestTemplate example used alone Controller *@author zhaoxu
 */
@RestController
public class RestTemplateController {

    @Resource
    RestTemplate restTemplate;

    @GetMapping("/baidu")
    public String getBaiduJson(a) {
        return  restTemplate.getForObject("https://www.baidu.com",String.class); }}Copy the code
  1. test

RestTemplate with Ribbon for load balancing and ZK for registry (Ribbon consumer client)

  1. Introduction of the Ribbon starter
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
Copy the code
  1. Add the @loadBalanced annotation to the standalone base
@Configuration
public class RestTemplateConfig {

    @Resource
    RestTemplateBuilder restTemplateBuilder;

    @LoadBalanced
    @Bean(name = "restTemplate")
    public RestTemplate getRestTemplate(a) {
        returnrestTemplateBuilder.build(); }}Copy the code
  1. If discovery and instant-host are configured, then address will display the name of instance-host configuration, and the hosts configuration can be accessed
Spring: Cloud: Zookeeper: #home connect-string: 192.168.50.75:2181 Discovery: root: /topsec/services instance-host: asset-manageCopy the code

     @Resource
    RestTemplate restTemplate;

    /** * Load balancing with zK,ribbon+RestTemplate registry */
    @GetMapping("/microserviceinfo")
    public String getMicroServiceActuatorInfo (a) {
        return restTemplate.getForObject("http://microservice/actuator/info",String.class);
    }


Copy the code

Ribbon

There are two approaches to load balancing

As a load balancing component, the Ribbon encapsulates the load balancing logic in code form to the client of the service consumer. That is, the Ribbon’s load balancing logic is written in the caller’s code. When configuring routes in the Gateway, the Ribbon also uses LB to start ne tflix ribbon

The service consumer client maintains a list of service providers. The Ribbon uses a load balancing policy to spread the load balancing logic across multiple providers. The Ribbon uses client load balancing to encapsulate the load balancing logic within the client processes

Native RibbonApi

We can also use the Ribbon without using any framework. Here, we use the Ribbon native API to maintain two service lists by ourselves, and use random load balancing to call them 30 times to check the results

/** * Ribbon native Api *@author zhaoxu
 */
public class RibbonNativeClientDemo {
    public static void main(String[] args) {
        // List of services
        List<Server> serverList = Arrays.asList(new Server("baidu.com".8081),new Server("google.com".8082));
        // Build the load instance
        BaseLoadBalancer loadBalancer = LoadBalancerBuilder.newBuilder().buildFixedServerListLoadBalancer(serverList);
        loadBalancer.setRule(new RandomRule());
        // Repeat the call to see the effect


        for (int i = 0; i <30 ; i++) {
            String result =LoadBalancerCommand.builder().withLoadBalancer(loadBalancer).build().submit(new ServerOperation<Object>() {
                @Override
                public Observable<Object> call(Server server) {
                    String addr = server.getHost()+":"+server.getPort();
                    System.out.println("Call address"+addr);
                    return Observable.just(""); } }).toBlocking().first().toString(); }}}Copy the code

Seeing that the results are randomly distributed, calls are made to the two nodes we maintain

The Ribbon only combines ZK pull service registry information

 /** * Use the Ribbon alone, not the RestTemplate, to pull registration information from zK for load balancing */
    @GetMapping("/testRibbon")
    public String testRibbon (a) {
        ServiceInstance serviceInstance =loadBalancerClient.choose("microservice");
        return serviceInstance.getHost()+":"+serviceInstance.getPort();
    }

Copy the code

Ribbon combined RestTemplate

We talked about this in RestTemplate, adding an @loadBalanced annotation. Let’s talk about how we can change the load balancing policy when we combine with RestTemplate, customize the Bean, return the new policy, and we can also implement the IRule interface to implement our own policy

/** * Modify the ribbon's strategy *@author zhaoxu
 */
@Configuration
public class RibbonConfig {


    @Bean
    public IRule ribbonRule(a){
        // Random policy, a load balancing policy that randomly distributes traffic among existing servers.
        //return new RandomRule();
        Tripped "circuit breaker and picked the
        // * server with lowest concurrent requests.
        //return new BestAvailableRule();
        // The most well known and basic load balancing strategy, i.e. Round Robin Rule.
        //return new RoundRobinRule();
        // By default, retry based on polling. Cascading policies can be passed to other policies
        return new RetryRule(new RandomRule(),300);
        // Assign a weight based on the response time. The lower the weight, the less likely it is to be selected
        //return new WeightedResponseTimeRule();
        // Poll the selection based on the server zone zone and availability
        //return new ZoneAvoidanceRule();}}Copy the code

With so many strategies on offer, let’s take a look at each one

Feign

Feign is a pseudo JavaHTTP client. Feign does not do any Request processing. It uses annotations to generate Request templates to simplify the development of HTTPAPi St, to the JavaHttp client to handle The client component sent to Feign is the component that sends Request and receives Response requests. The client is an interface in Feign, which is HttpUrlConnnction by default. It can also be replaced with other Http frameworks, such as HttpClien T and OkHttp take advantage of this approach, allowing developers to focus only on developing Feign annotation templates and not on the Http request itself

In Feign, you can call remote Http apis by defining the API interface. When defining the call Client, you need to add some annotations to describe the basic information of the call API, such as the request type is GET or POST, and what the REQUEST URI is. Contract allows users to customize contracts to parse annotation information. The most typical application scenario is using Feign in Spring Cloud. We can use Spring MVC annotations to define Feign clients. This is because Spring Cloud OpenFeign implements its own Spring MVCContract.

Encoder coding component

Through this component, we can encode and transmit the request information in a specified encoding mode.

Decoder Decoder component

Decoder decodes the corresponding data into objects.

Client requests the execution component

The Client is responsible for the execution of HTTP requests. Feign sends the request information to the Client after encapsulation. The default Client in Feign uses HttpURLConnection in JDK to initiate requests. Will create new HttpURLConnection links. Using the default method, Feign performance will be poor because HttpURLConnection is used. You can extend this interface to use a high-performance connection pool-based HTTP client such as Apache HttpClient.

Feign native Api

Like the Ribbon, you can also use Feign without using any framework, so it’s just an Http framework

/ * * *@author zhaoxu
 */
public class FeignApiDemo {
    public static void main(String[] args) {
        MicroService microService = Feign.builder().
                decoder(new GsonDecoder())
                .target(MicroService.class,"http://127.0.0.1:8763/"); System.out.print(microService.getActuatorInfoFromMicroService()); }}/** * Internal interface *@author zhaoxu
 */
interface MicroService {
    @RequestLine("GET /actuator/info")
    JsonObject getActuatorInfoFromMicroService(a);

}

Copy the code

Feign combined with Ribbon

Native Feign was already easy to use, but it wasn’t so easy to use in The Spring Cloud architecture, so the official team expanded on Feign and launched Spring-Cloud-OpenFeign. The goal is to make it easier for developers to use Feign in the Spring Cloud.

First of all, we develop apis using Spring MVC annotations, such as RequestMapping. Feign annotations are a separate set, so when we write and call Client interfaces, we need to write according to the existing interface. In Spring-Cloud-OpenFeign, a set of spring MVC annotations are implemented. The annotations in the Client interface of the caller can be consistent with the API side, which is very convenient.

This is one of the most common and convenient combinations in our development, and will be introduced at the end. The integration method is as follows

  1. Again, introducing dependencies, one for feign’s starter, one for Feign’s encoder, decoder, etc
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <! -- https://mvnrepository.com/artifact/io.github.openfeign/feign-gson --> <dependency> < the groupId > IO. Making. Openfeign < / groupId > < artifactId > feign - gson < / artifactId > < version > 11.0 < / version > < / dependency >Copy the code

If you click on Spring-cloud-starter-OpenFeign, feig’s Start already integrates ribbon and Hystrix fuse dependencies

2. Configure the @enableFeignClients primary startup class to enable packet scanning for interfaces annotated by @Feign

/ * * *@author zhaoxu
 */
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class FeignClientApplication {

    public static void main(String[] args) { SpringApplication.run(FeignClientApplication.class, args); }}Copy the code
  1. Write an @feignClient modified interface

Here value is the service name, and @getMapping writes the interface of the remote service

/ * * *@author zhaoxu
 */
@FeignClient(value = "microservice")
public interface IMicroService {

    @GetMapping(value = "/actuator/info")
    String getActuatorInfoFromMicroService(a);
}

Copy the code
  1. Use the injection interface, which is used directly as if calling native methods, and load balancing has been automatically integrated
/ * * *@author zhaoxu
 */
@RestController
public class FeignTestController {

    @Resource
    IMicroService microService;

    @GetMapping("/microserviceinfo")
    public String getMicroServiceInfo (a) {
        returnmicroService.getActuatorInfoFromMicroService(); }}Copy the code
  1. We can also make some configurations, such as declare the FeignConfig configuration class, configure timeout reconnection, or declare the RibbonConfig class, modify the load balancing policy, etc.

RPC call to dubbo

Mature microservice frameworks and RPC methods, such as dubbo framework, have also passed the test of large volumes of business, but also to learn, convenient in the most suitable business, choose the most suitable framework

Making remote calls in Dubbo does not require the consumer to pay attention to the service provider information, injecting an interface and then calling the methods in the interface as if they were local methods. The benefits are high development efficiency and elegant code. Let’s look at a native Duboo demo, configured as an XML annotation. Here we introduce minimal dependencies, only spring-Context containers, Dubbo dependencies, and several core packages that encapsulate NIO’s Netty

Microservice invocation in applications

1. The way of feign The required configuration has nothing to do with the server, which is one of Feign’s strengths, since it is a pseudo-HTTP call framework. So we look at the service provider’s exposed interfaces, parameters, and add @enableFeignClients to the caller’s main startup class as described above GnClient (value = “asset-manage”) modified interface, using springMVC annotations to write feign calls, followed by Bean injection where used

<! -- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter --> <dependency> < the groupId > org. Apache. Dubbo < / groupId > < artifactId > dubbo - spring - the boot - starter < / artifactId > < version > 2.7.6 < / version > </dependency>Copy the code

Dubbo not only uses dubbo’s complete micro-service framework, but also integrates dubbo- Spring-boot-starter to configure provider on the client and server respectively