目录
SpringCloud初识
简介
直接参考:Spring Cloud简介_springcloud简历_我是啊修啊的博客-CSDN博客
SpringCloud与Dubbo的区别
-
SpringCloud是一个完整的微服务解决方案,它提供了微服务各问题的解决方案集合,而Dubbo是一个高性能的RPC框架,它有着很多功能的缺失定位不一样
-
通信方式不同:Dubbo的通信方式是RPC,基于原声的tcp,性能较好,而SpringCloud的通信方式基于Http协议,虽然底层基于tcp,但是Http的封装过于臃肿,但是使用Http好处在于互相通信的两个服务可以使用不同的变成语言去编写,只要他们都支持Http通信即可互相调用,而Dubbo只支持Java,当然Dubbo交给Apache维护之后做了升级,Dubbo在以后不仅仅支持Java
-
背景都很强大:Dubbo背靠阿里和Apache,淘宝就是使用的Dubbo来开发经理过双11期间的高并发大流量检验,可以说是非常的稳定和成熟,SpringCloud是Spring家族的成员,严格遵循Martin Fowler提出的微服务规范,可以认为SpringCloud是微服务架构的标准,总之两者背景都很强大,文档完善,社区活跃,所以不管作何选择,都是很有前途的
-
开发风格:从开发风格上来讲,Dubbo官方推荐倾向于使用Springxml配置方式,SpringCloud是基于SpringBoot的开发风格,即采用注解的方式进行配置,从开发速度上来说,SpringCloud具有更高的开发和部署速度
SpringCloudNetflix-Eureka
1.什么是Eureka
Eureka称为注册中心:在微服务中服务数量众多,每个服务都有自己的通信地址,那么如何管理众多的服务地址呢?并且有时候服务的上线与下线我们如何知道,并且调用可用的服务呢?当服务可用或者不可用之后,我们又如何自动的发现/删除服务呢?如果需要我们程序员手动管理,那么难度必然是极大的,这时候我们就需要Eureka,帮助我们进行服务的注册和发现
2.Eureka的工作原理
-
服务注册
-
Eureka是一个服务注册与发现组件,简单说就是用来统一管理微服务的通信地址的组件,它包含了EurekaServer服务端/注册中心和EurekaClient客户端两部分组成,EurekaServer是独立的服务,而EurekaClient需要集成到每个微服务中
-
微服务/EurekaClient在启动的时候会向EurekaServer提交自己的服务信息,通信地址如:服务名、ip、端口等,在EurekaServer会形成一个微服务的通信地址列表存储起来,这叫服务注册
-
-
服务发现
-
微服务/EurekaClient会定期【默认30秒,可以进行更改】的从EurekaServer拉取一份微服务通信地址列表缓存到本地,这样做的目的是为了能够向其他服务发起调用
-
当一个微服务在向另一个微服务发起调用的时候会根据目标服务的服务名找到其通信地址,然后基于HTTP协议向目标服务发起请求,这叫服务发现
-
-
服务续约
-
微服务/EurekaClient采用定时【默认30秒,可以进行更改】发送“心跳”请求向EurekaServer发请求进行服务续约,其实就是定时向EurekaServer发请求报告自己的健康状况,告诉EurekaServer自己还活着,不要把自己从服务地址清单中剔除掉,那么当微服务/EurekaClient宕机未向EurekaServer续约,或者续约请求超时,注册中心机会从服务地址清单中剔除该续约失败的服务,默认是续约失败90秒之后剔除,那么意味这剔除一个不可用服务最大时间为120秒
-
-
服务下线
-
微服务/EurekaClient关闭服务前向注册中心发送下线请求,注册中心/EurekaServer接受到下线请求负责将该服务实例从注册列表剔除
-
Eureka实战
1.多模块项目搭建
因为涉及到多个模块,为了方便开发,我们采用Maven父子结构进行项目的搭建
- 第一步:创建父子项目,在父项目中导入Jar包。PS:父项目需要删除src文件夹,因为父项目只负责管理Jar包
<!--1.管理 SpringBoot的jar包-->
<!--SpringBoot-->
<parent>
<groupId> org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<!--2.管理 SpringCloud的jar包,父项目只管理,不引用-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!--3.这里是所有子项目都可以用的jar包-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
-
第二步:创建用户、订单、Eureka服务端(user-pojo是后面使用Ribbon的公共模块,当没看见就行)
2.搭建EurekaServer
官网参考文档:Spring Cloud Netflix
-
第一步:导入依赖
-
spring-cloud-starter-netflix-eureka-server是EurekaServer端的基础依赖,但同时这个包也把EurekaClient端的以来也导入进来了,spring-boot-starter-web作为web服务的基础依赖是不可缺少的
-
<dependencies>
<!--spring-cloud-starter-netflix-eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
-
第二步:编写启动类
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApp {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApp.class, args);
}
}
-
第三步:编写配置文件
-
因为导入的Eureka服务端包含了Eureka客户端依赖,我们要将当前Eureka服务端关闭服务注册、拉去注册表等功能
-
server: # Eureka服务端端口号
port: 1010
eureka: # Eureka配置
instance:
hostname: localhost # Eureka服务名称
client: # Eureka客户端配置
registerWithEureka: false # 该服务不注册到到注册中心
fetchRegistry: false # 该服务不拉取注册表
serviceUrl: # 注册中心地址 http://localhost:1001/eureka/
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
-
第四步:启动Eureka服务端,访问Eureka服务可视化页面,看到以下页面说明Eureka服务端搭建成功
3.EurekaClient实战-订单服务
-
第一步:导入依赖
<dependencies>
<!--引入Eureka的客户端依赖,不包含springboot-start-web,所以要单独引入-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--引入springboot-start-web依赖,必须引入-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
-
第二步:编写配置文件
server:
port: 1020 # order服务端口号
eureka:
client: # Eureka客户端配置,指向注册中心地址
serviceUrl:
defaultZone: http://localhost:1010/eureka/
instance:
prefer-ip-address: true # 开启使用IP地址进行注册
instance-id: order-server:1020 # 修改实例Id
spring:
application: # 指定此服务的应用名称
name: order-server
-
第三步:编写启动类
@SpringBootApplication
@EnableEurekaClient
public class OrderServerApp {
public static void main(String[] args) {
SpringApplication.run(OrderServerApp.class, args);
}
//配置一个RestTemplate ,Spring封装的一个机遇Restful风格的http客户端 工具
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
-
第四步:启动Order服务,在Eureka注册中心中查看Order服务
4.EurekaClient实战-用户服务
和订单服务一样,导入依赖、编写配置、编写启动类、启动服务,用户的实例Id和服务端口号使用1030。
RestTemplate服务通信
-
Spring为我们封装了一个基于Restful的使用非常简单的Http客户端工具 RestTemplate ,我们就用它来实订单服务和用户服务的通信
-
需要注意的是,RestTmplate本身不具备服务发现和负载均衡器的功能,我们本章的案例只是演示在订单服务中使用RestTemplate基于ip和端口的方式向用户服务发起调用,即:不走注册中心,不使用服务发现方式
搭建公共模块
-
用户服务需要提供User对象,我们需要为其编写Controller接口,编写相关方法返回User,订单服务需要从用户服务获取到User对象,而浏览器需要访问订单服务获取到User对象,所以订单服务也需要编写Controller接口供浏览器来调用
-
我们发现不管是用户服务还是订单服务都需要用到User对象,那么是不是在用户服务和订单服务都需要创建User的模型?当然没必要,公共的东西就是要抽取,所以我们会把User对象封装在一个公共的模块 springcloud-user-pojo中然后让用户服务和订单服务都去依赖这个模块
-
公共模块:只作为我们某个服务编写公共模块代码的地方,不会作为服务进行启动,其原理就是将我们的公共模块打包成一个Jar包,然后在需要使用此模块代码的服务中使用Maven坐标引入本地仓库中打包好的公共模块Jar包即可,这样在引入的模块中就可以使用公共模块的代码
在springcloud-user-pojo中创建User对象如下
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Long id;
private String username;
private String desc;
}
用户和订单依赖User模块
<dependency>
<groupId>cn.zfh</groupId>
<artifactId>springcloud-user-pojo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
用户服务返回User
/**
* 用户服务:暴露接口给订单访问
*/
@RestController
public class UserController {
//订单服务来调用
@GetMapping("/user/{id}")
public User getById(@PathVariable("id")Long id){
return new User(id,"urben:");
}
}
在订单服务中需要使用RestTemplate调用用户服务,我们需要把RestTmplate配置成Bean方便使用(当然也可以不创建Bean,用的时候直接new对象也可以)
@SpringBootApplication
@EnableEurekaClient
public class OrderServerApp {
public static void main(String[] args) {
SpringApplication.run(OrderServerApp.class, args);
}
//配置一个RestTemplate ,Spring封装的一个机遇Restful风格的http客户端 工具
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
创建controller,通过RestTemplate调用用户服务
@RestController
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/order/{id}")
public User getById(@PathVariable("id") Long id){
User user = restTemplate.getForObject("http://localhost/user/" + id, User.class);
return user;
}
}
浏览器访问Order服务接口,进行测试
SpringCloudNetflix-Ribbon
简介:
参考文章:Spring Cloud Netflix Ribbon_大河山川的博客-CSDN博客
消费者order-server集成Ribbon
- 第一步:order-server服务中导入Jar包
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.zfh</groupId>
<artifactId>springcloud-user-pojo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
</dependencies>
-
第二步:修改RestTemplate的Bean的定义方法,加上Ribbon的负载均衡注解@LoadBalanced赋予RestTemplate有负债均衡的能力
-
第三步:在调用时,使用应用名称称代替IP地址,这样RestTemplate会在服务下的集群服务中进行轮询选择
-
第四步:为了方便我们查看到底调用的是user-server中的那个服务,我们在user-server中打印进入接口时,服务的端口号
/**
* 用户服务:暴露接口给订单访问
*/
@RestController
public class UserController {
//加载端口
@Value("${server.port}")
private int port;
//订单服务来调用
@GetMapping("/user/{id}")
public User getById(@PathVariable("id")Long id){
return new User(id,"urben:"+port,"我是urben");
}
}
-
第五步:重启user、order、Eureka服务,访问order服务接口进行测试
负载均衡算法
感兴趣的可参考