环境搭建
服务间接口调用,GET接收对象参数可以使用@SpringQueryMap注解
@SpringQueryMap
-
创建父项目并添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR1</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>1.5.9.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
-
创建一个子项目,其中创建一个实体类
-
添加自动生成getter,setter等方法的依赖
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.6</version> </dependency>
-
创建实体
@AllArgsConstructor //生成全参构造 @NoArgsConstructor //生成无参构造 @ToString //生成tostring方法 @Accessors(chain = true) //链式,setter方法返回当前对象 @Data //生成get,set方法 public class Dept implements Serializable { private int deptno; private String dname; private String db_source; }
-
-
创建服务提供者
-
创建application.properties
server.port=8001 mybatis.config-location=classpath:mybatis/mybatis.cfg.xml mybatis.type-aliases-package=com.xdd.springcloud.model mybatis.mapper-locations=classpath:mybatis/mapper/**/*.xml spring.application.name=microservicecloud-dept spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/cloudDB01 spring.datasource.username=root spring.datasource.password=521314 spring.datasource.dbcp2.min-idle=5 spring.datasource.dbcp2.initial-size=5 spring.datasource.dbcp2.max-total=5 spring.datasource.dbcp2.max-wait-millis=2000
-
创建DeptMapper.java及DeptMapper.xml
@Mapper public interface DeptMapper { public Dept findByDeptno(int deptno); public List<Dept> findAll(); } <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.xdd.springcloud.mapper.DeptMapper"> <select id="findByDeptno" parameterType="int" resultType="com.xdd.springcloud.model.Dept" > select *from dept where deptno=#{deptno} </select> <select id="findAll" resultType="com.xdd.springcloud.model.Dept"> SELECT *FROM dept; </select> </mapper>
-
创建service及其实现
public interface DeptService { public boolean add(Dept dept); public Dept get(int deptno); public List<Dept> list(); } @Service public class DeptServiceImpl implements DeptService { @Autowired private DeptMapper deptMapper; @Override public Dept get(int deptno) { return deptMapper.findByDeptno(deptno); } @Override public List<Dept> list() { return deptMapper.findAll(); } }
-
创建cotroller
@RestController public class DeptConsumerController { private static final String REST_URL="http://localhost:8001/"; @Autowired RestTemplate restTemplate; @RequestMapping("/consumer/dept/get/{deptno}") public Dept get(@PathVariable("deptno") int deptno){ return restTemplate.getForObject(REST_URL+"/dept/get/"+deptno,Dept.class); } @RequestMapping("/consumer/dept/list") public List<Dept> list(){ return restTemplate.getForObject(REST_URL+"/dept/list",List.class); } }
-
创建主启动类
@SpringBootApplication public class DeptProvider8001_App { public static void main(String[] args) { SpringApplication.run(DeptProvider8001_App.class,args); } }
-
-
创建服务消费者
-
创建application.properties
server=80
-
创建ConfigBean.java用于获取RestTemplate对象
@Configuration public class ConfigBean { @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } }
-
创建controller
@RestController public class DeptConsumerController { private static final String REST_URL="http://localhost:8001/"; @Autowired RestTemplate restTemplate; @RequestMapping("/consumer/dept/get/{deptno}") public Dept get(@PathVariable("deptno") int deptno){ return restTemplate.getForObject(REST_URL+"/dept/get/"+deptno,Dept.class); } @RequestMapping("/consumer/dept/list") public List<Dept> list(){ return restTemplate.getForObject(REST_URL+"/dept/list",List.class); } }
-
创建主启动类
@SpringBootApplication public class DeptConsumer_App { public static void main(String[] args) { SpringApplication.run(DeptConsumer_App.class,args); } }
-
服务注册与发现(Eureka)
- 创建注册中心
-
添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> <!--修改后立即生效,热部署--> <dependency> <groupId>org.springframework</groupId> <artifactId>springloaded</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency>
-
创建配置文件application.properties
server.port=7001 eureka.instance.hostname=localhost //eureka服务端的名字 eureka.client.fetch-registry=false eureka.client.register-with-eureka=false //是否向注册中心注册自己 eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
-
创建主启动类
@SpringBootApplication @EnableEurekaServer public class Eureka_Server7001_App { public static void main(String[] args) { SpringApplication.run(Eureka_Server7001_App.class,args); } }
-
- 将服务注册到注册中心
-
在服务提供者pom.xml中添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency>
-
在application.properties中添加配置:
eureka.client.service-url.defaultZone=http://localhost:7001/eureka
-
在主启动类添加注解 @EnableEurekaClient
-
主机映射名称修改:
eureka.instance.instance-id=microservicecloud-dept8001 //修改主机名映射名字 eureka.instance.prefer-ip-address=true //设置映射访问路径可以显示ip
-
info信息的完善:
-
添加依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
-
在父工程pom.xml添加配置:
<build> <finalName>microservicecloud</finalName> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <configuration> <delimiters> <delimit>$</delimit> </delimiters> </configuration> </plugin> </plugins> </build>
-
在application.properties中添加info信息:
info.build.aftifactId=${project.artifactId} info.version=${project.version} ......
-
-
- 服务的发现
-
在提供者控制器中添加DiscoveryClient:
@AutoWired private DiscoveryClient discoveryClient; @RequestMapping("/dept/discovery") public Object discovery(){ List<String> list=discoveryClient.getServices(); System.out.println(list); List<ServiceInstance> serviceInstanceList=discoveryClient.getInstances("MICROSERVICECLOUD-DEPT"); for (ServiceInstance serviceInstance:serviceInstanceList){ System.out.println(serviceInstance.getServiceId()+"\t"+serviceInstance.getHost()+"\t"+serviceInstance.getPort()+"\t"+serviceInstance.getUri()+"\t"); } return discoveryClient; }
-
在主启动类上添加注解 @EnableDiscoveryClient
-
- Eureka集群的配置
-
分别创建多个Eureka注册中心,端口号不同(例:7001,7002,7003)
-
找到C:\Windows\System32\drivers\etc\hosts文件配置映射:
127.0.0.1 eureka7001.com 127.0.0.1 eureka7002.com 127.0.0.1 eureka7003.com
-
修改配置文件application.properties:
server.port=7001 eureka.instance.hostname=eureka7001.com eureka.client.fetch-registry=false eureka.client.register-with-eureka=false eureka.client.service-url.defaultZone=http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
-
修改提供者注册的地址:
eureka.client.service-url.defaultZone=http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
-
Ribbon负载均衡
-
在消费者中添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency>
-
修改application.properties
eureka.client.register-with-eureka=false eureka.client.service-url.defaultZone=http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
-
在ConfigBean.java的getRestTemplate方法上添加注解 @LoadBalanced:
@Configuration public class ConfigBean { @Bean @LoadBalanced //负载均衡,默认是轮询 public RestTemplate getRestTemplate(){ return new RestTemplate(); } }
-
在主启动类添加注解 @EnableEurekaClient
-
修改消费者的controller:
//private static final String REST_URL="http://localhost:8001/"; private static final String REST_URL="http://MICROSERVICECLOUD-DEPT/"; //此时才是真正的通过注册中心发现调用服务
-
创建多个提供者,与8001提供者类似,端口号不同,但spring.application.name相同
-
可以在消费者ConfigBean.java中修改负载均衡的策略:
@Configuration public class ConfigBean { @Bean @LoadBalanced //负载均衡,默认是轮询 public RestTemplate getRestTemplate(){ return new RestTemplate(); } @Bean public IRule iRule(){ return new RandomRule(); //返回一个随机算法的负载均衡对象 } }
~ ribbon负载均衡策略:
RoundRobinRule:轮询
RandomRule:随机
AvailabilityFilteringRule:先过滤掉因多次访问故障而处于断路器跳闸状态服务和并发的连接数量超过阈值的服务,然后对剩余的服务进行轮询
WeightedResponseTimeRule:根据权重,响应越快则权重越大
RetryRule: 先按照轮询获取服务,如果获取服务失败,则会在指定时间内重试,获取可用服务
BestAvailableRule:先过滤掉多次访问故障处于断路器跳闸状态的服务,然后选择一个并发量小的服务
ZoneAvoidanceRule:默认规则,复合判断server所在区域的性能和server的可用性选择服务器 -
自定义ribbon负载均衡策略(例:每个服务器执行5次)
-
在主启动类上添加注解:@RibbonClient(name = “MICROSERVICECLOUD-DEPT”,configuration = MyRandomRule.class)
-
创建自定义策略MyRandomRule.java(该类不能放在@ComponentScan所扫描的包及子包下)
public class MyRandomRule extends AbstractLoadBalancerRule { private int total=0; //当前服务被调用的次数 private int currentIndex=0; //当前的服务的索引 public Server choose(ILoadBalancer lb, Object key) { if (lb == null) { return null; } Server server = null; while (server == null) { if (Thread.interrupted()) { return null; } List<Server> upList = lb.getReachableServers(); List<Server> allList = lb.getAllServers(); int serverCount = allList.size(); if (serverCount == 0) { return null; } //每个服务器调用5次 if(total<5){ server=upList.get(currentIndex); total++; }else{ total=0; currentIndex++; if(currentIndex>=upList.size()){ currentIndex=0; } } if (server == null) { Thread.yield(); continue; } if (server.isAlive()) { return (server); } server = null; Thread.yield(); } return server; } protected int chooseRandomInt(int serverCount) { return ThreadLocalRandom.current().nextInt(serverCount); } @Override public Server choose(Object key) { return choose(getLoadBalancer(), key); } @Override public void initWithNiwsConfig(IClientConfig iClientConfig) { } }
-
Feign负载均衡(接口+注解)
-
在公共项目中创建service接口类(方法上需要有映射路径)
@FeignClient(value = "MICROSERVICECLOUD-DEPT") //value是提供者暴露的服务的名字 public interface DeptClientService { @RequestMapping("/dept/get/{deptno}") public Dept get(@PathVariable("deptno") int deptno); @RequestMapping("/dept/list") public List<Dept> list(); }
-
在消费者中创建controller调用DeptClientService的方法
@RestController public class DeptConsumerController { @Autowired DeptClientService deptClientService; @RequestMapping("/consumer/dept/get/{deptno}") public Dept get(@PathVariable("deptno") int deptno) { return deptClientService.get(deptno); } @RequestMapping("/consumer/dept/list") public List<Dept> list() { return deptClientService.list(); } }
-
在主启动类上添加注解 @EnableFeignClients(“com.xdd.springcloud”) 和 @ComponentScan(“com.xdd.springcloud”)
Hystrix断路器(服务熔断与降级)
-
在提供者中添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency>
-
在需要熔断的方法上添加注解 @HystrixCommand(fallbackMethod = “fallback”)
@HystrixCommand(fallbackMethod = "fallback") public Dept get(@PathVariable("deptno") int deptno) { Dept dept=deptService.get(deptno); if (dept==null){ throw new RuntimeException("没有相关数据"); } return dept; }
-
编写回调方法,当断路的方法发生异常的时候调用
public Dept fallback(@PathVariable("deptno") int deptno){ //参数与返回值类型与需要断路的方法相同 return new Dept().setDeptno(deptno).setDname("无").setDb_source("无数据库信息"); }
-
在主启动类上添加注解 @EnableCircuitBreaker
-
通过AOP实现服务的熔断
-
在公共类中添加一个类实现FallbackFactory,(添加注解 @Component)
@Component public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> { @Override public DeptClientService create(Throwable throwable) { return new DeptClientService() { @Override public Dept get(int deptno) { return new Dept().setDeptno(deptno).setDname("无").setDb_source("该服务已关闭,暂无相关数据库信息"); } @Override public List<Dept> list() { List list=new ArrayList<Dept>(); list.add(new Dept().setDb_source("暂无相关信息")); return list; } }; } }
-
在公共类DeptClientService.java中添加注解属性
@FeignClient(value = "MICROSERVICECLOUD-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
-
在消费者application.properties中添加配置
feign.hystrix.enable=true
-
hystrixDushboard
-
新建一个项目并添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency>
-
在提供者中添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
-
创建application.properties
server.port=9001
-
创建启动类并添加注解
@SpringBootApplication @EnableHystrixDashboard public class DeptConsumer_HystrixDashboard_App { public static void main(String[] args) { SpringApplication.run(DeptConsumer_HystrixDashboard_App.class,args); } }
-
启动项目并访问:localhost:9001/hystrix
zuul
-
创建一个项目并添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency>
-
创建application.properties
server.port=9527 spring.application.name=microservicecloud-zuul-gateway eureka.client.service-url.defaultZone=http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka eureka.instance.instance-id=microservicecloud-zuul-9527.com eureka.instance.prefer-ip-address=true
-
创建主启动类
@SpringBootApplication @EnableZuulProxy public class Zuul_9527 { public static void main(String[] args) { SpringApplication.run(Zuul_9527.class,args); } }
-
访问:http://localhost:9527/microservicecloud-dept/dept/get/2
-
zull路由访问映射规则,修改application.properties如下,
zuul.routes.mydept.serviceId=microservicecloud-dept zuul.routes.mydept.path=/mydept/** zuul.ignored-services=microservicecloud-dept //此配置使原路径失效 zuul.prifix=/xdd //访问都需要加前缀
此时访问:http://localhost:9527/mydept/dept/get/2与http://localhost:9527/microservicecloud-dept/dept/get/2相同
SpringCloud-Config
-
在github新建一个仓库,新建一个application.yml并提交到仓库
spring: profiles: active: -dev --- spring: profiles: dev application: name: microservicecloud-config-dev --- spring: profiles: test application: name: microservicecloud-config-test
-
新建配置中心模块并添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency>
-
创建application.properties
server: port: 3344 spring: application: name: microservicecloud-config cloud: config: server: git: uri: https://gitee.com/xdd15531179996/microservicecloud-config.git
-
创建主启动类并添加注解 @EnableConfigServer
-
测试读取数据:http://localhost:3344/application-test.yml