Springboot是什么?
是推出解决传统框架配置文件繁杂冗余,基于maven仓库和注解,快速搭建的框架,不依赖springcloud。
Springcloud是什么?
依赖springboot,专注于各个微服务的联调配置,通信,熔断,负载均衡。
Eureka:服务注册发现。(Dubbo用的是zooukeep做服务注册发现。)
Ribbon:服务的负载均衡,从服务的多台机器中选择一台,可以用spring的restTemplate和httpclient远程调用服务。
Feign:动态代理机制,pom文件里导入的jar包包含ribbon,根据注解来选择机器实现负载均衡。
Hystrix:当服务器发生故障,给服务调用增加返回错误码,避免调用不成功还一直调用导致系统阻塞。
Zuul:网关管理,可以在yml文件配置路径,转发给不同的服务。
搭建框架时候有几个大的不同点:
启动类:注解不同@EnableEurekaService和@EnableEurekaClient。
pom文件:eureka注册中心是导入eureka-service的jar,,服务端和消费端导入的是eureka-client的jar。
yml配置文件,eureka注册中心和服务端消费端是不同的,他们都需要配置eureka-instatnce-hostaname和eureka-client-serviceurl。但eureka注册中心需要多配置两个参数:一个是标注自己是注册中心不需要注册向自己注册,另一个是标注自己表示是否去服务上获取信息,并不需要去检查服务。
Hytrix的作用:在微服务中,独立的业务会拆分成一个个微服务,微服务可以相互调用的(RPC),在springcloud可以用restTemplate+ribbon和feign来调用。为了保证高可用,单个服务器通常会集群部署,因为只部署一个的话,总会因为项目本身或者网络问题服务断掉,而导致严重后果,hytrix就是保护集群微服务高可用,其中一个服务器发生故障直接返回错误编码,避免一直调用导致系统阻塞。
一、先创建一个父模块j_cloud
整体目录如下:
先创建 总的父模块,pom文件如下:
<?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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>j_cloud</artifactId> <version>0.0.1-SNAPSHOT</version> <name>j_cloud</name> <description>Demo project for Spring Boot</description> <!-- spring boot 聚合父工程中,打包类型要求设置为 pom--> <packaging>pom</packaging> <modules> <module>test-springboot-eureka-server8761</module> <module>eurekaclient</module> <module>eurekaclient2</module> </modules> <properties> <java.version>1.8</java.version> <spring-boot.version>2.2.5.RELEASE</spring-boot.version> <spring-cloud.version>Hoxton.RELEASE</spring-cloud.version> <!-- <spring-cloud-alibaba.version>2.1.0.RELEASE</spring-cloud-alibaba.version>--> <mybatis-spring-boot.version>2.1.2</mybatis-spring-boot.version> <mysql.version>8.0.12</mysql.version> <druid.version>1.1.21</druid.version> <lombok.version>1.16.20</lombok.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- spring boot --> <!-- <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency>--> <!-- spring cloud --> <!-- <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency>--> <!-- spring cloud alibaba --> <!-- <dependency>--> <!-- <groupId>com.alibaba.cloud</groupId>--> <!-- <artifactId>spring-cloud-alibaba-dependencies</artifactId>--> <!-- <version>${spring-cloud-alibaba.version}</version>--> <!-- <type>pom</type>--> <!-- <scope>import</scope>--> <!-- </dependency>--> <!-- mybatis --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis-spring-boot.version}</version> </dependency> <!-- mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!-- druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>${druid.version}</version> </dependency> <!-- lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> <!-- test --> <!-- <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>${spring-boot.version}</version> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency>--> </dependencies> <!--依赖管理--> <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> <build> <finalName>${project.artifactId}</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>${java.version}</source> <target>${java.version}</target> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> <configuration> <fork>true</fork> <addResources>true</addResources> </configuration> </plugin> </plugins> </build> </project>
二、父模块下建立test-springboot-eureka-server8761
在父类下建立后pom文件:
<?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> <parent> <groupId>com.example</groupId> <artifactId>j_cloud</artifactId> <version>0.0.1-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>test-springboot-eureka-server8761</artifactId> <version>0.0.1-SNAPSHOT</version> <name>test-springboot-eureka-server8761</name> <description>Demo project for Spring Boot</description> <dependencies> <!-- eureka server --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
启动类加上面的注解,yml文件如下:
# 端口 server: port: 8081 tomcat: uri-encoding: UTF-8 # Eureka配置 eureka: instance: # eureka服务端的实例名称 hostname: 127.0.0.1 client: # 是否将自己注册到Eureka服务中,因为该应用本身就是注册中心,不需要再注册自己(集群的时候为true) register-with-eureka: false #是否从Eureka Server上获取注册信息,默认为true fetch-registry: false # 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址 service-url: defaultZone: http://${eureka.instance.hostname}:8081/eureka/ # server: # enable-self-preservation: false spring: application: name: cloud-eureka-server
三、继续创建eurekaclient
<?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> <parent> <groupId>com.example</groupId> <artifactId>j_cloud</artifactId> <version>0.0.1-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>eurekaclient</artifactId> <version>0.0.1-SNAPSHOT</version> <name>eurekaclient</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <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> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
这时候eureka注解改为eurekaClient,之前那个eurekaService是服务注册用的
# 端口 server: port: 8082 tomcat: uri-encoding: UTF-8 # Eureka配置 eureka: instance: # eureka服务端的实例名称 hostname: localhost client: # 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址 service-url: defaultZone: http://${eureka.instance.hostname}:8081/eureka/ spring: application: name: eureka-client
四、搭建Ribbon模块
<?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> <parent> <groupId>com.example</groupId> <artifactId>j_cloud</artifactId> <version>0.0.1-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>ribbon</artifactId> <version>0.0.1-SNAPSHOT</version> <name>ribbon</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <!--cloud rabbit--> <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.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
这里断容器可以先注释掉,ribbon是通过restTemplate调用远程的,所以先用restTemplateBuilder吧他注入到容器。
controller和service代码分别是:
@RestController public class RibbonController { @Resource private RibbonService ribbonService; @RequestMapping("/ribbon") public String ribbon(String name) { return ribbonService.ribbon(name); } } @Service public class RibbonService { @Resource private RestTemplate restTemplate; @HystrixCommand(fallbackMethod = "error") public String ribbon(String name) { return restTemplate.getForObject("http://EUREKA-CLIENT/hi_eureka?name=" + name, String.class); } public String error(String name) { return "springCloud的Ribbon远程调用失败:" + name; } } yml配置文件: # 端口 server: port: 8084 tomcat: uri-encoding: UTF-8 # Eureka配置 eureka: instance: # eureka服务端的实例名称 hostname: localhost client: # 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址 service-url: defaultZone: http://${eureka.instance.hostname}:8081/eureka/ spring: application: name: rabbon
这时候访问端口就可以看到调用eureka成功了:http://localhost:8084/ribbon?name=123
五、feign负载均衡消费端
<?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> <parent> <groupId>com.example</groupId> <artifactId>j_cloud</artifactId> <version>0.0.1-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>feign</artifactId> <version>0.0.1-SNAPSHOT</version> <name>feign</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!--引入feign 依赖,包含ribbon负载均衡,也包含Hystrix服务容错。--> <!--Spring Cloud Feign在构建被@FeignClient注解修饰的服务客户端是,会为每一个客户端都创建一个feign.Logger实例,我们可以利用该日志对象进行Log分析。--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
@Repository @FeignClient(value = "eureka-client",fallback = HystrixService.class) public interface FeignServer { @RequestMapping("/hi_eureka") public String hi(@RequestParam("name") String name); }
在Hytrix熔断器,在Ribbon加入、在feign加入熔断器hrtrix
public String error(String name) { return "springCloud的Ribbon远程调用失败:" + name; } @Component public class HystrixService implements FeignServer { @Override public String hi(String name) { return "sprigCloud远程访问异常:" + name; } }
六、zull网管负载均衡
<?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> <parent> <groupId>com.example</groupId> <artifactId>j_cloud</artifactId> <version>0.0.1-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>zuul</artifactId> <version>0.0.1-SNAPSHOT</version> <name>zuul</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <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-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
yml关键点在于配置负载以及需要用注解@EnableZuulProxy:
zuul: routes: api-a: path: /api-a/** service-id: rabbit api-b: path: /api-b/** service-id: feign api-c: path: /api-c/** service-id: feign host: socket-timeout-millis: 60000 connect-timeout-millis: 60000 spring: application: name: zuul