Spring Cloud
是一個基於Spring Boot
實現的雲應用開發工具,它爲基於JVM的雲應用開發中涉及的配置管理、服務發現、斷路器、智能路由、微代理、控制總線、全局鎖、決策競選、分佈式會話和集羣狀態管理等操做提供了一種簡單的開發方式。html
Spring Cloud
包含了多個子項目(針對分佈式系統中涉及的多個不一樣開源產品),好比:Spring Cloud Config
、Spring Cloud Netflix
、Spring Cloud CloudFoundry
、Spring Cloud AWS
、Spring Cloud Security
、Spring Cloud Commons
、Spring Cloud Zookeeper
、Spring Cloud CLI
等項目。java
「微服務架構」在這幾年很是的火熱,以致於關於微服務架構相關的開源產品被反覆的說起(好比: netflix
、dubbo
),Spring Cloud
也因Spring
社區的強大知名度和影響力也被廣大架構師與開發者備受關注。mysql
那麼什麼是「微服務架構」呢?簡單的說,微服務架構就是將一個完整的應用從數據存儲開始垂直拆分紅多個不一樣的服務,每一個服務都能獨立部署、獨立維護、獨立擴展,服務與服務間經過諸如RESTful API的方式互相調用。linux
對於「微服務架構」,你們在互聯網能夠搜索到不少相關的介紹和研究文章來進行學習和了解。也能夠閱讀始祖Martin Fowler
的《Microservices》(中文版翻譯點擊查看),本文不作更多的介紹和描述。git
在簡單介紹了Spring Cloud
和微服務架構以後,下面迴歸本文的主旨內容,如何使用Spring Cloud
來實現服務治理。web
因爲Spring Cloud
爲服務治理作了一層抽象接口,因此在Spring Cloud
應用中能夠支持多種不一樣的服務治理框架,好比:Netflix Eureka
、Consul
、Zookeeper
。在Spring Cloud
服務治理抽象層的做用下,咱們能夠無縫地切換服務治理實現,而且不影響任何其餘的服務註冊、服務發現、服務調用等邏輯。spring
因此,下面咱們經過Eureka這種種服務治理的實現來體會Spring Cloud
這一層抽象所帶來的好處。
下一篇介紹基於Consul
的服務註冊與調用。sql
首先,咱們來嘗試使用Spring Cloud Consul
來實現服務治理。apache
Consul
是一套開源的分佈式服務發現和配置管理系統,由 HashiCorp
公司用 Go
語言開發。json
它具備不少優勢。包括: 基於 raft
協議,比較簡潔; 支持健康檢查, 同時支持 HTTP
和 DNS
協議 支持跨數據中心的 WAN
集羣 提供圖形界面 跨平臺,支持 Linux、Mac、Windows
下面,就來具體看看如何使用Spring Cloud Consul
實現服務治理,這裏使用Consul
爲服務註冊中心工程、consul-provider
服務提供者工程、consul-consumer
服務消費者工程。
環境:
windows jdk 8 maven 3.0 IDEA
首先構建父工程,引入父工程依賴:
<?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> <parent> <groupId>cn.zhangbox</groupId> <artifactId>spring-cloud-study</artifactId> <version>1.0-SNAPSHOT</version> </parent> <groupId>cn.zhangbox</groupId> <artifactId>spring-cloud-consul</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <!--子模塊--> <modules> <module>consul-provider</module> <module>consul-consumer</module> </modules> </project>
父工程取名爲:spring-cloud-consul
構建子工程,分別建立工程名爲:、consul-provider
、consul-consumer
並在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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>cn.zhangbox</groupId> <artifactId>spring-cloud-consul</artifactId> <version>1.0-SNAPSHOT</version> </parent> <groupId>cn.zhangbox</groupId> <artifactId>consul-provider</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>consul-provider</name> <description>this project for Spring Boot</description> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <!-- 版本控制 --> <commons-lang3.version>3.4</commons-lang3.version> <commons-codec.version>1.10</commons-codec.version> <mybatis-spring-boot.version>1.2.0</mybatis-spring-boot.version> <lombok.version>1.16.14</lombok.version> <fastjson.version>1.2.41</fastjson.version> <druid.version>1.1.2</druid.version> </properties> <repositories> <!-- 阿里私服 --> <repository> <id>aliyunmaven</id> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> </repository> </repositories> <dependencies> <!-- mybatis核心包 start --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis-spring-boot.version}</version> </dependency> <!-- mybatis核心包 end --> <!-- 添加consul支持start --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- 添加consul支持start --> <!-- SpringWEB核心包 start --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- SpringWEB核心包 end --> <!-- Swagger核心包 start --> <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> <!-- Swagger核心包 end --> <!-- mysql驅動核心包 start --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!-- mysql驅動核心包 end --> <!-- sprigTest核心包 start --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- sprigTest核心包 end --> <!-- commons工具核心包 start --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>${commons-lang3.version}</version> </dependency> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>${commons-codec.version}</version> </dependency> <!-- commons工具核心包 end --> <!-- fastjson核心包 start --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> <!-- fastjson核心包 end --> <!-- druid核心包 start --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>${druid.version}</version> </dependency> <!-- druid核心包 end --> <!-- lombok核心包 start --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> <!-- lombok核心包 end --> </dependencies> <!-- 添加cloud 依賴start --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <!-- 添加cloud 依賴end --> <build> <finalName>eureka-provider</finalName> <plugins> <!-- 添加maven構建插件start --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <!-- 添加maven構建插件end --> </plugins> </build> </project>
<?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> <parent> <groupId>cn.zhangbox</groupId> <artifactId>spring-cloud-consul</artifactId> <version>1.0-SNAPSHOT</version> </parent> <groupId>cn.zhangbox</groupId> <artifactId>consul-consumer</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>consul-consumer</name> <description>this project for Spring Boot</description> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <!-- 版本控制 --> <commons-lang3.version>3.4</commons-lang3.version> <commons-codec.version>1.10</commons-codec.version> <mybatis-spring-boot.version>1.2.0</mybatis-spring-boot.version> <lombok.version>1.16.14</lombok.version> <fastjson.version>1.2.41</fastjson.version> <druid.version>1.1.2</druid.version> </properties> <repositories> <!-- 阿里私服 --> <repository> <id>aliyunmaven</id> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> </repository> </repositories> <dependencies> <!-- 添加consul支持start --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- 添加consul支持start --> <!-- 添加feign支持start --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> <!-- 添加feign支持end --> <!-- SpringWEB核心包 start --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- SpringWEB核心包 end --> <!-- Swagger核心包 start --> <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> <!-- Swagger核心包 end --> <!-- sprigTest核心包 start --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- sprigTest核心包 end --> <!-- commons工具核心包 start --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>${commons-lang3.version}</version> </dependency> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>${commons-codec.version}</version> </dependency> <!-- commons工具核心包 end --> <!-- fastjson核心包 start --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> <!-- fastjson核心包 end --> <!-- lombok核心包 start --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> <!-- lombok核心包 end --> </dependencies> <!-- 添加cloud 依賴start --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <!-- 添加cloud 依賴end --> <build> <finalName>eureka-provider</finalName> <plugins> <!-- 添加maven構建插件start --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <!-- 添加maven構建插件end --> </plugins> </build> </project>
工程構建完成。
Window下安裝:
window下安裝Consul
Linux下安裝:
CentOS 安裝 Consul 服務註冊和發現軟件
Consul安裝 linux環境
至此consul
註冊中心建立完成,window
下本機安裝的consul
瀏覽器輸入地址:http://localhost:8500linux
下安裝的只須要把localhost
換成對應的ip
便可
能夠看到以下頁面,表示服務啓動OK
這裏這看到尚未服務暴露出來,是由於還沒建立服務提供者工程。
這裏服務提供者是使用以前SpringBoot進階教程 | 第三篇:整合Druid鏈接池以及Druid監控改造而來,這裏同樣的部分就再也不重複說明,下面將說明新增的部分。
首先:修改application.yml
配置爲以下:
#公共配置 server: port: 80 tomcat: uri-encoding: UTF-8 spring: application: name: consul-provider #激活哪個環境的配置文件 profiles: active: dev #鏈接池配置 datasource: driver-class-name: com.mysql.jdbc.Driver # 使用druid數據源 type: com.alibaba.druid.pool.DruidDataSource druid: # 配置測試查詢語句 validationQuery: SELECT 1 FROM DUAL # 初始化大小,最小,最大 initialSize: 10 minIdle: 10 maxActive: 200 # 配置一個鏈接在池中最小生存的時間,單位是毫秒 minEvictableIdleTimeMillis: 180000 testOnBorrow: false testWhileIdle: true removeAbandoned: true removeAbandonedTimeout: 1800 logAbandoned: true # 打開PSCache,而且指定每一個鏈接上PSCache的大小 poolPreparedStatements: true maxOpenPreparedStatements: 100 # 配置監控統計攔截的filters,去掉後監控界面sql沒法統計,'wall'用於防火牆 filters: stat,wall,log4j # 經過connectProperties屬性來打開mergeSql功能;慢SQL記錄 connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 #配置consul獲取服務地址,這裏使用的是本地提供的註冊中心 cloud: consul: #consul服務地址 host: localhost #consul端口號 port: 8500 discovery: #配置註冊中心顯示當前服務的ip prefer-ip-address: true #配置當前服務的ip和端口號 #instance-id: ${spring.cloud.client.ipAddress}:${server.port} #配置該項點擊ip會跳轉至對應的接口swagger頁面 health-check-url: http://${spring.cloud.client.ipAddress}:${server.port}/swagger-ui.html # ${server.port}爲該服務的端口號 #mybatis mybatis: # 實體類掃描 type-aliases-package: cn.zhangbox.springboot.entity # 配置映射文件位置 mapper-locations: classpath:mapper/*.xml # 開啓駝峯匹配 mapUnderscoreToCamelCase: true --- #開發環境配置 server: #端口 port: 8080 spring: profiles: dev # 數據源配置 datasource: url: jdbc:mysql://101.132.66.175:3306/student?useUnicode=true&characterEncoding=utf8&useSSL=false&tinyInt1isBit=true username: root password: 123456 #日誌 logging: config: classpath:log/logback.xml path: log/consul-provider --- #測試環境配置 server: #端口 port: 80 spring: profiles: test # 數據源配置 datasource: url: jdbc:mysql://127.0.0.1:3306/consul-provider?useUnicode=true&characterEncoding=utf8&useSSL=false&tinyInt1isBit=true username: root password: 123456 #日誌 logging: config: classpath:log/logback.xml path: /home/log/consul-provider --- #生產環境配置 server: #端口 port: 8080 spring: profiles: prod # 數據源配置 datasource: url: jdbc:mysql://127.0.0.1:3306/consul-provider?useUnicode=true&characterEncoding=utf8&useSSL=false&tinyInt1isBit=true username: root password: 123456 #日誌 logging: config: classpath:log/logback.xml path: /home/log/consul-provider
其次:在config
目錄下增長SwaggerConfig
類加入如下代碼:
@Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket userApi() { Docket docket = new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("cn.zhangbox.eureka.provider.controller"))//過濾的接口,有這掃描纔會看到接口信息 .paths(PathSelectors.any()) .build(); return docket; } private ApiInfo apiInfo() { return new ApiInfoBuilder().title("eureka服務端提供者接口平臺").description("服務相關數據接口") .termsOfServiceUrl("http://www.zhang.box.cn/").contact("技術開發部") .license("Licence Version 1.0").licenseUrl("#").version("1.0").build(); } }
這裏若是不會使用swagger
的整合能夠參考這篇文章:
SpringBoot非官方教程 | 第十一篇:SpringBoot集成swagger2,構建優雅的Restful API
接着:建立核心啓動類:
@EnableDiscoveryClient //使用該註解將註冊服務到consul @SpringBootApplication @MapperScan("cn.zhangbox.consul.provider.dao")//配置mybatis接口包掃描 public class ConsulProviderApplication extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(ConsulProviderApplication.class, args); } }
至此consul-provider
服務提供者建立完成,瀏覽器輸入地址:http://localhost:8500/
能夠看到以下頁面,表示服務註冊OK
瀏覽器輸入地址:http://localhost:8080/swagger-ui.html後能夠跳轉看到swagger
的頁面並但是測試服務提供者的接口,以下:
這裏構建的工程名爲consul-consumer
,上文已經構建了工程可是沒有建立目錄,這裏只須要在java目錄下建立config
、controller
,service
,包便可,這裏服務的消費是經過feign
來進行服務調用的,後面會有專門以篇文章來說feign
。
首先:在consul-consumer
工程下resource
目錄下添加application.yml
文件並加入如下配置:
#公共配置 server: port: 80 tomcat: uri-encoding: UTF-8 spring: #服務名稱,更關鍵,使用feign進行服務消費將以此爲依據 application: name: consul-consumer #激活哪個環境的配置文件 profiles: active: dev #配置consul獲取服務地址,這裏使用的是本地提供的註冊中心 cloud: consul: #consul服務地址 host: localhost #consul端口號 port: 8500 discovery: #配置註冊中心顯示當前服務的ip prefer-ip-address: true #配置當前服務的ip和端口號 #instance-id: ${spring.cloud.client.ipAddress}:${server.port} #配置該項點擊ip會跳轉至對應的接口swagger頁面 health-check-url: http://${spring.cloud.client.ipAddress}:${server.port}/swagger-ui.html # ${server.port}爲該服務的端口號 --- #開發環境配置 server: #端口 port: 8081 spring: profiles: dev #日誌 logging: config: classpath:log/logback.xml path: log/consul-consumer --- #測試環境配置 server: #端口 port: 8082 spring: profiles: test #日誌 logging: config: classpath:log/logback.xml path: /home/log/consul-consumer --- #生產環境配置 server: #端口 port: 8083 spring: profiles: prod #日誌 logging: config: classpath:log/logback.xml path: /home/log/consul-consumer
其次:在config
目錄下增長SwaggerConfig
類加入如下代碼:
@Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket userApi() { Docket docket = new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("cn.zhangbox.eureka.consumer.controller"))//過濾的接口,有這掃描纔會看到接口信息 .paths(PathSelectors.any()) .build(); return docket; } private ApiInfo apiInfo() { return new ApiInfoBuilder().title("eureka服務端消費者接口平臺").description("服務相關數據接口") .termsOfServiceUrl("http://www.zhang.box.cn/").contact("技術開發部") .license("Licence Version 1.0").licenseUrl("#").version("1.0").build(); } }
接着:在service
包下建立StudentConsumerService
類並加入如下代碼:
@FeignClient(value = "consul-provider") public interface StudentConsumerService { /** * 查詢全部的學生信息 * * @param sname * @param age * @return */ @RequestMapping(value = "/student/list",method = RequestMethod.GET) String getStudentList(@RequestParam(value = "sname") String sname, @RequestParam(value = "age") Integer age); }
而後:在controller
包下建立StudentConteroller
並加入以下代碼:
@Controller @RequestMapping("/student") @Api(value = "eureka-consumer", description = "學生查詢接口") public class StudentConteroller { private static final Logger LOGGER = LoggerFactory.getLogger(StudentConteroller.class); @Autowired StudentConsumerService studentService; /** * 查詢全部的學生信息 * * @param sname * @param age * @param modelMap * @return */ @ResponseBody @GetMapping("/consumer/list") public String list( @ApiParam(value = "學生姓名") @RequestParam(required = false) String sname, @ApiParam(value = "年齡") @RequestParam(required = false) Integer age, ModelMap modelMap) { String json = null; try { json = studentService.getStudentList(sname, age); } catch (Exception e) { e.printStackTrace(); modelMap.put("ren_code", "0"); modelMap.put("ren_msg", "查詢失敗===>" + e); LOGGER.error("查詢失敗===>" + e); json = JSON.toJSONString(modelMap); } return json; } }
接着:建立核心啓動類:
@EnableFeignClients//開啓Feign調用接口 @EnableDiscoveryClient//開啓客戶端服務,沒有這個註解會報Feign找不到對應服務的錯誤 @SpringBootApplication public class ConsulConsumerApplication extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(EurekaConsumerApplication.class, args); } }
至此consul-consumer
服務提供者建立完成,瀏覽器輸入地址:http://127.0.0.1:8081/swagger-ui.htmlconsul
註冊中心能夠看到服務提供和消費者都在:
跳轉看到swagger
的頁面並但是測試服務消費者的接口,能夠看到以下頁面,並點擊try it out
按鈕,返回了正確的學生信息數據
返回數據以下:
{ "ren_code": "0", "ren_msg": "查詢成功", "studentList": [{ "age": "17", "birth": "2010-07-22", "dept": "王同窗學習成績很不錯", "sex": "1", "sname": "王同窗", "sno": 1 }, { "age": "17", "birth": "2010-07-22", "dept": "李同窗學習成績很不錯", "sex": "1", "sname": "李同窗", "sno": 2 }] }
以上就是spring cloud
基於consul
實現分佈式服務註冊與消費的整合流程,是否是很簡單,你也來小試牛刀一把吧。
SpringCloud核心教程 | 第四篇:服務註冊與發現 Consul篇
歡迎關注、喜歡、和點贊後續將推出更多的spring cloud
教程,敬請期待。
歡迎關注個人微信公衆號獲取更多更全的學習資源,視頻資料,技術乾貨!