SpringCloud踩坑实战笔记(入门篇)
来源:互联网 发布:小说改编都市网络剧 编辑:程序博客网 时间:2024/06/05 14:11
前言
本周投入了不少的精力着重研究了springCloud相关的基础知识,把网上的相关博文,资料翻了一遍,搭建出了第一个SpringCould的Demo集群,把SrpingCould的入门坑踩了一遍,在这记录一下,希望大家能少走一些弯路。
SpringCould介绍
Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线)。简单来说,SpringCloud为开发人员提供了一系列贴有Spring品牌的适合于微服务应用开发的服务组件。
本文涉及到的主要内容如下图所示。
Demo架构
这里面涉及的内容较多,由于本文侧重实战就不详细说明了,请参考网络上的博客和https://www.springcloud.cc/spring-cloud-dalston.html与https://www.springcloud.cc/。
主要内容
准备工作
建立开发环境,我们一共需要5个工程来完成Demo的搭建,开发环境是maven,jdk8,intellij。
目录结构如下图所示,采用maven约定的结构。
服务注册与发现(Spring Eureka)
demo-eureka工程
DemoApplication.java
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@EnableEurekaServer@SpringBootApplicationpublic class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }}
application.properties
ps这个配置不可用于生产环境,缺乏优化
server.port=8181#端口spring.application.name=mmb-eureka-server#服务名称eureka.client.register-with-eureka=false#注册自己,用于集群形式eureka.client.fetch-registry=false#若为true的话会报错
pom.xml
<?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"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demo</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Dalston.SR1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </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> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>
负载均衡和连接模板(Spring Ribbon&Feign)
DemoClient2Application.java
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.netflix.feign.EnableFeignClients;@SpringBootApplication@EnableDiscoveryClient@EnableFeignClientspublic class DemoClient2Application { public static void main(String[] args) { SpringApplication.run(DemoClient2Application.class, args); }}
DemoController.java
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import springfox.documentation.swagger2.annotations.EnableSwagger2;@RestControllerpublic class DemoController { @Autowired private WordFeignClient wordFeignClient; @RequestMapping("/abc") public String getSentence() { return wordFeignClient.getWord() + wordFeignClient.getWord(); }}
WordFeignClient.java
import org.springframework.cloud.netflix.feign.FeignClient;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;/** * Created by zhaoenwei on 2017/7/1. */@FeignClient("mmb-eureka-subject")public interface WordFeignClient { @RequestMapping(value = "/", method = RequestMethod.GET) String getWord();}
application.properties
eureka.client.service-url.defaultZone=http://localhost:8181/eurekaserver.port= 8182spring.application.name=mmb-eureka-client2eureka.instance.prefer-ip-address=truemmb-eureka-subject.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
pom.xml
<?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"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo-client2</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demo-client2</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Dalston.SR1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</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-feign</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.6.1</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.6.1</version> </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> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>
网关(Spring Zuul)
ZuulDemoApplication.java
package com.example.demo;import org.springframework.boot.SpringApplication; import org.springframework.cloud.client.SpringCloudApplication; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; import org.springframework.context.annotation.Bean;@SpringCloudApplication@EnableZuulProxypublic class ZuulDemoApplication { @Bean public SimpleFilter simpleFilter() { return new SimpleFilter(); } public static void main(String[] args) { SpringApplication.run(ZuulDemoApplication.class, args); }}
SimpleFilter.java
package com.example.demo;import com.netflix.zuul.ZuulFilter;import com.netflix.zuul.context.RequestContext;import net.sf.json.JSONObject;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.servlet.http.HttpServletRequest;import java.util.Map;/** * Created by zhaoenwei on 2017/6/30. */public class SimpleFilter extends ZuulFilter { private static Logger log = LoggerFactory.getLogger(SimpleFilter.class); @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 1; } @Override public boolean shouldFilter() { return true; } @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); Map<String,String[]> map=request.getParameterMap(); JSONObject jsonMap= JSONObject.fromObject(map); log.info(String.format("%s request to %s ZEW==>params:%s", request.getMethod(), request.getRequestURL().toString(),jsonMap.toString())); return null; }}
application.properties
#path的url是被替换掉的也示例#zuulIP:zuulPort/sentence2/abc->serviceIP:servicePort/abczuul.routes.sentence.path=/sentence2/**zuul.routes.sentence.serviceId=mmb-eureka-client2 #zuul.routes.sentence.url=http://localhost:8182/sentencespring.application.name=mmb-zuul-server#下面那个参数是去掉zuul-prefix参数产生的前缀的,跟path一毛钱关系都没有zuul.strip-prefix=falseserver.port=8081eureka.client.service-url.defaultZone=http://localhost:8181/eureka
pom.xml
<?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"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>zuul-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>zuul-demo</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Dalston.SR1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.4</version> <classifier>jdk15</classifier> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </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> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>
配置中心与消息总线(Srping Config & Bus)
该配置中心设置是支持在git的统一配置管理,并支持rabbitmq的消息传播。也就是说该服务需要rabbitmq的环境。
配置中心
DemoConfigApplication.java
package com.example.demo;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.config.server.EnableConfigServer;@SpringBootApplication@EnableConfigServer@EnableDiscoveryClientpublic class DemoConfigApplication { public static void main(String[] args) { SpringApplication.run(DemoConfigApplication.class, args); }}
application.properties
server.port=8888spring.application.name=config-servereureka.client.service-url.defaultZone=http://localhost:8181/eurekaeureka.instance.prefer-ip-address=true
bootstrap.properties
spring.cloud.config.server.git.uri=https://github.com/zhaoenweiex/config-repo.gitmanagement.security.enabled=falsespring.cloud.config.server.git.basedir=target/configspring.cloud.config.server.git.search-paths= configclientspring.rabbitmq.host=localhostspring.rabbitmq.port=5672
pom.xml
<?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"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo-config</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demo-config</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Dalston.SR1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</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-eureka</artifactId> </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> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>
配置客户端
DemoConfigApplication.java
package com.example.demo;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@SpringBootApplication@EnableDiscoveryClientpublic class DemoClientApplication { public static void main(String[] args) { SpringApplication.run(DemoClientApplication.class, args); }}
DemoController.java
package com.example.demo;import org.springframework.beans.factory.annotation.Value;import org.springframework.cloud.context.config.annotation.RefreshScope;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.net.Inet4Address;import java.net.UnknownHostException;/** * Created by zhaoenwei on 2017/6/29. */@RefreshScope@RestControllerpublic class DemoController { private static long timeStample=System.currentTimeMillis();// @Autowired// private ConstantProperties constantProperties; //从config server拿到的配置数据 @Value("${words}") private String wordsStr; @RequestMapping("/") public String getWord() { String[] wordArray = wordsStr.split(","); String address= null; try { address = Inet4Address.getLocalHost().getHostAddress(); } catch (UnknownHostException e) { e.printStackTrace(); } int i = (int)Math.round(Math.random() * (wordArray.length - 1)); return wordArray[i]+timeStample+ address; }}
application.properties
eureka.client.service-url.defaultZone=http://192.168.31.238:8181/eurekaserver.port= ${PORT:${SERVER_PORT:0}}spring.application.name=mmb-eureka-subjecteureka.instance.prefer-ip-address=truespring.cloud.config.uri=http://localhost:8888spring.cloud.config.profile=devspring.rabbitmq.host=localhostspring.rabbitmq.port=5672
pom.xml
<?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"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo-client</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demo-client</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Dalston.SR1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </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> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>
总结
本文展示了如何搭建基于SpringCloud的微服务框架,包括了负责服务注册于发现的Spring Eureka,负责基于客户端负载均衡的组件Srping Ribbon,负责统一配置的Spring Config,负责智能路由和网关的Sping Zuul以及消息更新的消息总线Spring Bus,还有简化Rest连接的模板Feign。
最后补充两点:
1.在springCloud中最为复杂和容易出错的的并非是业务代码开发,而是依赖与配置,所以关于.properties或.yaml都是使用SpringCloud的必背基础,
2.支撑业务的SpringBoot开发框架也是必不可少的基础知识。
附录
下面是Demo项目的Git地址:
- 统一配置文件:https://github.com/zhaoenweiex/config-repo.git
- 配置中心:https://github.com/zhaoenweiex/demo-config.git
- 网关:https://github.com/zhaoenweiex/demo-zuul.git
- 负载均衡和连接模板的客户端:https://github.com/zhaoenweiex/demo-client-ribbon-feign.git
- 配置客户端:https://github.com/zhaoenweiex/demo-client.git
- 服务注册中心:https://github.com/zhaoenweiex/demo-eureka.git
- SpringCloud踩坑实战笔记(入门篇)
- SpringCloud踩坑实战笔记(入门篇)
- SpringCloud踩坑实战笔记2(复杂环境(docker+IDE+windows)的配置篇)
- springcloud 入门笔记-1
- SpringCloud Eureka实战
- SpringCloud微服务系列笔记(1)-SpringBoot简单入门
- SpringCloud学习踩坑记录
- springcloud入门(1)
- SpringCloud Eureda入门案例
- springcloud(第一篇)springcloud config 入门
- 【SpringCloud】(一):SpringCloud入门程序
- SpringCloud实战小贴士:随机端口
- 使用SpringCloud实战微服务
- 使用SpringCloud实战微服务
- springcloud(第四篇)springcloud hystrix
- springcloud(第五篇)springcloud turbine
- springcloud(第六篇)springcloud ribbon
- springcloud(第八篇)springcloud feign
- 【Dockerfile】Dockerfile构建过程-去除缓存构建
- poll服务器
- 巨杉数据库执行计划和索引的使用
- 电脑安装了WPS之后,文档无法用原来的office打开,右键新建的文档是wps类型的而不是office类型的解决方案
- Guetzli:谷歌开源新JPEG算法,可将文件缩小35%
- SpringCloud踩坑实战笔记(入门篇)
- javaweb4
- 跟任何人都聊得来—最受世界500强企业欢迎的沟通课(二)
- 本体结构介绍
- Range Update and Range Queries in BIT
- Struts2_动态方法调用
- Anaconda多环境多版本python配置指导
- mysql CMD命令行插入中文数据报错ERROR 1366
- 基于python的手写数字识别(KNN算法)