This commit is contained in:
朱毅骏 2020-11-12 10:23:02 +08:00
parent 82fc148519
commit 35915e9d4d
30 changed files with 725 additions and 0 deletions

33
.gitignore vendored Normal file
View File

@ -0,0 +1,33 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/

29
01-eureka/pom.xml Normal file
View File

@ -0,0 +1,29 @@
<?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">
<parent>
<artifactId>springcloud</artifactId>
<groupId>cn.zyjblogs</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>01-eureka</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,13 @@
package cn.zyjblogs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class,args);
}
}

View File

@ -0,0 +1,17 @@
package cn.zyjblogs.config;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@EnableWebSecurity
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//忽略掉/eureka/**路径
http.csrf().ignoringAntMatchers("/eureka/**");
super.configure(http);
}
}

View File

@ -0,0 +1,23 @@
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
#当前的eureka是单机版的 false单机版 true集群
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: http://root:root@localhost:8762/eureka/
# Eureka保护机制配置
server:
enable-self-preservation: true
spring:
application:
name: EUREKA
security:
user:
name: root
password: root

47
02-customer/pom.xml Normal file
View File

@ -0,0 +1,47 @@
<?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">
<parent>
<artifactId>springcloud</artifactId>
<groupId>cn.zyjblogs</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>02-customer</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,17 @@
package cn.zyjblogs;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Customer {
private Integer id;
private String name;
private Integer age;
}

View File

@ -0,0 +1,21 @@
package cn.zyjblogs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableEurekaClient
@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
@EnableHystrixDashboard
@ServletComponentScan({"cn.zyjblogs.servlet","cn.zyjblogs.filter"})
public class CustomerApplication {
public static void main(String[] args) {
SpringApplication.run(CustomerApplication.class,args);
}
}

View File

@ -0,0 +1,28 @@
package cn.zyjblogs.client;
import cn.zyjblogs.Customer;
import cn.zyjblogs.factory.SearchClientFallBackFactory;
import cn.zyjblogs.fallback.SearchClientFallBack;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
//指定服务名称
@FeignClient(value = "SEARCH",
/*fallback = SearchClientFallBack.class*/
fallbackFactory = SearchClientFallBackFactory.class
)
public interface SearchClient {
//value -> 目标服务的请求路径method -> 映射请求方式
@RequestMapping(value = "/search",method = RequestMethod.GET)
String search();
@RequestMapping(value = "/search/{id}",method = RequestMethod.GET)
Customer findById(@PathVariable(value = "id") Integer id);
@RequestMapping(value = "/getCustomer",method = RequestMethod.GET)
Customer getcustomer(@RequestParam(value = "id") Integer id, @RequestParam(value = "name") String name);
@RequestMapping(value = "save",method = RequestMethod.GET) //会自动转化成POST请求 405
Customer save(@RequestBody Customer customer);
}

View File

@ -0,0 +1,24 @@
package cn.zyjblogs.config;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
// @Bean
// public IRule robbinRule() {
// return new RandomRule();
// }
}

View File

@ -0,0 +1,87 @@
package cn.zyjblogs.controller;
import cn.zyjblogs.Customer;
import cn.zyjblogs.client.SearchClient;
import cn.zyjblogs.service.CustomerService;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
@RestController
public class CustomerController {
@Autowired private RestTemplate restTemplate;
@Autowired private EurekaClient eurekaClient;
@Autowired private SearchClient searchClient;
@Autowired private CustomerService customerService;
@GetMapping("/customer")
public String customer() {
System.out.println(Thread.currentThread().getName());
/*
//直接使用EurekaClient调用的方式
//1. 通过eurekaClient 获取到SEARCH服务的信息
InstanceInfo info = eurekaClient.getNextServerFromEureka("SEARCH", false);
//2. 获取到访问的地址
String url = info.getHomePageUrl();
System.out.println(url);
//3. 通过restTemplate访问
String result = restTemplate.getForObject(url + "/search", String.class);
*/
/*
//Robbin时使用的调用方式
String result = restTemplate.getForObject("http://SEARCH/search", String.class);
*/
String result = searchClient.search();
// 4. 返回
return result;
}
@GetMapping("/customer/{id}")
@HystrixCommand(
fallbackMethod = "findByIdFallBack",
commandProperties = {
/*@HystrixProperty(name = "execution.isolation.strategy",value = "THREAD"),
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000"),*/
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "70"),
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000"),
})
public Customer findById(@PathVariable Integer id) throws InterruptedException {
System.out.println(Thread.currentThread().getName());
// Thread.sleep(3000);
if (id == 1) {
int i = 1 / 0;
}
System.out.println(customerService.findById(id));
System.out.println(customerService.findById(id));
customerService.clearFindById(id);
System.out.println(customerService.findById(id));
System.out.println(customerService.findById(id));
customerService.clearFindById(id);
return searchClient.findById(id);
}
// findById的降级方法方法描述要与接口一致
public Customer findByIdFallBack(Integer id) {
return new Customer(-1, "", 0);
}
@GetMapping("/getCustomer")
public Customer getcustomer(@RequestParam Integer id, @RequestParam String name) {
return searchClient.getcustomer(id, name);
}
@GetMapping("save")
public Customer save(Customer customer) {
return searchClient.save(customer);
}
}

View File

@ -0,0 +1,20 @@
package cn.zyjblogs.factory;
import cn.zyjblogs.client.SearchClient;
import cn.zyjblogs.fallback.SearchClientFallBack;
import feign.hystrix.FallbackFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class SearchClientFallBackFactory implements FallbackFactory<SearchClient> {
@Autowired
private SearchClientFallBack searchClientFallBack;
@Override
public SearchClient create(Throwable throwable) {
throwable.printStackTrace();
return searchClientFallBack;
}
}

View File

@ -0,0 +1,30 @@
package cn.zyjblogs.fallback;
import cn.zyjblogs.Customer;
import cn.zyjblogs.client.SearchClient;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
@Component
public class SearchClientFallBack implements SearchClient {
@Override
public String search() {
return "出现问题了";
}
@Override
public Customer findById(Integer id) {
return null;
}
@Override
public Customer getcustomer(Integer id, String name) {
return null;
}
@Override
public Customer save(Customer customer) {
return null;
}
}

View File

@ -0,0 +1,16 @@
package cn.zyjblogs.filter;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/*")
public class HystrixRequestContextFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HystrixRequestContext.initializeContext();
filterChain.doFilter(servletRequest,servletResponse);
}
}

View File

@ -0,0 +1,30 @@
package cn.zyjblogs.service;
import cn.zyjblogs.Customer;
import cn.zyjblogs.client.SearchClient;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheKey;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheRemove;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class CustomerService {
@Autowired
private SearchClient searchClient;
@CacheResult
@HystrixCommand(commandKey = "findById")
public Customer findById(@CacheKey Integer id) throws InterruptedException {
return searchClient.findById(id);
}
@CacheRemove(commandKey = "findById")
@HystrixCommand
public void clearFindById(@CacheKey Integer id) {
System.out.println("findById缓存被清空");
}
}

View File

@ -0,0 +1,9 @@
package cn.zyjblogs.servlet;
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import javax.servlet.annotation.WebServlet;
@WebServlet("/hystrix.stream")
public class HystrixServlet extends HystrixMetricsStreamServlet {
}

View File

@ -0,0 +1,33 @@
server:
port: 8080
#指定Eureka服务地址
eureka:
client:
service-url:
defaultZone: http://root:root@localhost:8761/eureka,http://root:root@localhost:8762/eureka
#每隔多久去更新一下本地的注册表缓存信息
registry-fetch-interval-seconds: 30
instance:
#心跳间隔
lease-renewal-interval-in-seconds: 30
#多久没法送,就认为你宕机了
lease-expiration-duration-in-seconds: 90
#指定具体服务的负载均衡策略
SEARCH: #编写服务名称
ribbon:
# NIWSServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule
#feign和hystrix主件整合
feign:
hystrix:
enabled: true
#指定服务名称
spring:
application:
name: CUSTOMER
hystrix:
dashboard:
proxy-stream-allow-list: localhost

28
03-search/pom.xml Normal file
View File

@ -0,0 +1,28 @@
<?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">
<parent>
<artifactId>springcloud</artifactId>
<groupId>cn.zyjblogs</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>03-search</artifactId>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,13 @@
package cn.zyjblogs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableEurekaClient
@SpringBootApplication
public class SearchApplication {
public static void main(String[] args) {
SpringApplication.run(SearchApplication.class,args);
}
}

View File

@ -0,0 +1,33 @@
package cn.zyjblogs.controller;
import cn.zyjblogs.entity.Customer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
@RestController
public class SearchController {
@Value("${server.port}")
private String port;
@GetMapping("/search")
public String search() {
int i = 1/0;
return "search:" + port;
}
@GetMapping("/search/{id}")
public Customer findById(@PathVariable Integer id) {
return new Customer(1, "zhangsan", (int) (Math.random() * 100000));
}
@GetMapping("/getCustomer")
public Customer getcustomer(@RequestParam Integer id, @RequestParam String name) {
return new Customer(id, name, (int) (Math.random() * 100000));
}
@PostMapping("save")
public Customer save(@RequestBody Customer customer) {
return customer;
}
}

View File

@ -0,0 +1,17 @@
package cn.zyjblogs.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Customer {
private Integer id;
private String name;
private Integer age;
}

View File

@ -0,0 +1,12 @@
server:
port: 8081
#指定Eureka服务地址
eureka:
client:
service-url:
defaultZone: http://root:root@localhost:8761/eureka,http://root:root@localhost:8762/eureka
#指定服务名称
spring:
application:
name: SEARCH

29
04-eureka/pom.xml Normal file
View File

@ -0,0 +1,29 @@
<?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">
<parent>
<artifactId>springcloud</artifactId>
<groupId>cn.zyjblogs</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>04-eureka</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,13 @@
package cn.zyjblogs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class,args);
}
}

View File

@ -0,0 +1,17 @@
package cn.zyjblogs.config;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@EnableWebSecurity
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//忽略掉/eureka/**路径
http.csrf().ignoringAntMatchers("/eureka/**");
super.configure(http);
}
}

View File

@ -0,0 +1,19 @@
server:
port: 8762
eureka:
instance:
hostname: localhost
client:
#当前的eureka是单机版的 false单机版 true集群
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: http://root:root@localhost:8761/eureka/
spring:
application:
name: EUREKA
security:
user:
name: root
password: root

40
pom.xml Normal file
View File

@ -0,0 +1,40 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<modules>
<module>01-eureka</module>
<module>02-customer</module>
<module>03-search</module>
<module>04-eureka</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.zyjblogs</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud</name>
<packaging>pom</packaging>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring.cloud-version>Hoxton.SR8</spring.cloud-version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@ -0,0 +1,13 @@
package cn.zyjblogs.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringcloudApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudApplication.class, args);
}
}

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,13 @@
package cn.zyjblogs.springcloud;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class SpringcloudApplicationTests {
@Test
void contextLoads() {
}
}