参考资料:
尚硅谷springcloud教程
springcloud文档:https://cloud.spring.io/spring-cloud-static/Hoxton.SR1/reference/htmlsingle/
springboot文档:https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/htmlsingle/
springcloud=分布式微服务架构的一站式解决方案,是多重微服务架构落地技术的集合体,俗称微服务全家桶
springcloud所包含的技术
下面就是我们需要掌握的技术
下面是学习课程是的版本选型
springboot:2.x版本,springcloud H版
下面这张图是springcloud和springboot版本号的对应
最终学习选择的版本:
注意:springcloud版本决定springboot版本,看可以在springcloud官网查看对应版本所推荐的springboot版本,我使用的idea是2022版本的
查看springcloud推荐的springboot版本的方式:
下面是本次课程中所要学的一些技术(主要是打勾的)
a)创建一个父maven工程
修改好字符编码
b)父工程的pom.xml文件
DependencyManagement和Dependencies的区别:前者一般用于父工程,使用pom.xml 中的dependencyManagement 元素能让所有在子项目中引用一个依赖而不用显式的列出版本号。
Maven 会沿着父子层次向上走,直到找到一个拥有dependencyManagement 元素的项目,然后它就会使用这个
注意:DependencyManagement只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖(报错的话把他去掉刷新一下maven引入依赖后再加上即可)
只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom
如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。
<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.0modelVersion>
<groupId>com.javalearn.springcloudgroupId>
<artifactId>springcloudLearnartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>pompackaging>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
<junit.version>4.12junit.version>
<log4j.version>1.2.17log4j.version>
<lombok.version>1.16.18lombok.version>
<mysql.version>8.0.27mysql.version>
<druid.version>1.1.16druid.version>
<mybatis.spring.boot.version>1.3.0mybatis.spring.boot.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>2.2.2.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>Hoxton.SR1version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>2.1.0.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>${mysql.version}version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>${druid.version}version>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>${mybatis.spring.boot.version}version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>${junit.version}version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>${log4j.version}version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>${lombok.version}version>
<optional>trueoptional>
dependency>
dependencies>
dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<fork>truefork>
<addResources>trueaddResources>
configuration>
plugin>
plugins>
build>
project>
1、建模块
在我们原来的父工程下新建一个模块
查看父工程的pom,我们发现多出了一个模块
2、改pom
引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.1.10version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jdbcartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
3、改yml
在resources文件夹中创建一个application.yml文件
server:
port: 8001
spring:
application:
name: cloud-payment-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
driver-class-name: com.mysql.cj.jdbc.Driver # mysql驱动包
url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password:
mybatis:
mapperLocations: classpath:mapper/*.xml
type-aliases-package: com.javalearn.springcloud.entities # 所有Entity别名类所在包
4、主启动
即springboot的主启动类,我们在springboot中已经学习过了
5、业务类
vue->controller->service->dao->mysql
b)创建实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Payment implements Serializable {
private long id;
private String serial;
}
下面是返回给前端的实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CommonResult <T>{
private Integer code;//状态码
private String message;
private T data;
public CommonResult(Integer code,String message){
this(code,message,null);
}
}
c)dao(Mapper)
@Mapper
public interface PaymentDao {
public int create(Payment payment);
public Payment getPaymentById(@Param("id")Long id);
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.javalearn.springcloud.dao.PaymentDao">
<insert id="create" parameterType="Payment" useGeneratedKeys="true" keyProperty="id">
insert into payment (serial) values (#{serial})
insert>
<resultMap id="BaseResultMap" type="Payment">
<id column="id" property="id" jdbcType="BIGINT"/>
<id column="serial" property="serial" jdbcType="VARCHAR"/>
resultMap>
<select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap">
select * from payment where id=#{id}
select>
mapper>
d)service
public interface PaymentService {
public int create(Payment payment);
public Payment getPaymentById(@Param("id")Long id);
}
以及他的实现类
@Service
public class PaymentServiceImpl implements PaymentService {
@Resource
PaymentDao paymentDao;
@Override
public int create(Payment payment) {
return paymentDao.create(payment);
}
@Override
public Payment getPaymentById(Long id) {
return paymentDao.getPaymentById(id);
}
}
e)controller
@Slf4j
@RestController
public class PaymentController {
@Resource
private PaymentService paymentService;
@PostMapping("/payment/create")
public CommonResult createPayment(Payment payment){
int result = paymentService.create(payment);
log.info("****插入结果"+result);
//返回给前端的数据
if (result>0){
return new CommonResult(200,"插入数据苦成功",result);
}else{
return new CommonResult(444,"插入数据库失败",null);
}
}
@GetMapping ("/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id){
Payment payment = paymentService.getPaymentById(id);
if (payment!=null){
return new CommonResult(200,"查询成功",payment);
}else{
return new CommonResult(444,"查询失败,查询id:"+id,null);
}
}
}
六、测试
经过测试,由于我的idea版本过高,所以用周阳老师的lombok版本会报错,修改了一下版本
<lombok.version>1.18.20lombok.version>
测试查询的时候,由于需要post请求,所以这里使用postman,结果插入成功
总结:业务模块的步骤
1.建module
2.改pom
3.写yml
4.写run
5.写业务
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
3、写yml
使用8080端口
server:
port: 80
5、写业务
我们使用消费者模块来操作我们刚刚写的支付模块,所以只需要有controller即可
消费者模块也需要用到Payment的实体类,所以我们先复制一份实体类
接下来写我们的controller类,去调用我们之前写的支付模块,这里就要使用RestTemplate了:是一种简单便捷的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具集
官网:https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html
使用
使用restTemplate访问restful接口非常的简单粗暴无脑。
(url, requestMap, ResponseBean.class)这三个参数分别代表
REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。
a)配置类,注入RestTemplate
@Configuration
public class ApplicationContextConfig {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
b)controller
@Slf4j
@RestController
public class OrderController {
public static final String PAYMENT_URL = "http://localhost:8001";//这个是我们需要转发到的端口
@Resource
private RestTemplate restTemplate;
@GetMapping("/consumer/payment/create")
public CommonResult<Payment> create(Payment payment){
//调用restTemplate的这个方法
return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment,CommonResult.class);
}
@GetMapping("/consumer/payment/get/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
}
}
接下来分别启动80和8001的主启动类,进行测试,启动后idea会弹出一个选项,勾选使用
这样我们就可以方便的看每一个服务了
经过测试,我们可以使用consumer模块调用payment模块的查询方法
但是当我们要调用增加方法时,由于我们的consumer传递给payment模块的是一个json数据,所以我们需要增加一个@RequestBody注解用于接受json字符串,所以要修改8001的代码
在我们的8001和80两个模块中,他们有重复部分,也就是entities实体类,这就会造成代码的冗余,那么接下来我们就要抽取公共部分了。
还是通过maven抽取,通过新建一个cloud-api-commons模块来抽取
1、建模块(不演示了)
2、改pom
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>5.1.0version>
dependency>
dependencies>
4、使用maven命令:clean->install
5、删除原来模块中的entities内容,并引入这个自己定义的jar包
<dependency>
<groupId>com.javalearn.springcloudgroupId>
<artifactId>cloud-api-commonsartifactId>
<version>${project.version}version>
dependency>
到这里,我们的基础构件入门就完成了
虽然Eureka目前已经停止更新,但是许多老项目还是在使用的,我们需要先来了解下面的一些概念
1、服务治理
在传统的rpc远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。
2、服务注册与发现
Eureka Server 作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用 Eureka的客户端连接到 Eureka Server并维持心跳连接。这样系统的维护人员就可以通过 Eureka Server 来监控系统中各个微服务是否正常运行下图是工作原理。
其包括两个组件:
Eureka Server提供服务注册服务: 各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。
EurekaClient通过注册中心进行访问: 是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)
1、建立一个module:cloud-eureka-server7001
2、改pom
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
<dependency>
<groupId>com.javalearn.springcloudgroupId>
<artifactId>cloud-api-commonsartifactId>
<version>${project.version}version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
dependency>
dependencies>
3、写yml
server:
port: 7001
eureka:
instance:
hostname: localhost #eureka服务端的实例名称
client:
#false表示不向注册中心注册自己。
register-with-eureka: false
#false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
#设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址。
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
4、创建springboot主启动类
5、测试
运行主启动类,在浏览器中输入对应网址,进入成功
修改8001模块
1、改pom
注意这里引入的是client,而7001注册中心是sever
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
2、写yml
eureka:
client:
#表示是否将自己注册进EurekaServer默认为true。
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
#入驻哪个主机的哪个端口
defaultZone: http://localhost:7001/eureka
b)如果启动报错
修改一下client依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
<exclusions>
<exclusion>
<groupId>com.sun.jerseygroupId>
<artifactId>jersey-clientartifactId>
exclusion>
<exclusion>
<groupId>com.sun.jerseygroupId>
<artifactId>jersey-coreartifactId>
exclusion>
<exclusion>
<groupId>com.sun.jersey.contribsgroupId>
<artifactId>jersey-apache-client4artifactId>
exclusion>
exclusions>
dependency>
c)刷新Eureka界面,发现服务已经注册进来了
d)发现微服务注册到名称与我们yml文件中的一致
5、消费者模块80也是一样的流程,直接到测试环节
a)先启动7001,和8001,然后启动80
1、集群原理
如果说注册中心只有一台,那么如果他除了故障,整个服务环境就不可用了,所以我们需要搭建集群,下图是到目前为止的工作原理,来保证高可用。
集群原理:相互注册,相互守望,并且对外暴露出一个整体,下面是搭建的步骤
2、建module,参考7001创建cloud-eureka-server7002
3、改pom
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
<dependency>
<groupId>com.javalearn.springcloudgroupId>
<artifactId>cloud-api-commonsartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
dependency>
<dependency>
<groupId>com.thoughtworks.xstreamgroupId>
<artifactId>xstreamartifactId>
<version>1.4.15version>
dependency>
dependencies>
4、修改映射配置
找到C:\Windows\System32\drivers\etc路径下的hosts文件
修改映射配置添加进hosts文件,添加如下内容,方便区分两台sever
6、创建7002的主启动类,与7001一样,别忘了加注解
7、测试,分别运行7001和7002的主启动类,启动服务
1、经过测试,曾经的localhost还可以访问到Eureka主页
1、注册8001,修改yml
2、注册80,修改yml
3、测试
1、启动7001和7002集群,然后启动服务提供者8001,最后启动80
我们工程目前的架构图是80是消费者,8001是服务的提供者,为了保持高可用,我们微服务的提供者也需要进行集群配置
1、参考8001新建8002
2、改pom
直接复制8001的即可
3、写yml
复制粘贴8001的yml,修改端口为8002即可,此时8001和8002对外暴露的服务名其实是一样的
4、主启动
5、业务类
也是直接从8001粘贴
6、修改8001和8002的ontroller(重点)
以8001为例,8002也是一样的修改,获取端口号,来获取是哪台服务器执行的请求
7、测试
启动顺序:7001-7002-8001-8002-80
观察Eureka界面,我们发现支付服务有两台服务器了
8、修改80的controller
在之前的项目中,我们的80是使用了RestTemplate,所以请求只会转发给8001,达不到集群的效果,所以我们需要修改。
a)在原先的配置类中,使用 @LoadBalanced注解赋予RestTemplate负载均衡能力
b)修改地址,80controller中的地址,不再写死8001
这样我们就完成了微服务集群的配置,注意,访问集群的方式默认是轮询,即:你一次我一次
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
(2)修改部分
b)显示ip
修改部分:在8001和8002的yml中加入
这样就可以显示ip了
功能:对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息
1、修改8001的controller,8002也是一样的,就不演示了
首先注入DiscoveryClient
@Resource
private DiscoveryClient discoveryClient;
然后写一个用于获取信息的方法
通过这个discoveryClient就可以获取微服务信息了
@GetMapping("/payment/discovery")
public Object discovery(){
List<String> services = discoveryClient.getServices();//获取服务列表的信息
for (String service : services) {
log.info("****element"+service);
}
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");//获取一个微服务名称下面的全部具体实例
for (ServiceInstance instance : instances) {
log.info(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri());
}
return discoveryClient;
}
2、在8001的主启动类上添加注解@EnableDiscoveryClient
概念:一句话:某时刻某一个微服务不可用了,Eureka不会立刻清理,依旧会对该微服务的信息进行保存,属于CAP里面的AP分支,防止了因为网络分区发生故障而去住注销掉一个健康的微服务。
AP:当发生网络分区时,最大努力保证可用性
如果在Eureka Server的首页看到以下这段提示,则说明Eureka进入了保护模式:
综上,自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留)也不盲目注销任何健康的微服务。 使用自我保护模式,可以让Eureka集群更加的健壮、稳定。
那么怎么关闭自我保护机制?
此次演示以7001服务器和8001客户端为例
(1)修改7001的yml文件,关闭自我保护机制
在运行7001,发现系统提示我们自我保护机制已经关闭了
在写这篇文章的时候,博主本人之前并未学习过zookeeper,所以这里暂时先跳过,后续学习后回来补。
官网:https://www.consul.io/intro/index.html
中文文档:https://www.springcloud.cc/spring-cloud-consul.html
安装说明:https://learn.hashicorp.com/consul/getting-started/install.html
下载地址:https://www.consul.io/downloads.html
Consul 是一套开源的分布式服务发现和配置管理系统,由 HashiCorp 公司用 Go 语言开发。
提供了微服务系统中的服务治理、配置中心、控制总线等功能。这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建全方位的服务网格,总之Consul提供了一种完整的服务网格解决方案。
可以干的事情:
文件下载解压后:
在这个文件夹可以直接用cmd命令运行
启动以后,在浏览器中输入 http://localhost:8500就可以访问web界面了,还是很漂亮的
1、建module:cloud-providerconsul-payment8006
2、改pom
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-consul-discoveryartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
3.写yml
###consul服务端口号
server:
port: 8006
spring:
application:
name: consul-provider-payment
####consul注册中心地址
cloud:
consul:
host: localhost
port: 8500
discovery:
#hostname: 127.0.0.1
service-name: ${spring.application.name}
4、主启动
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain8006 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8006.class,args);
}
}
5、业务类controller
@RestController
@Slf4j
public class PaymentController {
@Value("${server.port}")
private String serverPort;
@RequestMapping("/payment/consul")
public String paymentConsul(){
return "springcloud with consul: "+serverPort+"\t\t"+ UUID.randomUUID().toString();
}
}
6、测试
运行我们的主启动类,然后去consul的web界面观察
程序访问也通过
1、新建一个module:cloud-consumerconsul-order80
2、改pom
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-consul-discoveryartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
3、写yml
###consul服务端口号
server:
port: 80
spring:
application:
name: cloud-consumer-order
####consul注册中心地址
cloud:
consul:
host: localhost
port: 8500
discovery:
#hostname: 127.0.0.1
#注册进去的名字
service-name: ${spring.application.name}
4、主启动
@SpringBootApplication
@EnableDiscoveryClient
public class OrderConsul80 {
public static void main(String[] args) {
SpringApplication.run(OrderConsul80.class,args);
}
}
5、业务类
这里的业务类和我们之前的Eureka下的那个80消费者很相似,也是使用RestTemplate,所以我们拷贝原来的配置类就行
然后写一个controller
@RestController
@Slf4j
public class OrderConsulController {
public static final String INVOKE_URL = "http://consul-provider-payment"; //与Eureka类似,我们要转发的服务的注册名字
@Autowired
private RestTemplate restTemplate;
@GetMapping(value = "/consumer/payment/consul")
public String paymentInfo()
{
String result = restTemplate.getForObject(INVOKE_URL+"/payment/consul", String.class);
System.out.println("消费者调用支付服务(consule)--->result:" + result);
return result;
}
}
6、测试
启动顺序:8006->80
测试访问,发现一切正常
1、CAP是什么?
C:Consistency(数据一致性)
A:Availability(可用性)
P:Partition tolerance(分区容错性)
最多只能同时较好的满足两个。
CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,
因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三 大类:
CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
CP - 满足一致性,分区容忍必的系统,通常性能不是特别高。