从零搭建 Spring Cloud 服务(超级详细)
共 13897字,需浏览 28分钟
·
2021-04-03 23:44
点击上方“程序员大白”,选择“星标”公众号
重磅干货,第一时间送达
作者:Anakki;链接:blog.csdn.net/qq_29519041/article/details/85238270
这里会介绍很多基础知识,直接想开始搭建微服务的可以看第二章,微服务的搭建。直接看第二章不会有什么影响,可以先学会开车再学习车的构造的,看个人习惯来。
1.什么是SpringCloud?
SpringCloud官网:https://spring.io/projects/spring-cloud(个人建议是用谷歌浏览器访问官网打开中文翻译粗略把官网读一遍)
个人理解:
以前的服务器就好像,一个会语数外全能的老师,为学生提供服务,这个老师生病了,那全校停课。现在微服务流行后,学校有了数学教研组,语文教研组,外语教研组,每个教研组有一群老师具体负责某科的教学,缺了谁,学校都照样运转。
而这个变化中,那些改变历史的程序员就是把一个服务器中的众多服务,或好几台服务器中的众多服务,分类出来,解耦合出来,把他们类似的功能交给同一个集群来做,把互相耦合在一起的功能剥离出来,按业务,按功能来把他们作为一个个微服务放在服务器上,而这个服务器就只提供一个服务,或较少的服务。
让一个超大的服务逻辑,解耦合为一个个小服务,均匀的分布在各自的服务器中。微服务就微在这。每个教研组就是一个微服务集群。他们提供同样的服务,而注册中心Eureka就是这个存放这个教研组老师名单的地方,学生们想先访问这个注册中心获取教师名单,然后根据相应的负载方法去访问各自老师。不至于让集群中某一老师累死也不至于让某一老师闲死。
而Zuul网关呢,就是学校的门卫,某些学生来学校找谁,它负责指引(路由),并且通过一些非常简单的配置,达到阻拦一些人进入(身份验证),或者控制想学数学的人只能去数学教研组,不能去核能教研组学怎么造原子弹(权限验证)。
那Hystrix熔断器呢,可以把它当成学校的志愿者,当一个教研组集体罢课后,学生找不到老师了,这些志愿者及时的告诉来访问的学生,相应的结果,异常信息等,免得大量的学生在学校等待,这些志愿者赶快把这些等待的学生梳理出去,学生一直在学校等待,那其他需要学生的学校,也会等待学生,最后造成大面积的学校瘫痪。这里学生我们看成一个个请求。熔断器就是把某事故的蔓延即使熔断了。
当然这些组件也是微服务需要注册到Eureka注册中心
那 Spring Cloud 就可以看成是这个学校了。众多上面提到的组件相当于都是这个学校的各职能部门。
ps: 博主基于Maven+idea搭建。 另外SpringCloud需要基于springboot搭建。
2.1 引入Spring Boot相关依赖 这里的springboot用的是1.5.7版本
引入Spring Cloud相关依赖 这里为 Edgware.SR5
2.1 工程初始化配置
在Idea中创建工程:File -> New ->Project
点击 Empty Project -> Next
项目命名 -> 项目位置
选择模组 modules ->next
进入新的窗口后,开始配置Maven,打开设置 setting
因为我之前做过配置,因此只需要改变框1的路径,如第一次配置需要自己找到你maven放置的位置,以及settings.xml,repository的位置,实在不会的百度 maven集成idea
3个框选择完毕后点击 ok
接下来新建module
这里可能会出现加载不出archetype list的问题
用了网上的所有解决办法花了3个小时解决都没用,重启之后竟然可以了····你敢信?????小时候网吧网管的至理名言都忘了!!重启一下嘛!!
出来之后 选择quickstart ->下一步
名字自己想 想好后,复制一下你想好的 ArtifactId点击Next,groupId为组织名 也是自己想一个,一般为公司网址反写。
粘贴后下一步
提供注册服务的服务器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>
2.2 Springboot的搭建 以及提供注册服务 的 服务配置
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
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的server
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class,args);
}
}
2.3 客户端client 提供真正服务的角色的配置, 它提供服务 在 服务注册方server (注册中心)进行注册
server:
port: 8701 # 服务提供方
# 指定当前eureka客户端的注册地址,
eureka:
client:
service-url:
defaultZone: http://${eureka.instance.hostname}:8700/eureka
instance:
hostname: localhost
#当前服务名称
spring:
application:
name: eureka-service
@RestController
@RequestMapping("/Hello")
public class Controller {
@RequestMapping("/World")
public String helloWorld(String s){
System.out.println("传入的值为:"+s);
return "传入的值为:"+s;
}
}
@SpringBootApplication
@EnableDiscoveryClient//代表自己是一个服务提供方
public class EurekaServiceApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServiceApplication.class,args);
}
}
2.4 服务的调用方式
第一种调用方式:restTemplate+ribbon
第二种调用方式:feign
2.4.1 restTemplate+ribbon
而客户端负载均衡和服务端负载均衡最大的不同点在于上面所提到服务清单所存储的位置。在客户端负载均衡中,所有客户端节点都维护着自己要访问的服务端清单,而这些服务端端清单来自于服务注册中心,比如上一章我们介绍的Eureka服务端。 同服务端负载均衡的架构类似,在客户端负载均衡中也需要心跳去维护服务端清单的健康性,默认会创建针对各个服务治理框架的Ribbon自动化整合配置,比如Eureka中的org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration,Consul中的org.springframework.cloud.consul.discovery.RibbonConsulAutoConfiguration。在实际使用的时候,我们可以通过查看这两个类的实现,以找到它们的配置详情来帮助我们更好地使用它。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
server:
port: 8702 # 服务消费方
# 指定当前eureka客户端的注册地址,
eureka:
client:
service-url:
defaultZone: http://${eureka.instance.hostname}:8700/eureka
instance:
hostname: localhost
#当前服务名称
spring:
application:
name: eureka-consumer
@SpringBootApplication
@EnableDiscoveryClient //当前使用eureka的server
public class EurekaConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaConsumerApplication.class,args);
}
}
@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;
}
}
@Autowired
private LoadBalancerClient loadBalancerClient;
@Configuration
public class Beans {
//管理简单对象
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
String forObject = restTemplate.getForObject("http://EUREKA-SERVICE/Hello/World?s=" + s, String.class);
访问服务消费方@RequestMapping指定的路径及消费方的端口来访问消费方的controller controller根据服务名去server方获取获取服务列表,获取服务列表后根据随机的模式负载匀衡后去选择服务地址去访问servicesupport:如下图
2.5 Eureka server的高可用配置
推荐阅读
关于程序员大白
程序员大白是一群哈工大,东北大学,西湖大学和上海交通大学的硕士博士运营维护的号,大家乐于分享高质量文章,喜欢总结知识,欢迎关注[程序员大白],大家一起学习进步!