Build Spring Cloud service from scratch

1. The basics of microservices

1. What is Spring Cloud?

SpringCloud official website: https://spring.io/projects/spring-cloud (personal suggestion is to use Google browser to visit the official website, open the Chinese translation and roughly read the official website)

Personal understanding:

The previous server was like an all-round teacher who can speak English and Mathematics to provide services for students. If the teacher is sick, the whole school will be suspended. Now that microservices are popular, the school has mathematics teaching and research groups, Chinese teaching and research groups, and foreign language teaching and research groups. Each teaching and research group has a group of teachers who are responsible for the teaching of a certain subject. If there is no one, the school will continue to operate.

In this change, those programmers who changed history classified and decoupled many services in one server, or many services in several servers, and handed over their similar functions to the same cluster. The functions that are coupled with each other are separated, and they are placed on the server as microservices according to business and function, and this server only provides one service, or fewer services. Let a super-large service logic be decoupled into small services, evenly distributed in their respective servers. Microservices are here.

Each teaching and research group is a microservice cluster. They provide the same service, and the registration center Eureka is the place where the list of teachers of this teaching and research group is stored. Students want to visit this registration center to obtain the list of teachers first, and then visit their respective teachers according to the corresponding load method. It will not make a certain teacher in the cluster exhausted or let a certain teacher die idle.

As for the Zuul gateway, it is the gatekeeper of the school. Some students come to the school to find someone. It is responsible for guiding (routing), and through some very simple configurations, it can block some people from entering (authentication), or control people who want to learn mathematics. You can only go to the mathematics teaching and research group, not the nuclear energy teaching and research group to learn how to build an atomic bomb (permission verification).

As for the Hystrix fuse, it can be regarded as a school volunteer. When a teaching and research group strikes collectively and the students cannot find the teacher, these volunteers will promptly inform the visiting students of the corresponding results, abnormal information, etc., so as to avoid a large number of The students are waiting in the school, and these volunteers quickly sort out these waiting students. The students have been waiting in the school, and other schools that need students will also wait for students, and finally cause a large area of ​​​​the school to be paralyzed. Here we regard the students as requests one by one. The fuse is to blow the spread of an accident even if it is blown.

Of course, these components are also microservices that need to be registered with the Eureka registry

Then SpringCloud can be regarded as this school. Many of the components mentioned above are equivalent to the various functional departments of this school.

2. Construction of microservices

ps: The blogger builds based on Maven+idea.

In addition, SpringCloud needs to be built based on springboot.

Introduce Spring Boot-related dependencies: here springboot uses version 1.5.7; introduce Spring Cloud-related dependencies: here is Edgware.SR5

2.1 Project initialization configuration


Create a project in Idea: File -> New -> Project

Click Empty Project -> Next

Project Naming -> Project Location

Select the module modules ->next

After entering the new window, start configuring Maven and open the settings

Because I have done configuration before, I only need to change the path of box 1. For the first configuration, I need to find the location where your maven is placed, as well as the location of settings.xml and repository. I really don’t know how to integrate Baidu maven.

After the 3 boxes are selected, click ok

Next create a new module

There may be a problem that the archetype list cannot be loaded here

It took 3 hours to solve all the solutions on the Internet to no avail, but it worked after restarting... Can you believe it? ? ? ? ? When I was a child, I forgot the wise words of Internet cafe network administrators! ! Restart it! !

After coming out, select quickstart -> next step

After thinking about the name by yourself, copy the ArtifactId you thought of and click Next. The groupId is the name of the organization and you can think of it yourself. Generally, it is the company website.

next step after pasting

提供注册服务的服务器pom.xml配置如下:

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  <modelVersion>4.0.0</modelVersion>   <groupId>com.yun</groupId>  <artifactId>springcloud-eureka-server</artifactId>  <version>1.0-SNAPSHOT</version>   <name>springcloud-eureka-server</name>  <!-- FIXME change it to the project's website -->  <url>http://www.example.com</url>   <properties>    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>    <maven.compiler.source>1.7</maven.compiler.source>    <maven.compiler.target>1.7</maven.compiler.target>  </properties>   <!--引入springboot-parent父项目-->  <parent>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-parent</artifactId>    <version>1.5.7.RELEASE</version>  </parent>   <dependencies>    <!--引入springcloud的euekea server依赖-->    <dependency>      <groupId>org.springframework.cloud</groupId>      <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>    </dependency>   </dependencies>    <!--指定下载源和使用springcloud的版本-->  <dependencyManagement>    <dependencies>      <dependency>        <groupId>org.springframework.cloud</groupId>        <artifactId>spring-cloud-dependencies</artifactId>        <version>Edgware.SR5</version>        <type>pom</type>        <scope>import</scope>      </dependency>    </dependencies>  </dependencyManagement></project>

点击Import Changes

等待右下角加载springcloud的依赖

2.2 Springboot的搭建 以及提供注册服务 的 服务配置


创建resources文件夹

并设置作为资源根目录,之后文件变成这样

之后文件夹变成有黄色的横杠

在resources下新建文件,文件名为application.yml (对是yml 不是xml ,博主第一次学习时,还以为是其他博主打错了,踩了一个小坑)

配置yml,注意:如果只配置前两行端口号信息会报错

server:  port: 8700 # 端口自己决定  # 指定当前eureka客户端的注册地址,也就是eureka服务的提供方,当前配置的服务的注册服务方eureka:  client:    service-url:      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka    register-with-eureka: false #自身 不在向eureka注册    fetch-registry: false  #启动时禁用client的注册  instance:    hostname: localhost #指定应用名称spring:  application:    name: eureka-server

知识补充:

开发springboot的入口类 EurekaServerApplication.java

EurekaServerApplication.java

package com.yun; import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication@EnableEurekaServer //当前使用eureka的serverpublic class EurekaServerApplication {    public static void main(String[] args) {        SpringApplication.run(EurekaServerApplication.class,args);    }}

右键运行当前类:

运行成功console画面

尝试进入eureka管理界面 端口号为 yml里配置的(端口号自己设置 需要大于公用和保留的端口号)1024~65535

一般我喜欢设置为 8700到8800之间

如下 管理界面已经可以登录了。搜索Java知音公众号,回复“后端面试”,送你一份Java面试题宝典.pdf

2.3 客户端client 提供真正服务的角色的配置, 它提供服务 在 服务注册方server (注册中心)进行注册


同样新建module,选择quickstart点击下一步

两个位置 置空

取名 下一步

注意这里要在根目录springcloud 下创建模组,content root 会默认在之前的模组之下创建模组 这样创建模组会出现问题并报错

推荐这种配置方法 在content root下springcloud后改名字 如下图配置点下一步,红框处一般默认为上一个模组的文件目录名,需要改为你的模组名

成功后为并列状态,如不为并列或报错请重新配置

配置servicesupport的pom,与server的pom配置相同,只需要把第一个pom的1的方框处server改为client

和第一个微服务同理 我们需要配置入口类 pom.xml application.yml,因为是服务提供者,这里还需编写服务类controller

application.yml

server:  port: 8701 # 服务提供方 # 指定当前eureka客户端的注册地址,eureka:  client:    service-url:      defaultZone: http://${eureka.instance.hostname}:8700/eureka  instance:    hostname: localhost #当前服务名称spring:  application:    name: eureka-service

pom.xml:

编写所提供的 服务controller:

package com.yun; import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController; @RestController@RequestMapping("/Hello")public class Controller {    @RequestMapping("/World")    public String helloWorld(String s){        System.out.println("传入的值为:"+s);        return "传入的值为:"+s;    }}

入口类 并运行此微服务:

package com.yun; import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication@EnableDiscoveryClient//代表自己是一个服务提供方public class EurekaServiceApplication {    public static void main(String[] args) {        SpringApplication.run(EurekaServiceApplication.class,args);    }}

右键入口类名点击 run(当然开启此服务时需要先开启server服务 就是我们第一个编写的微服务)

此时再进入服务注册的页面 http://localhost:8700/

可以看见服务提供者已被注册进 服务注册者

在直接访问一下服务提供者的 网络位置http://localhost:8701/Hello/World?s=小沛

我们已经看见 可以访问了,证明此微服务可用。

但是我们一般不直接调用所需的微服务,而是经过提供注册服务的服务器server,获取所需的服务提供者列表(为一个列表,此列表包含了能提供相应服务的服务器),他们也许是个集群,因此server会返回一个 ip+端口号的表,服务消费者通过相应算法访问这表上的不同服务器,这些服务器提供的是相同的服务,这种在服务消费者一方挑选服务器为自己服务的方式是一种客户端的负载均衡。

目前博主所知的有 轮询和随机两种方式 访问这些服务器,轮询就是循环的意思,假如有3台服务器,访问方式就是1,2,3,1,2,3,1,2,3····,随机就是随机,回想一下random方法,一种无规律的方式。这两种方式都是为了,访问每个服务器的可能性尽量的相同。还有权重负载这种算法,意思就是 根据服务器负载能力的分配相应的服务。能力大的干得多。能力小的干得少。

搜索Java知音公众号,回复“后端面试”,送你一份Java面试题宝典.pdf

2.4 服务的调用方式


第一种调用方式:restTemplate+ribbon
第二种调用方式:feign

2.4.1 restTemplate+ribbon

ribbon是一种负载均衡的客户端,它是什么呢?请详读https://www.jianshu.com/p/1bd66db5dc46

可以看见其中的一段如下:

而客户端负载均衡和服务端负载均衡最大的不同点在于上面所提到服务清单所存储的位置。在客户端负载均衡中,所有客户端节点都维护着自己要访问的服务端清单,而这些服务端端清单来自于服务注册中心,比如上一章我们介绍的Eureka服务端。同服务端负载均衡的架构类似,在客户端负载均衡中也需要心跳去维护服务端清单的健康性,默认会创建针对各个服务治理框架的Ribbon自动化整合配置,比如Eureka中的org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration,Consul中的org.springframework.cloud.consul.discovery.RibbonConsulAutoConfiguration。在实际使用的时候,我们可以通过查看这两个类的实现,以找到它们的配置详情来帮助我们更好地使用它。

接下来我们来搭建基于ribbon的客户端,他用于消费服务。

同理先搭建springboot的环境

与之前搭建servicesupport不同的是:

第一步:现在pom中需要在dependencies中添加ribbon依赖

        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-ribbon</artifactId>        </dependency>

第二步:yml如下配置:

server:  port: 8702 # 服务消费方 # 指定当前eureka客户端的注册地址,eureka:  client:    service-url:      defaultZone: http://${eureka.instance.hostname}:8700/eureka  instance:    hostname: localhost #当前服务名称spring:  application:    name: eureka-consumer

服务的消费方依旧需要在注册方8700端口去注册。配置当前服务消费方的端口8072,名字为eureka-consumer

第三步:依旧需要启动类,因为它是一个springboot的架构:

package com.yun; import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;  @SpringBootApplication@EnableDiscoveryClient //当前使用eureka的serverpublic class EurekaConsumerApplication {    public static void main(String[] args) {        SpringApplication.run(EurekaConsumerApplication.class,args);    }}

如上图:

我们需要一个controller类来编写ribbon的代码。

package com.yun.controller; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cloud.client.ServiceInstance;import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate; @RestController@RequestMapping("/Hello")class ConsumerController {    @Autowired    private LoadBalancerClient loadBalancerClient;    @Autowired    private RestTemplate restTemplate;    @RequestMapping("/Consumer")    public String helloWorld(String s){        System.out.println("传入的值为:"+s);        //第一种调用方式        //String forObject = new RestTemplate().getForObject("http://localhost:8071/Hello/World?s=" + s, String.class);         //第二种调用方式        //根据服务名 获取服务列表 根据算法选取某个服务 并访问某个服务的网络位置。        //ServiceInstance serviceInstance = loadBalancerClient.choose("EUREKA-SERVICE");        //String forObject = new RestTemplate().getForObject("http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/Hello/World?s="+s,String.class);         //第三种调用方式 需要restTemplate注入的方式        String forObject = restTemplate.getForObject("http://EUREKA-SERVICE/Hello/World?s=" + s, String.class);        return forObject;    }}

我们常用第三种调用方式。

第一种是直接调用:不经过注册中心那服务列表,直接访问的servicesupport

第二种:是根据服务名选择调用,如上图需要做如下注入

@Autowired
private LoadBalancerClient loadBalancerClient;

如上图代码中第二种调用方法的代码所示。

用服务名去注册中心获取服务列表,当前客户端底层会做随机算法的选取获得服务并访问。

第三种需要一个@Bean的注解自动注入并直接调用restTemplate对象调用服务。底层调用模式与第二种调用方式一样。如下:

package com.yun.beans; import org.springframework.cloud.client.loadbalancer.LoadBalanced;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.client.RestTemplate; @Configurationpublic class Beans {    //管理简单对象    @Bean    @LoadBalanced    public RestTemplate getRestTemplate(){        return new RestTemplate();    }}

@Bean注解告诉工厂,这个方法需要自动注入。

@LoadBalanced,表示需要做负载匀衡。

然后如controller中一样注入一下restTemplate,并且使用他,区别是可以直接使用服务名访问了

String forObject = restTemplate.getForObject(" http://EUREKA-SERVICE/Hello/World?s=" + s, String.class);

开始测试:

1.运行server的启动类:

  1. 运行servicesupport的启动类:

3.运行serviceconsume的启动类:

浏览器访问:

8072为服务消费方的端口

访问方法解析:

  • 访问服务消费方@RequestMapping指定的路径及消费方的端口来访问消费方的controller

  • controller根据服务名去server方获取获取服务列表,获取服务列表后根据随机的模式负载匀衡后去选择服务地址去访问servicesupport:如下图

---------- 更新于星期日2018年12月30日 20:02 待续....---------

待续...

2.5 Eureka server的高可用配置


点击下图配置

接下来配置三台01,02,03的虚拟机参数

01:8699

02:8698

03:8697

之后点ok保存,可看见多出三个启动项

接下来分别改注册端口号,defaultZone分别启动三个启动项

打开server的yml配置,删掉前两行端口号配置(图中有错,请把instance 和hostname那两行删掉)

配置好yml后点击启动

同理,我们再次改动端口号为8699和8697后,把启动项改为02,之后启动(图中有错,请把instance 和hostname那两行删掉)

同理把yml端口改为8699 和 8698后,把启动项改为03,之后启动(图中有错,请把instance 和hostname那两行删掉)

启动后分别访问三个01,02,03端口,已经可以看见可以访问了。

打开服务提供方的yml配置如下,把端口号改为三个中其中的一个。

启动服务提供方之后,再次访问三个01,02,03我们会发现

重点:即使服务提供方只注册了一个端口号8699,但是另外两个端口号,也能感知到服务提供方8701的存在了。如下图:

接下来像服务消费方中添加服务注册者的端口号,这样在server挂掉任何一个的时候,都能有其他的server也能获取服务列表

访问以下服务消费方,发现可以通过消费方调用server服务列表并且访问service了

我么随便关闭其中两个server的副本,重启serviceconsume,再进行访问。必须重启serviceconsume才能清空缓存,清掉consume里面有的服务列表。

上图发现即使关闭两台server后依旧可以访问,如下图,依旧从server中获取了服务列表,从中也能看见之后不用再获取服务列表了。

但是当我们关掉所有server后。访问还是没问题,因为缓存了服务列表。

但是让我们来重启一下serviceconsume,再访问就不行了。

综上我们就完成了springcloud中server的高可用配置

Guess you like

Origin blog.csdn.net/z_ssyy/article/details/128721892