参考狂神说笔记
https://www.kuangstudy.com/bbs/1374942542566551554
参考博客
https://blog.csdn.net/lijie0213/article/details/107914619
代码已上传gitee
版本1:https://gitee.com/zhengwen_y/springcloud-yzw.git
版本2(缩减版):https://gitee.com/zhengwen_y/springcloud-demo.git
2、创建子模块springcloud-api,存放pojo (1) 结构如下 (2)创建数据库的表UTF-8 8 8 4.12 1.16.18 1.2.17 1.2.3 org.springframework.cloud spring-cloud-alibaba-dependencies0.2.0.RELEASE pom import org.springframework.cloud spring-cloud-dependenciesGreenwich.SR1 pom import org.springframework.boot spring-boot-dependencies2.1.4.RELEASE pom import mysql mysql-connector-java5.1.47 com.alibaba druid1.1.10 org.mybatis.spring.boot mybatis-spring-boot-starter1.3.2 ch.qos.logback logback-core${logback-core.version} junit junit${junit.version} org.projectlombok lombok${lombok.version} log4j log4j${log4j.version}
CREATE TABLE `dept` (
`deptno` bigint(20) NOT NULL AUTO_INCREMENT,
`dname` varchar(60) DEFAULT NULL,
`db_source` varchar(60) DEFAULT NULL,
PRIMARY KEY (`deptno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='部门表'
INSERT INTO dept(dname,db_source) VALUES ('开发部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES ('项目部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES ('研发部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES ('运维部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES ('市场部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES ('人事部',DATABASE());
(3)导入lombok依赖
(4)创建Dept实体类org.projectlombok lombok
package com.yzw.springcloud.pojo;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@NoArgsConstructor
@Accessors(chain = true) //链式写法
//所有的实体类必须实现序列化接口
public class Dept implements Serializable {
private Long deptno;
private String dname;
private String db_source;//这个数据是存在哪个数据库的字段
}
3、创建服务的提供者—子模块springcloud-provider-dept-8001
(0)结构如图所示
(1)导入项目依赖
(2)配置application.yml`com.yzw springcloud-api1.0-SNAPSHOT junit junitmysql mysql-connector-javacom.alibaba druidch.qos.logback logback-coreorg.mybatis.spring.boot mybatis-spring-boot-starterorg.springframework.boot spring-boot-starter-weborg.springframework.boot spring-boot-starter-jettyorg.springframework.boot spring-boot-devtools
server:
port: 8001
#mybatis配置
mybatis:
#省略pojo前面的一长串前缀
type-aliases-package: com.yzw.springcloud.pojo
config-location: classpath:mybatis/mybatis-config.xml
#如果sql的xml文件与mapper不在同一文件夹下,就需要配置
mapper-locations: classpath:mybatis/mapper/*.xml
#spring的配置
spring:
application:
name: springcloud-provider-dept
#数据源的配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource #数据源为druid
driver-class-name: com.mysql.jdbc.Driver #数据库驱动
url: jdbc:mysql://localhost:3306/springcloud1?useUnicode=true&characterEncoding=utf-8&servetTimeZone=Asia/Shanghai
username: root
password: 12345678
(3)创建DeptDao接口
注意:这里的DeptDao接口需要加上一个@Mapper注解,后面的会扫描到相应的mapper文件后,给接口生成一个具体实现类,注册到Spring容器中
@Mapper
public interface DeptDao {
//添加一个部门
public boolean addDept(Dept dept);
//根据id查出一个部门
public Dept queryById(Long id);
//查询所有部门信息
public List queryAll();
}
(4)创建DeptMapper.xml
在resource包下创建mybatis包
在mybtis/mapper包下 创建DeptMapper.xml 实现DeptDao方法的sql
(5)在mybtis下创建mybatis-config.xml的配置insert into dept (dname,db_source) values (#{dname},DATABASE()) select * from dept where deptno = #{depono};
(6)创建service包
DeptService接口
public interface DeptService {
//增加一个部门
boolean addDept(Dept dept);
//根据id查询部门信息
Dept queryById(Long id);
//查询所有的部门信息
List queryAll();
}
(7)DeptServiceImpl实现service的接口
DeptService接口
@Service
public class DeptServiceImpl implements DeptService{
@Autowired
private DeptDao deptDao;
@Override
public boolean addDept(Dept dept) {
return deptDao.addDept(dept);
}
@Override
public Dept queryById(Long id) {
return deptDao.queryById(id);
}
@Override
public List queryAll() {
return deptDao.queryAll();
}
}
(8)创建controller包
DeptController类
//提供Restful服务
@RestController
public class DeptController{
@Autowired
private DeptService deptService;
@PostMapping("/dept/add")
public boolean addDept(Dept dept) {
return deptService.addDept(dept);
}
@RequestMapping("/dept/get/{id}")
public Dept queryById(@PathVariable("id") Long id) {
return deptService.queryById(id);
}
@RequestMapping("/dept/list")
public List queryAll() {
return deptService.queryAll();
}
}
(9)创建DeptProvider_8001的启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DeptProvider_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider_8001.class);
}
}
(10)启动后访问http://localhost:8001/dept/get/1
4、Rest环境搭建——创建服务消费者—子模块springcloud-consumer-dept-80
(0)结构如图所示
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DeptProvider_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider_8001.class);
}
}
(1)导入项目依赖
(2)配置application.ymlcom.yzw springcloud-api1.0-SNAPSHOT org.springframework.boot spring-boot-starter-web
server: port: 80(3)配置RestTemplate,作为远程调用
创建config文件包
创建ConfigBean类,里面配置RestTemplate
@Configuration
public class ConfigBean { //@Configuration=spring的 application.xml
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
(4)创建消费者controller/DeptConsumerController控制器,自动注入RestTemplate,去调用提供者
@RestController
public class DeptConsumerController {
// 理解:消费者,不该有service层
// RestTemplate.. 里面有方法供我们调用即可,注册到spring中
//(String url,实体, Class responseType)
//提供多种便捷访问远程http服务的方法,简单的Restful服务模板
@Autowired
private RestTemplate restTemplate;
//声明提供者的localhost路径
private static final String rest_url_prefix = "http://localhost:8001";
//调用8001提供者的控制器=>根据id查询数据
@RequestMapping("/consumer/dept/get/{id}")
public Dept get(@PathVariable("id") Long id){
// restTemplate.注意和提供者的getmapping或postmapping保持一致
return restTemplate.getForObject(rest_url_prefix+"/dept/get/"+id,Dept.class);
}
//调用8001提供者的控制器=>添加方法
@RequestMapping("/consumer/dept/add")
public Boolean add(Dept dept){
// restTemplate.注意和提供者的getmapping或postmapping保持一致
return restTemplate.postForObject(rest_url_prefix+"/dept/add",dept,Boolean.class);
}
//调用8001提供者的控制器=>查询所有
@RequestMapping("/consumer/dept/list")
public List queryall(){
// restTemplate.注意和提供者的getmapping或postmapping保持一致
return restTemplate.getForObject(rest_url_prefix+"/dept/list",List.class);
}
}
(5)创建DeptConsumer_80启动类
//消费者 运行方式80可省略 例:localhost/consumer/dept/list
@SpringBootApplication
public class DeptConsumer_80 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer_80.class,args);
}
}
(6)启动后访问http://localhost:80/consumer/dept/get/2
二、Eureka服务注册与发现
1、注册中心搭建(Eurkea服务端)——创建springcloud-eureka-7001 maven项目
(0)结构如图所示
(1)导入项目依赖
(2)配置application.ymlorg.springframework.cloud spring-cloud-starter-eureka-server1.4.6.RELEASE org.springframework.boot spring-boot-devtools
server:
port: 7001
#Eureka配置
eureka:
instance:
hostname: localhost #Eureaka服务端的实例名称
client:
register-with-eureka: false #表示是否向Eureka注册中心注册自己
fetch-registry: false #如果fetch-registry为false,则表示自己为注册中心
service-url: #监控页面
#点进去参考源码,可看到默认的url端口配置为8761,我们设置为自己的端口。
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
(3)配置EurekaServer_7001启动类,利用@EnableEurekaServer开启Eureka服务端功能
@SpringBootApplication
@EnableEurekaServer //表示为Eureka服务端的启动类,可以接收别人注册进来
public class EurekaServer_7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaServer_7001.class,args);
}
}
(4)启动成功后访问 http://localhost:7001/
可以看到eureka服务端搭建成功
(2)在application.yml添加Eureka注册中心的配置org.springframework.cloud spring-cloud-starter-eureka1.4.6.RELEASE
#Eureka的配置。 服务注册到Eureka中,需要一个路径地址
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
instance:
#修改Eureka中status的默认描述信息。不配置默认为DESKTOP-XXX描述
instance-id: springcloud-provider-dept-8001
(3)在主启动类DeptProvider_8001 上加上@EnableEurekaClient注解
@SpringBootApplication
@EnableEurekaClient//在服务启动后,自动注册到Eureka注册中心中
public class DeptProvider_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider_8001.class,args);
}
}
(4)启动主启动类DeptProvider_8001,查看Eureka注册中心http://localhost:7001/
(5)自我保护机制——关闭服务提供者DeptProvider_8001后,Eureka注册中心监控页面过几分钟会出现预警信息
注意:注册进注册中心的服务一旦下线后,重新上线,需要重启Eureka注册中心
org.springframework.boot
spring-boot-starter-actuator
2.5.2
ii ) 在application.yml中添加配置
#info配置 Eureka的status的xx/info链接点开后的info监控信息。没有太大意义 info: app.name: APP的名字 company.name: 公司名字 test.name: 测试iii)重启eureka注册中心和8001服务,显示正常了 (7)配置 Eureka的status的xx/info链接点开后的真实ip地址
application如下配置后,eureka注册中心会显示出链接的真实ip地址,而不再是desptop …链接 默认是:不显示 false
prefer-ip-address: true #改为true后 Eureka中的status就会显示真实ip地址
@SpringBootApplication
@EnableEurekaClient//在服务启动后,自动注册到Eureka注册中心中
@EnableDiscoveryClient //注册进来的微服务,获取一些信息。服务发现,扩展内容
public class DeptProvider_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider_8001.class,args);
}
}
(2)注入并调用DiscoveryClient——在8001的 DeptController 控制器中新增
//获取一些配置的信息,得到具体的微服务
@Autowired
private DiscoveryClient client;
//注册进来的微服务,获取一些信息。没有实际作用
@RequestMapping("/dept/discovery")
public Object discovery(){
//获取微服务列表的清单
List services = client.getServices();
System.out.println("discovery=>services "+services);
//得到一个具体的微服务信息,通过具体的微服务id,7001中的applicationName
List instances = client.getInstances("SPRINGCLOUD-PROVIDER-DEPT");
for (ServiceInstance instance : instances) {
System.out.println(
instance.getHost()+"ttt"+
instance.getPort()+"ttt"+
instance.getUri()+"ttt"+
instance.getServiceId());
}
return this.client;
}
三、搭建Eureka注册中心的服务端集群,并将服务提供者(生产者)注册进集群
1、创建项目
创建 springcloud-eureka-7002 Maven项目
创建 springcloud-eureka-7003 Maven项目
(2)配置hosts文件org.springframework.cloud spring-cloud-starter-eureka-server1.4.6.RELEASE org.springframework.boot spring-boot-devtools
修改C盘的hosts文件,用于模拟集群域名映射
(3)配置application.yml 修改7001的application.ymlserver:
port: 7001
#Eureka配置
eureka:
instance:
hostname: eureka7001.com #Eureaka服务端的实例名称
client:
register-with-eureka: false #表示是否向Eureka注册中心注册自己
fetch-registry: false #如果fetch-registry为false,则表示自己为注册中心
service-url: #监控页面
#单机:点进去参考源码,可看到默认的url端口配置为8761,我们设置为自己的端口。
#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
#集群(除自身外 关联其他所有)
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
配置7002的application.yml
server:
port: 7002
#Eureka配置
eureka:
instance:
hostname: eureka7002.com #Eureaka服务端的实例名称
client:
register-with-eureka: false #表示是否向Eureka注册中心注册自己
fetch-registry: false #如果fetch-registry为false,则表示自己为注册中心
service-url: #监控页面
#单机:点进去参考源码,可看到默认的url端口配置为8761,我们设置为自己的端口。
#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
#集群(除自身外 关联其他所有)
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/
配置7003的application.yml
server:
port: 7003
#Eureka配置
eureka:
instance:
hostname: eureka7003.com #Eureaka服务端的实例名称
client:
register-with-eureka: false #表示是否向Eureka注册中心注册自己
fetch-registry: false #如果fetch-registry为false,则表示自己为注册中心
service-url: #监控页面
#单机:点进去参考源码,可看到默认的url端口配置为8761,我们设置为自己的端口。
#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
#集群(除自身外 关联其他所有)
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7001.com:7001/eureka/
(4)分别创建启动类
2、分别启动项目7001、7002、7003这3个Eureka注册中心
(1)访问Eureka7001
(2)访问Eureka7002
(3)访问Eureka7003
3、将8001服务提供者注册到注册中心集群中来
修改springcloud-provider-dept-8001的application.yml Eureka服务注册defaultZone地址
#Eureka配置
eureka:
instance:
#修改Eureka中status的默认描述信息。不配置默认为DESKTOP-XXX描述
instance-id: springcloud-provider-dept-8001
client:
service-url: #监控页面
defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/
4、启动8001服务,查看注册中心集群7001、7002、7003
(1)服务提供者8001成功注册到注册中心7001
(2)服务提供者8001成功注册到注册中心7002
(3)服务提供者8001成功注册到注册中心7003
中途总结:至目前为止,只是将服务提供者注入集群种,服务提供者有Eureka相关依赖,注册中心有Eureka相关依赖,而消费者目前未参与
四、服务的消费者连接注册中心(附带配置负载均衡ribbon)——改造消费者
1、改造消费者——连接注册中心
(1)consumer_80项目中新增Eureka依赖,以及负载均衡ribbon依赖
(2)配置消费者的负载均衡——在 config类中加入@loadBalanced 注解。实现负载均衡,消费者想要通过Eureka注册中心远程调用服务提供者必须在此处配置负载均衡策略org.springframework.cloud spring-cloud-starter-eureka1.4.6.RELEASE org.springframework.cloud spring-cloud-starter-ribbon1.4.6.RELEASE
@Configuration
public class ConfigBean {//@Configuration=spring的 application.xml
//配置负载均衡实现RestTemplate
@Bean
@LoadBalanced //ribbon负载均衡的作用
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
(3)在application.yml中添加Eureka集群的配置(也可以配置单机版)
server:
port: 80
#Eureka配置
eureka:
client:
register-with-eureka: false #不向Eureka中注册自己
service-url:
defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/
(4)修改DeptConsumerController中的Rest的路径
//声明提供者的localhost路径 //private static final String rest_url_prefix = "http://localhost:8001"; //通过ribbon去实现负载均衡,这里服务应该是一个变量,通过服务名来访问 * private static final String rest_url_prefix = "http://SPRINGCLOUD-PROVIDER-DEPT";(5)在消费者80服务启动类加上@EnableEurekaClient的注解
//访问:localhost/consumer/dept/list
//Ribbon 和 Eureka 整合后,客户端可直接调用,不用关心Ip地址和端口号,会在定义的多个地址中随机选择
@SpringBootApplication
@EnableEurekaClient//在服务启动后,自动注册到Eureka注册中心中
public class DeptConsumer_80 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer_80.class,args);
}
}
(6)访问localhost/consumer/dept/list 查出所有数据
2、测试负载均衡
(1)创建多个数据库
CREATE TABLE `dept` (
`deptno` bigint(20) NOT NULL AUTO_INCREMENT,
`dname` varchar(60) DEFAULT NULL,
`db_source` varchar(60) DEFAULT NULL,
PRIMARY KEY (`deptno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='部门表'
INSERT INTO dept(dname,db_source) VALUES ('开发部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES ('项目部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES ('研发部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES ('运维部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES ('市场部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES ('人事部',DATABASE());
(2)创建多个服务提供者(生产者)
创建maven项目 springcloud-provider-dept-8002
复制8001提供方的所有内容.
修改application.yml文件
分别更改application.yml中的数据库的地址和端口号,更改启动类的名称,修改Eureka中status的默认描述信息
server:
port: 8002
#mybatis配置
mybatis:
type-aliases-package: com.yzw.springcloud.pojo
config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*.xml
spring:
application:
name: springcloud-provider-dept
#数据源设置
datasource:
type: com.alibaba.druid.pool.DruidDataSource #数据源为druid
driver-class-name: com.mysql.jdbc.Driver #数据库驱动
url: jdbc:mysql://localhost:3306/springcloud-demo2?useUnicode=true&characterEncoding=utf-8&servetTimeZone=Asia/Shanghai
username: root
password: 123456
#Eureka配置
eureka:
instance:
#修改Eureka中status的默认描述信息。不配置默认为DESKTOP-XXX描述
instance-id: springcloud-provider-dept-8002
client:
service-url: #监控页面
defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/
#info配置 Eureka的status的xx/info链接点开后的info监控信息。没有太大意义
info:
app.name: sss
company.name: sss
test.name: sss
创建maven项目 springcloud-provider-dept-8003
复制8001提供方的所有内容.
修改application.yml文件
分别更改application.yml中的数据库的地址和端口号,更改启动类的名称,修改Eureka中status的默认描述信息
server:
port: 8003
#mybatis配置
mybatis:
type-aliases-package: com.yzw.springcloud.pojo
config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*.xml
spring:
application:
name: springcloud-provider-dept
#数据源设置
datasource:
type: com.alibaba.druid.pool.DruidDataSource #数据源为druid
driver-class-name: com.mysql.jdbc.Driver #数据库驱动
url: jdbc:mysql://localhost:3306/springcloud-demo3?useUnicode=true&characterEncoding=utf-8&servetTimeZone=Asia/Shanghai
username: root
password: 123456
#Eureka配置
eureka:
instance:
#修改Eureka中status的默认描述信息。不配置默认为DESKTOP-XXX描述
instance-id: springcloud-provider-dept-8003
client:
service-url: #监控页面
defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/
#info配置 Eureka的status的xx/info链接点开后的info监控信息。没有太大意义
info:
app.name: sss
company.name: sss
test.name: sss
(3) 测试效果
i)启动服务
启动Eureka7001 7002 7003注册中心集群
启动服务提供者8001 8002 8003
启动消费者80
ii)多次访问
localhost/consumer/dept/list 访问,多次刷新,我们这次可以直观的看到显示不同服务的数据,这次我们可直观的感受到负载均衡的应用。
成功,使用Ribbon实现负载均衡已完成。
3、自定义负载均衡策略 (1) 在主目录外创建myrule文件包官网指出:
这个自定义的类不能放在@ComponentScan所扫描的当前包以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,也就是我们达不到特殊化指定的目的了。推荐在springboot主程序扫描的包范围之外进行自定义配置类。
(2) 在myrule包下创建RuleConfig//自定义Ribbon配置的负载均衡类,客户端RibbonConfiguration中已存在的组件与FooConfiguration中的任何组件组成(后者通常会覆盖前者)
//自定义的组件请注意 它不在|程序的上下文的ComponentScan中,所以要放在单独的不重叠的包中
@Configuration
public class RuleConfig {
@Bean
public IRule myRule(){
//默认是轮询,现在我们自定义为DiyRandomRule 自定义负载均衡
return new DiyRandomRule();
}
}
(3) 在myrule包下创建DiyRandomRule,双击shift搜索 RandomRule 全部复制,改为自己自定义算法负载均衡
public class DiyRandomRule extends AbstractLoadBalancerRule {
//代码全是复制的 DiyRandomRule.class的,自定义负载均衡需要自己修改
//当前自定义负载均衡:
//每个服务访问5次。换下一个服务
//total=0,默认=0,如果=5,指向下一个服务节点
//index=0,默认0,如果total=5,则inedx+1
private int totla=0;//被调用的次数
private int currentIndex=0;//当前是谁在提供服务
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
} else {
Server server = null;
while (server == null) {
if (Thread.interrupted()) {
return null;
}
List upList = lb.getReachableServers();//获得活着的服务
List allList = lb.getAllServers();//获得全部的服务
int serverCount = allList.size();
if (serverCount == 0) {
return null;
}
//int index = this.chooseRandomInt(serverCount);//生成区间随机数
//server = (Server) upList.get(index);//从活着的服务中,随机获取一个
//================自定义负载均衡算法==================
if(totla<5){
server = upList.get(currentIndex);
totla++;
}else{
totla=0;
currentIndex++;
if (currentIndex>=upList.size()){//当前节点大于活着的数量
currentIndex = 0;
}
server=upList.get(currentIndex);//从活着的服务中,获取指定的服务来进行操作
}
//====================================================
if (server == null) {
Thread.yield();
} else {
if (server.isAlive()) {
return server;
}
server = null;
Thread.yield();
}
}
return server;
}
}
protected int chooseRandomInt(int serverCount) {
return ThreadLocalRandom.current().nextInt(serverCount);
}
public Server choose(Object key) {
return this.choose(this.getLoadBalancer(), key);
}
public void initWithNiwsConfig(IClientConfig clientConfig) {
}
}
(4) 启动器上添加自定义负载均衡配置引用的@RibbonClien注解——@RibbonClient(name=“SPRINGCLOUD-PROVIDER-DEPT”,configuration = RuleConfig.class)
@SpringBootApplication
@EnableEurekaClient//在服务启动后,自动注册到Eureka注册中心中
//在微服务启动的时候就能去加载我们自定义Ribbon配置的负载均衡类,自定义为跳转5次切换节点
@RibbonClient(name="SPRINGCLOUD-PROVIDER-DEPT",configuration = RuleConfig.class)
public class DeptConsumer_80 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer_80.class,args);
}
}
(5) 测试效果
启动多个注册中心,服务提供者和80消费端口。
多次刷新访问 localhost/consumer/dept/list
我们可直观的看到页面每刷新五次值会更改
至此 Ribbon自定负载均衡完成
五、Feign(替换RestTemplate的接口写法) 1、改造springcloud-api模块当然也可以新建一个feign接口模块
(1)新建包service,创建查询部门接口DeptClientService@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT")
public interface DeptClientService {
@GetMapping("/dept/get/{id}")
public Dept queryById(@PathVariable("id") Long id);
@PostMapping("/dept/list")
public List queryAll();
@GetMapping("/dept/add")
public boolean addDept(Dept dept);
}
(2)新增加Feign依赖
2、新建springcloud-consumer-dept-feign模块,作为消费者(使用feign) (1)复制springcloud-consumer-dept-80项目的所有内容,更改启动类名称为FeignDeptConsumer_80。org.springframework.cloud spring-cloud-starter-feign1.4.6.RELEASE
项目结构如图所示
(3)修改DeptConsumerController的内容com.yzw springcloud-api1.0-SNAPSHOT org.springframework.boot spring-boot-starter-weborg.springframework.cloud spring-cloud-starter-eureka1.4.6.RELEASE org.springframework.cloud spring-cloud-starter-feign1.4.6.RELEASE
@RestController
public class DeptConsumerController {
//Feign面向接口编程
//springcloud-api模块下的接口service
@Autowired
private DeptClientService deptClientService =null;
//添加数据
@RequestMapping("/consumer/dept/add")
public boolean add(Dept dept){
return deptClientService.addDept(dept);
}
//通过id查询
@RequestMapping("/consumer/dept/get/{id}")
public Dept get(@PathVariable("id") Long id){
return deptClientService.queryById(id);
}
//查询所有
@RequestMapping("/consumer/dept/list")
public List queryAll(){
return deptClientService.queryAll();
}
}
(4)在DeptConsumer_feign启动类加上Feign相关注解@EnableFeignClients(…)
//消费者 运行方式80可省略 例:localhost/consumer/dept/list
@SpringBootApplication
@EnableEurekaClient //在服务启动后,自动注册到Eureka注册中心中
@EnableFeignClients(basePackages = {"com.yzw.springCloud"}) //Feign被扫描到
public class DeptConsumer_feign {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer_feign.class,args);
}
}
六、Hystrix
1、服务熔断(服务提供者—生产者)
(1)创建服务提供者—springcloud-provider-dept-hystrix-8001
复制springcloud-provider-dept-8001项目的所有内容
(2)修改启动类名字为:eptProviderHystrix_8001 (3)修改application.yml中的Eureka的instance-id为 springcloud-provider-dept-hystrix-8001 (4)导入springcloud-provider-dept-8001所有依赖,再加一个Hystrix服务熔断依赖(5)更改DeptController的所有内容org.springframework.cloud spring-cloud-starter-hystrix1.4.6.RELEASE
//提供Restful服务
@RestController
public class DeptController{
@Autowired
private DeptService deptService;
@RequestMapping("/dept/get/{id}")
@HystrixCommand(fallbackMethod = "hystrixGet") //如果失败 去调用Hystrix的备选方案
public Dept get(@PathVariable("id") Long id){
Dept dept = deptService.queryById(id);
if (dept==null){//如果当前id值为空 抛出异常
throw new RuntimeException("id=> "+ id+"不存在该用户,或者该信息无法找到");
}
return dept;
}
//如果出现异常 采取Hystrix的备选方案
public Dept hystrixGet(@PathVariable("id") Long id){
return new Dept()
.setDeptno(id)
.setDname("没找到,服务提供方发生了熔断");
}
}
(6)在DeptProviderHystrix_8001的启动类上加上@EnableCircuitBreaker服务熔断 断路器的支持注解
@SpringBootApplication
@EnableEurekaClient//在服务启动后,自动注册到Eureka注册中心中
@EnableDiscoveryClient //注册进来的微服务,获取一些信息。服务发现,扩展内容
@EnableCircuitBreaker //添加Hystrix服务熔断 断路器的支持
public class DeptProviderHystrix_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProviderHystrix_8001.class,args);
}
}
(7)测试效果
访问http://localhost:8001/dept/get/1,找到了
访问http://localhost:8001/dept/get/100,找不到,发生熔断
//Hystrix 降级,当服务端关闭后的提示信息
@Component
public class DeptClientServiceFallbackFactory implements FallbackFactory {
@Override
public DeptClientService create(Throwable throwable) {
return new DeptClientService() {
@Override
public Dept queryById(Long id) {
return new Dept()
.setDeptno(id)
.setDname("id=>" +id+"没有对应的信息,客户端提供了降级的信息,这个服务现在已经关闭")
.setDb_source("已降级 未查找到数据");
}
@Override
public List queryAll() {
return null;
}
@Override
public boolean addDept(Dept dept) {
return false;
}
};
}
}
ii) 在DeptClientService中添加服务降级的注解,@FeignClient(value=“xxx”,fallbackFactory=“降级的类”)
@Component
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {
@GetMapping("/dept/get/{id}")
public Dept queryById(@PathVariable("id") Long id);
@PostMapping("/dept/list")
public List queryAll();
@PostMapping("/dept/add")
public boolean addDept(Dept dept);
}
(2)改造springcloud-consumer-dept-feign模块
修改application.yml,新增Hystrix的降级配置
#开启降级Feign Hystrix
feign:
hystrix:
enabled: true
(3)测试效果
服务提供方关闭服务前:
服务提供方关闭服务后:发生服务降级(消费者端)
将 springcloud-consumer-dept-80 项目中所有依赖复制到当前项目,并添加Hystrix和dashboard流监控依赖
(2)创建application.yml,配置启动端口org.springframework.cloud spring-cloud-starter-hystrix1.4.6.RELEASE org.springframework.cloud spring-cloud-starter-hystrix-dashboard1.4.6.RELEASE
#Hystrix的dashboard流监控 端口
server:
port: 9001
#Eureka的配置。 服务注册到Eureka中,需要一个路径地址
eureka:
client:
register-with-eureka: false #不向Eureka中注册自己
service-url:
#defaultZone: http://localhost:7001/eureka,http://localhost:7002/eureka,http://localhost:7003/eureka
defaultZone: http://localhost:7001/eureka
(3)配置DeptConsumerDashboard_9001启动类
@SpringBootApplication
@EnableHystrixDashboard//开启监控
public class DeptConsumerDashboard_9001 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumerDashboard_9001.class,args);
}
}
(4)启动当前9001监控服务
访问:localhost:9001/hystrix
说明监控服务搭建成功
添加依赖
(2)在DeptProviderHystrix_8001 启动类中 添加 dashboard监控配置,增加一个Servletorg.springframework.boot spring-boot-starter-actuator
@SpringBootApplication
@EnableEurekaClient//在服务启动后,自动注册到Eureka注册中心中
@EnableDiscoveryClient //注册进来的微服务,获取一些信息。服务发现,扩展内容
@EnableCircuitBreaker //添加Hystrix服务熔断 断路器的支持
public class DeptProviderHystrix_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProviderHystrix_8001.class,args);
}
//增加一个servlet,配合dashboard监控使用,固定的代码 http://localhost:8001/actuator/hystrix.stream访问监控
@Bean
public ServletRegistrationBean hystrixMetricsStreamServlet(){
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
registrationBean.addUrlMappings("/actuator/hystrix.stream");
return registrationBean;
}
}
(3)启动hystrix8001服务端
(4)查看监控
i)被监控端直接看
页面输入localhost:8001/actuator/hystrix.stream,可以看到监控捕获到的内容
查询一条值信息,可以看到会加载到一些监控信息
访问:localhost:9001/hystrix ,输入要监控的页面地址,时间及标题设置
(1)创建springcloud-consumer-hystrix-dashboard项目,复制springcloud-consumer-dept-80项目所有依赖,导入Hystrix和dashboard依赖
(2)编写application.yml端口配置
(3)配置监控的启动类,配置监控注解
(4)切换至被监控服务子模块,添加actuator相关监控信息依赖
(5)要监控流,需要在hystrix8001启动类中配置流监控
(6)启动注册中心,hystrix8001服务,9001监控测试
3、创建application.yml,配置org.springframework.cloud spring-cloud-starter-zuul1.4.6.RELEASE
server:
port: 9527
spring:
application:
name: springcloud-zuul
eureka:
client:
service-url:
#defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/
defaultZone: http://localhost:7001/eureka/
instance:
#修改Eureka中status的默认描述信息。不配置默认为DESKTOP-XXX描述
instance-id: zuul9527.com #自定义名称
prefer-ip-address: true #改为true后 Eureka中的status就会显示真实ip地址
4、启动Eureka注册中心7001,启动一个提供者8001,启动9527
5、配置启动类,开启Zuul
@SpringBootApplication
@EnableZuulProxy // 开启Zuul
public class ZuulApplication_9527 {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication_9527.class,args);
}
}
6、测试
访问http://localhost:9527/springcloud-provider-dept/dept/get/3
zuul:
routes:
mydept.serviceId: springcloud-provider-dept
#之前的查询链接地址 http://localhost:9527/springcloud-provider-dept/dept/get/1
#现在的查询链接地址,配置后为 http://localhost:9527/mydept/dept/get/1
#两者都皆可访问(原路径+现配路径)。配置自定义的前缀后 可不让客户端知道真实的ip地址
mydept.path: /mydept/**
#加上此配置后 原路径不能访问(springcloud-provider-dept/dept/get/6),只能通过自定义的规则路径访问。
#ignored-services: springcloud-provider-dept
#星号(*) 隐藏全部的项目真实名字
ignored-services: "*"
prefix: /li #设置公共的地址前缀 配置后链接为:localhost:9527/li/mydept/dept/get/11
八、SpringCloud config分布式配置
Spring Cloud Config 分为服务端和客户端两部分;
1、服务端 (1)在gitee上创建一个仓库,如果是私有仓库下面yml文件中得配置账号密码 i)Git大全# 显示当前的Git配置 $ git config --list # 设置提交代码时的用户信息 $ git config --global user.name "[name]" $ git config --global user.email "[email address]"ii) clone远程仓库
复制仓库中的 https 中的地址,直接 在 GitBash中,git clone 复制的地址
iii) 创建application.yml,修改文件spring:
profiles:
active: dev
---
spring:
profiles: dev
application:
name: springcloud-config-dev
---
spring:
profiles: test
application:
name: springcloud-config-test
iiii) 推送到gitee上
git add . 将文件添加到暂存区 git status 查看状态 git commit -m “一次提交” 本地提交,-m为提交时写的信息 git push origin master 提交到远程的当前路径分枝(2)服务端连接git配置 i)新建项目 springcloud-config-server-3344 ii) 导入依赖:spring-cloud-config-server
iii) 配置application.ymlorg.springframework.boot spring-boot-starter-weborg.springframework.cloud spring-cloud-config-server2.1.1.RELEASE org.springframework.boot spring-boot-starter-actuator
server:
port: 3344
spring:
application:
name: springcloud-config-server
#连接远程的仓库
cloud:
config:
server:
git:
uri: https://gitee.com/zhengwen_y/springcloud-config.git #自己远程仓库的https地址
# 通过 config-server可以连接到git,访问其中的资源以及配置~
username: (gitee的账号)
password: (gitee的密码)
iiii)创建启动类Config_Server_3344,开启@EnableConfigServer //开启配置服务
@SpringBootApplication
@EnableConfigServer //开启配置服务
public class Config_Server_3344 {
public static void main(String[] args) {
SpringApplication.run(Config_Server_3344.class,args);
}
}
iiiii)启动 Config_Server_3344服务
浏览器输入 localhost:3344/application-dev.yml
浏览器输入 localhost:3344/application-test.yml
2、客户端 (1) 创建一个配置文件 config-client.yml推送到远程仓库中#启动环境选择的配置
spring:
profiles:
active: dev
#springboot启动多环境的配置
---
server:
port: 8201
#spring的配置
spring:
profiles: dev
application:
name: springcloud-config-client-dev
#Eureka的配置。 服务注册到Eureka中,需要一个路径地址
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
---
server:
port: 8202
#spring的配置
spring:
profiles: test
application:
name: springcloud-config-client-test
#Eureka的配置。 服务注册到Eureka中,需要一个路径地址
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
(2)客户端连接配置中心服务端
i)创建springcloud-config-client子模块
ii)导入依赖
iii) 创建application.yml,并配置org.springframework.boot spring-boot-starter-weborg.springframework.cloud spring-cloud-starter-config2.1.1.RELEASE org.springframework.boot spring-boot-starter-actuator
#用户级别的配置 配置去读取谁
spring:
application:
name: springcloud-config-client
iiii) 创建bootstrap.yml,配置以下内容。注意创建此yml之前一定要导入springcloud-config的配置依赖
# 系统级别的配置
spring:
cloud:
config:
name: config-client # 需要从git上读取的资源名称,不要后缀
profile: dev #dev环境端口:8201 test环境端口:8202
label: master #需要在git上的哪个分支拿
#连接到3344服务,中转站的形式连接服务端访问远程地址
uri: http://localhost:3344 #config的服务端
iiiii)创建ConfigClientController控制器
//@Value为git上的client-config的值
@RestController
public class ConfigClientController {
@Value("${spring.application.name}")
private String applicationName;
@Value("${eureka.client.service-url.defaultZone}")
private String eurekaServer;
@Value("${server.port}")
private String port;
@RequestMapping("/config")
public String getConfig(){
return "applicationName: "+applicationName+
"eurekaServer: "+eurekaServer+
"port: "+port;
}
}
iiiiii)创建启动类
@SpringBootApplication
public class Config_Client {
public static void main(String[] args) {
SpringApplication.run(Config_Client .class,args);
}
}
(3)测试
启动客户端服务(i)通过服务端查看config-client的文件内容:
localhost:3344/config-client-dev.yml 不同的启动环境 查到不同的查询到仓库配置的config-client的信息
localhost:3344/config-client-test.yml 不同的启动环境 查到不同的查询到仓库配置的config-client的信息
读取的端口号就是config-client.yml中配置的端口号8201
访问:http://localhost:8201/config/
#启动环境选择的配置
spring:
profiles:
active: dev
---
server:
port: 7001
#spring的配置
spring:
profiles: dev
application:
name: springcloud-config-eureka-dev
#Eureka配置
eureka:
instance:
hostname: eureka7001.com #Eureaka服务端的实例名称
client:
register-with-eureka: false #表示是否向Eureka注册中心注册自己
fetch-registry: false #如果fetch-registry为false,则表示自己为注册中心
service-url: #监控页面
#单机:点进去参考源码,可看到默认的url端口配置为8761,我们设置为自己的端口。
#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
#集群(除自身外 关联其他所有)
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
---
server:
port: 7001
#spring的配置
spring:
profiles: test
application:
name: springcloud-config-eureka-test
#Eureka配置
eureka:
instance:
hostname: eureka7001.com #Eureaka服务端的实例名称
client:
register-with-eureka: false #表示是否向Eureka注册中心注册自己
fetch-registry: false #如果fetch-registry为false,则表示自己为注册中心
service-url: #监控页面
#单机:点进去参考源码,可看到默认的url端口配置为8761,我们设置为自己的端口。
#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
#集群(除自身外 关联其他所有)
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
(2)推送到远程仓库
(3)创建 项目springcloud-config-eureka-7001,利用远程仓库的config-eureka.yml文件启动
(4)导入pom依赖
(5)application.yml所有配置:org.springframework.cloud spring-cloud-starter-eureka-server1.4.6.RELEASE org.springframework.cloud spring-cloud-starter-config2.1.1.RELEASE
spring:
application:
name: sorubgckiyd-config-eureka-7001
(6)创建bootstrap.yml 注意创建此yml之前一定要导入springcloud-config的配置依赖
# 系统级别的配置
spring:
cloud:
config:
name: config-eureka # 需要从git上读取的资源名称,不要后缀
profile: dev #dev环境端口:8201 test环境端口:8202
label: master #需要在git上的哪个分支拿
#连接到3344服务,中转站的形式连接服务端访问远程地址
uri: http://localhost:3344
(7)配置服务器端进行预读取
访问:localhost:3344/config-eureka-dev.yml
@SpringBootApplication
@EnableEurekaServer //表示为Eureka服务端的启动类,可以接收别人注册进来
public class ConfigEureka_7001 {
public static void main(String[] args) {
SpringApplication.run(ConfigEureka_7001.class,args);
}
}
(9)启动后访问,按照config-eureka里面配置的端口,表示eureka-7001用远程仓库的配置文件启动成功
4、用远程配置文件启动provider-8001
(1)创建 config-dept.yml
#启动环境选择的配置
spring:
profiles:
active: dev
---
server:
port: 8001
#mybatis配置
mybatis:
type-aliases-package: com.yzw.springcloud.pojo
config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*.xml
#spring的配置
spring:
profiles: dev
application:
name: springcloud-config-dept-dev
#数据源的配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource #数据源为druid
driver-class-name: com.mysql.jdbc.Driver #数据库驱动
url: jdbc:mysql://localhost:3306/springcloud-demo1?useUnicode=true&characterEncoding=utf-8&servetTimeZone=Asia/Shanghai
username: root
password: 123456
#Eureka的配置。 服务注册到Eureka中,需要一个路径地址
eureka:
client:
service-url:
#defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/
defaultZone: http://localhost:7001/eureka/
instance:
#修改Eureka中status的默认描述信息。不配置默认为DESKTOP-XXX描述
instance-id: springcloud-provider-dept-8001
prefer-ip-address: true #改为true后 Eureka中的status就会显示真实ip地址
#info配置 Eureka的status的xx/info链接点开后的info监控信息。没有太大意义
info:
app.name: ti zi zui bang,jiayou
company.name: tizi.lemon.com
test.name: hahah test
---
server:
port: 8001
#mybatis配置
mybatis:
type-aliases-package: com.yzw.springcloud.pojo
config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*.xml
#spring的配置
spring:
profiles: test
application:
name: springcloud-config-dept-test
#数据源的配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource #数据源为druid
driver-class-name: com.mysql.jdbc.Driver #数据库驱动
url: jdbc:mysql://localhost:3306/springcloud-demo2?useUnicode=true&characterEncoding=utf-8&servetTimeZone=Asia/Shanghai
username: root
password: 123456
#Eureka的配置。 服务注册到Eureka中,需要一个路径地址
eureka:
client:
service-url:
#defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/
defaultZone: http://localhost:7001/eureka/
instance:
#修改Eureka中status的默认描述信息。不配置默认为DESKTOP-XXX描述
instance-id: springcloud-provider-dept8001
prefer-ip-address: true #改为true后 Eureka中的status就会显示真实ip地址
#info配置 Eureka的status的xx/info链接点开后的info监控信息。没有太大意义
info:
app.name: ti zi zui bang,jiayou
company.name: tizi.lemon.com
test.name: hahah test
(2)推送到远程仓库
(3)创建 项目 springcloud-config-provider-dept-8001 ,利用远程仓库的config-dept.yml文件启动
(4)复制 springcloud-provider-dept-8001 项目所有的内容及依赖
(5)application.yml所有配置:
spring:
application:
name: springcloud-config-provider-dept-8001
(6)创建bootstrap.yml 注意创建此yml之前一定要导入springcloud-config的配置依赖
# 系统级别的配置
spring:
cloud:
config:
name: config-dept # 需要从git上读取的资源名称,不要后缀
profile: dev #dev环境端口:8201 test环境端口:8202
label: master #需要在git上的哪个分支拿
#连接到3344服务,中转站的形式连接服务端访问远程地址
uri: http://localhost:3344
(7)配置服务器端进行预读取
访问:localhost:3344/config-dept-dev.yml
@SpringBootApplication
@EnableDiscoveryClient
public class ConfigDept_8001 {
public static void main(String[] args) {
SpringApplication.run(ConfigDept_8001.class);
}
}
(9)启动后访问,按照config-dept里面配置的端口,表示 springcloud-config-provider-dept-8001用远程仓库的配置文件启动成功,可以正常访问8001端口



