|
SpringCloud讲义 |
微服务管理框架 |
|
目 录
1 Spring Cloud概述 4
1.1 基于SOA系统架构 4
1.2 Spring Cloud的作用 5
1.3 为什么要学习Springcloud? 6
1.4 如何学习SpringCloud? 6
2 入门示例 6
2.1 配置步骤 6
2.2 第一部分:配置Eureka服务器(注册中心) 6
2.2.1 第一步:创建一个maven项目 7
2.2.2 第二步:在Spring官方网站,生成代码 7
2.2.3 第三步:创建一个启动类Application 9
2.2.4 第四步:创建配置文件application.properties 10
2.2.5 第五步:启动程序测试 10
2.3 第二部分:创建一个注册服务实例instanceServer 11
2.3.1 第一步:创建一个Maven项目 11
2.3.2 第二步:生成Spring boot项目代码 11
2.3.3 第三步:编写Application入口类 13
2.3.4 第四步:编写一个Controller类 14
2.3.5 第五步:编写配置文件application.properties 14
2.3.6 第六步:启动实例 15
2.4 第三部分:创建一个发现服务实例新实例(调用服务) 16
2.4.1 第一步:修改pom.xml配置文件的项目名 16
2.4.2 第二步:修改appplication.properties配置文件 16
2.4.3 第三步:修改发现服务入门程序注解 17
2.4.4 第四步:启动实例 17
2.5 第四部分:实现instanceClient与instanceServer的远程调用 17
2.5.1 第一步:修改注册服务,注册login登陆服务 18
2.5.2 第二步:修改发现服务实例instanceClient 19
2.5.3 第三步:启动实例 21
2.5.4 第四步:基于ribbon负载均衡实现 22
3 基于Feign实现服务调用 24
3.1 第一步:添加Feign依赖 24
3.2 第二步:修改UserService 24
3.3 第三步:修改启动类Application 25
3.4 第四步:启动instanceClient2 25
4 Eureka高可用配置 26
4.1 入门示例存在的缺陷 26
4.2 配置步骤 26
4.3 第一步:配置一个Eureka服务器。(已实现) 26
4.4 第二步:复制另外一个Eureka服务器 26
4.4.1 修改pom.xml中的Eureka服务名 27
4.4.2 修改application.properties配置文件 27
4.5 第三步:配置两个Eureka高可用(通讯) 28
4.5.1 修改第一个Eureka的application.properties文件 28
4.5.2 修改第二个Eureka的application.properties文件 28
4.5.3 修改本地hosts文件,注册Eureka主机名 29
4.6 第四步:分别启动两个Eureka测试 29
4.7 第五步:测试Eureka高可用 30
4.7.1 修改实例instanceServer的application.properties文件 30
4.7.2 修改实例instanceClient的application.properties文件 31
4.7.3 修改实例instanceServer2的application.properties文件 31
4.7.4 依次启动这三个实例 31
4.7.5 测试实例2调用远程服务 32
4.7.6 测试Eureka高可用 32
5 Eureka安全认证 33
5.1 第一部分:在Eureka服务端开启身份认证 33
5.1.1 第一步:添加身份认证依赖 33
5.1.2 第二步:开启身份认证 33
5.2 第二部分:在Eureka客户端进行身份认证 34
6 SpringBoot项目打包发布 34
6.1 第一步:使用Maven打包 34
6.2 第二步:上传到Linux环境 35
6.3 第三步:编写启动文件 35
7 改造电商系统为springcloud分布式架构 36
7.1 第一步:改造ego-project为springcloud系统 36
7.2 第二步:改造ego-order系统为注册服务实例系统 42
7.3 第三步:改造ego-portal工程为发现服务实例系统 45
1
Spring Cloud概述
1.1 基于SOA系统架构
面向服务的架构,是一种程序开发架构的设计思想。它将不同的功能单元使用一个作为独立的程序运行,并且提供访问的入口(将这些单独运行的每个程序称为服务)。
一个SOA架构的web应用程序,是多个服务组成的!!!
SOA架构的思想就是用于实现,程序分布式的。所以我们也可以将SOA架构的思想理解为分布式架构的思想。
如图所示:
1.2 Spring Cloud的作用
问题:以上SOA架构,这样的系统架构,有什么问题?
答:(1)无法检查服务的健康状态(服务是否可用)。
(2)无法对服务进行管理。
我们可以通过一个框架来,解决这些问题。那就是Spring Cloud。
Spring Cloud通过一个注册中心(Eureka),统一管理了整个分布式系统的服务接口。
所有的服务(子系统)在对外提供服务(接口)之前,必须要在注册中心中注册。我们开发人员就可以在注册中心中,查看整个分布式系统的所有服务!!
我们SOA概念中称为服务系统的东西,在Spring cloud有一个新的名字,叫实例(instance,实例系统)!
1.3 为什么要学习Springcloud?
Springcloud是提供了一整套企业级分布式云应用的完美解决方案,能够结合Spring Boot、Spring其它组件,实现快速开发的目的。
企业级开发越来越倾向Spring生态体系。当然也包括SpringCloud了。
1.4 如何学习SpringCloud?
根据上图所示,我们学习Spring Cloud首先要学习什么东西呢?
答:(1)必须要将Eureka配置成功
(2)实例是如何将服务在Eureka注册的
(3)如何在Eureka查看整个分布式系统所有实例对外提供的服务(发现服务)
(4)实例域实例之间是如何通讯的(远程调用)
2 入门示例
2.1 配置步骤
第一步:配置Eureka服务器
第二步:创建注册服务实例(Eureka客户端-注册服务@EnableEurekaClient)
第三步:创建发现服务实例(Eureka客户端-发现服务@EnableDiscoveryClient)
第四步:实现发现服务实例调用注册服务实例的示例。
2.2 第一部分:配置Eureka服务器(注册中心)
--注意实现:
1.Eclipse配置Spring Cloud必须先安装好 spring tool suite 插件。否则配置文件没有提示!!
2.Spring Cloud框架的jar都是由maven或者gradle构建工具获得的。我们主流使用的是Maven。所以创建的maven项目
2.2.1 第一步:创建一个maven项目
|
2.2.2 第二步:在Spring官方网站,生成代码
注意事项:必须要勾上Eureka Server选项
|
--生成代码包如下
|
我们需要将生成好的代码的pom.xml文件的依赖加入到我们的项目!!!!!
<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>cn.gzsxt.springcloud</groupId> <artifactId>springcloud-demo-01-eureka</artifactId> <version>1.0</version>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.19.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <java.version>1.8</java.version> <spring-cloud.version>Edgware.SR5</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> <!-- springcloud版本锁定 --> <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> |
2.2.3 第三步:创建一个启动类Application
package cn.gzsxt.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class, args); } } |
2.2.4 第四步:创建配置文件application.properties
#1.配置端口 server.port=5121 #2.配置eureka主机名,找到eureka所在的机器 eureka.instance.hostname=localhost #3.是否将自身注册为服务 false表示不注册 eureka.client.register-with-eureka=false #4.是否主动发现服务 false表示不发现 eureka.client.fetch-registry=false #5.对外提供的注册入口 eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/ |
2.2.5 第五步:启动程序测试
|
--测试结果
|
2.3 第二部分:创建一个注册服务实例instanceServer
注意事项:实例使用的是Spring Boot
2.3.1 第一步:创建一个Maven项目
|
2.3.2 第二步:生成Spring boot项目代码
--注意实现:必须添加webmvc模块以及Eureka客户端模块
|
--将生成的项目的pom.xml代码覆盖项目的pom.xml
<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>cn.gzsxt.springcloud</groupId> <artifactId>springcloud-demo-02-instanceServer01</artifactId> <version>1.0</version>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.19.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <java.version>1.8</java.version> <spring-cloud.version>Edgware.SR5</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-netflix-eureka-client</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> |
2.3.3 第三步:编写Application入口类
|
--Application代码
package cn.gzsxt.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class InstanceApplication { public static void main(String[] args) { SpringApplication.run(InstanceApplication.class, args); } } |
2.3.4 第四步:编写一个Controller类
package cn.gzsxt.springcloud.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @RequestMapping("/say") public String say(){
return "hello,springcloud";
} } |
2.3.5 第五步:编写配置文件application.properties
#指定实例端口 server.port=8080 #指定实例名,springcloud是通过实例名称来寻址服务的 spring.application.name=instanceServer #指定Eureka服务端访问路径 eureka.client.service-url.defaultZone=http://localhost:5121/eureka |
2.3.6 第六步:启动实例
--注意事项:因为实例是Eureka的客户端,所以启动实例之前,必须要先启动Eureka服务端!
2.3.6.1 启动Eureka服务端
--启动Eureka服务端,启动成功,会暴露配置文件指定的5121端口
|
--测试Eureka服务端是否成功,在浏览器输入:http://localhost:5121
如果成功,会出现以下页面
|
2.3.6.2 启动注册服务实例instanceServer01
--启动成功,会暴露配置文件指定的8080端口
|
--通过Eureka服务端管理后台可以查看客户端服务是否注册成功
|
2.4 第三部分:创建一个发现服务实例新实例(调用服务)
说明:将实例1复制一份。修改配置文件,修改为第二个实例
2.4.1 第一步:修改pom.xml配置文件的项目名
|
2.4.2 第二步:修改appplication.properties配置文件
#指定实例端口 server.port=8081 #指定实例名,springcloud是通过实例名称来寻址服务的 spring.application.name=instanceClient #指定Eureka服务端访问路径 eureka.client.service-url.defaultZone=http://localhost:5121/eureka |
2.4.3 第三步:修改发现服务入门程序注解
@SpringBootApplication //标记该项目为一个,该实例是一个发现服务的实例 @EnableDiscoveryClient public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } |
2.4.4 第四步:启动实例
启动实例2,确定实例在Eureka服务端注册时成功的。
--如果启动成功,会暴露一个application.xml配置文件指定的访问端口8081
|
2.5 第四部分:实现instanceClient与instanceServer的远程调用
需求:
(1)在instanceServer中,我们暴露一个login的远程restful接口。
(2)instanceClient调用该接口。将数据传递给它。
说明:SpringCloud远程服务调用,有两种实现方式:
(1)Ribbon+RestTemplate,基于restful实现。
其中,Ribbon是一个基于HTTP和TCP客户端的负载均衡器。
(2)Feign
其中,Feign默认启动Ribbon负载均衡。
步骤说明:(1)修改注册服务代码
(2)修改发现服务代码
(3)启动实例,实现服务调用
(4)负载均衡实现。
2.5.1 第一步:修改注册服务,注册login登陆服务
(1)创建User类
package cn.gzsxt.instance.pojo; import java.io.Serializable; public class User implements Serializable{ /** * */ private static final long serialVersionUID = 7260598142983180828L; private Integer id; private String username; private String password; //补全get、set方法 } |
(2)修改UserController类,新增登录方法
package cn.gzsxt.instance.controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import cn.gzsxt.instance.pojo.User; @RestController public class UserController { /** * 用户登录 * @return */ @RequestMapping(value="/login",method=RequestMethod.POST) public String login(@RequestBody User user){ System.out.println("用户名:"+user.getUsername()+",密码:"+user.getPassword()); return "Ok—intanceServer--8080"; } } |
2.5.2 第二步:修改发现服务实例instanceClient
(1)添加Ribbon依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> |
(2)修改Application启动类,标记该实例是发现服务实例
//1.用于启动Spring boot项目 @SpringBootApplication //2.用于标识该项目是一个Eureka客户端(发现服务) @EnableDiscoveryClient public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } //2.创建RestTemplate实例对象,用来远程调用服务 @Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); } } |
(3)创建UserService类
package cn.gzsxt.instance.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import cn.gzsxt.instance.pojo.User; @Service public class UserService { @Autowired private RestTemplate restTemplate; public String login(User user){ String result = restTemplate.postForObject("http://instanceServer/login",user, String.class); return result; } } |
(4)修改UserController类
package cn.gzsxt.instance.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import cn.gzsxt.instance.pojo.User; import cn.gzsxt.instance.service.UserService; @RestController public class UserController { @Autowired private UserService userService; @RequestMapping("/login") public String login(User user){ String result = userService.login(user); System.out.println(result); return result; } } |
2.5.3 第三步:启动实例
说明:依次启动注册中心、服务提供实例、服务发现实例。
(1)启动注册中心
|
(2)启动服务提供者
|
(4)启动服务发现者
|
(5)访问注册中心 http://localhost:5121/eureka
|
(6)访问服务发现实例
http://localhost:8081/login?username=root&password=123
|
远程服务调用成功!!!
2.5.4 第四步:基于ribbon负载均衡实现
负载均衡概念:在多个并且相同的服务可用的情况下,通过一定的负载策略,均衡的去调用这些服务,让服务到达一个平衡的状态。
重用的负载策略:轮询、权重、一致性ip等。
基于ribbon负载均衡实现步骤:
(1)创建一个新的注册服务实现instanceServer2。(复制instanceServer即可)
|
(2)修改instanceServer2的maven坐标
<groupId>cn.gzsxt.springcloud</groupId> <artifactId>springcloud-demo-04-instanceServer2</artifactId> <version>1.0</version> |
(3)修改application.properties文件
说明:相同的服务,实例的名称也相同。
因此只用修改端口即可。
#指定实例端口 server.port=8082 #指定实例名 spring.application.name=instanceServer #指定Eureka服务端访问路径 eureka.client.service-url.defaultZone=http://localhost:5121/eureka |
(4)修改UserController代码
@RequestMapping(value="/login",method=RequestMethod.POST) public String login(@RequestBody User user){ System.out.println("用户名:"+user.getUsername()+",密码:"+user.getPassword()); return "Ok—intanceServer02--8082"; } |
(5)启动实例
|
(6)多次访问登陆接口,查看结果
--调用到注册服务实例1
|
--调用到注册服务实例2
|
基于ribbon负载均衡实现!!!
3 基于Feign实现服务调用
说明:在入门示例的基础上,复制一个新的发现服务实例instanceClient2。
步骤说明:(1)添加Feign客户端依赖
(2)修改服务发现代码
3.1 第一步:添加Feign依赖
修改pom.xml文件
<!-- 注意事项:必须要导入该包 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> |
3.2 第二步:修改UserService
说明:Feign是基于interface接口来发现服务的。
package cn.gzsxt.instance.service; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.RequestMapping; import cn.gzsxt.instance.pojo.User; @FeignClient(name="instanceServer") public interface UserService { @RequestMapping(value="/login") public String login(User user);
} |
3.3 第三步:修改启动类Application
说明:添加Feign客户端支持 @EnableFeignClients
package cn.gzsxt.instance; 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; //1.用于启动Spring boot项目 @SpringBootApplication //2.用于标识该项目是一个Eureka客户端(发现服务) @EnableDiscoveryClient @EnableFeignClients public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } |
3.4 第四步:启动instanceClient2
--调用到注册服务实例1
|
--调用到注册服务实例2
|
基于Feign远程访问成功!!!
4 Eureka高可用配置
4.1 入门示例存在的缺陷
在入门示例中,服务的注册、发现和调用,都是基于Eureka注册中心实现。
如果Eureka服务宕机了,整个服务就都不可用了。
解决的办法:
配置Eureka高可用,即配置多个Eureka服务器,当只要有一个Eureka还正常运行,就能够提供正常的服务。
4.2 配置步骤
第一步:先配置一个完整的Eureka服务器。
第二步:复制另外一个Eureka服务器。
第三步:修改两个Eureka的配置,实现这两个Eureka高可用。
4.3 第一步:配置一个Eureka服务器。(已实现)
4.4 第二步:复制另外一个Eureka服务器
--将第一个Eureka服务器复制一份,修改器配置为第二个Eureka服务。
|
4.4.1 修改pom.xml中的Eureka服务名
<groupId>cn.gzsxt.springcloud</groupId> <artifactId>springcloud-demo-01-eureka2</artifactId> <version>1.0</version> |
4.4.2 修改application.properties配置文件
--修改第二个Eureka的服务端口,不要和第一个冲突。
#1.配置端口 server.port=5122 #2.配置eureka主机名 eureka.instance.hostname=localhost #3.由于我们目前创建的应用是一个服务注册中心,而不是普通的应用,默认情况下,这个应用会向注册中心(也是它自己)注册它自己,设置为false表示禁止这种默认行为 eureka.client.register-with-eureka=false #4.表示不去检索其他的服务,因为服务注册中心本身的职责就是维护服务实例,它也不需要去检索其他服务 eureka.client.fetch-registry=false #5.对外提供的注册入口 eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/ |
4.5 第三步:配置两个Eureka高可用(通讯)
--注意:两个Eureka服务器,是通过主机名和端口来互相发现的。
因此配置Eureka高可用,就是在配置主机名和端口。
主机名(eureka.instance.hostname) |
服务端口(server.port) |
|
Eureka 1 |
eureka1 |
5121 |
Eureka 2 |
eureka2 |
5122 |
4.5.1 修改第一个Eureka的application.properties文件
#1.配置端口 server.port=5121 #2.配置eureka主机名 eureka.instance.hostname=eureka1 #3.由于我们目前创建的应用是一个服务注册中心,而不是普通的应用,默认情况下,这个应用会向注册中心(也是它自己)注册它自己,设置为false表示禁止这种默认行为 eureka.client.register-with-eureka=false #4.表示不去检索其他的服务,因为服务注册中心本身的职责就是维护服务实例,它也不需要去检索其他服务 eureka.client.fetch-registry=false #5.对外提供的注册入口,关联其它的Eureka2 eureka.client.service-url.defaultZone=http://eureka2:5122/eureka/ |
4.5.2 修改第二个Eureka的application.properties文件
#1.配置端口 server.port=5122 #2.配置eureka主机名 eureka.instance.hostname=eureka2 #3.由于我们目前创建的应用是一个服务注册中心,而不是普通的应用,默认情况下,这个应用会向注册中心(也是它自己)注册它自己,设置为false表示禁止这种默认行为 eureka.client.register-with-eureka=false #4.表示不去检索其他的服务,因为服务注册中心本身的职责就是维护服务实例,它也不需要去检索其他服务 eureka.client.fetch-registry=false #5.对外提供的注册入口,关联其它的Eureka2 eureka.client.service-url.defaultZone=http://eureka1:5121/eureka/ |
4.5.3 修改本地hosts文件,注册Eureka主机名
文件位置:C:\Windows\System32\drivers\etc\hosts。(注意:使用管理员身份编辑)
|
4.6 第四步:分别启动两个Eureka测试
--启动Eureka1成功
|
--启动Eureka2成功
|
--访问Eureka1控制台
|
--访问Eureka2控制台
|
4.7 第五步:测试Eureka高可用
步骤说明:
(1)修改前面的实例,使用Eureka集群配置。
(2)依次启动前面的实例。
(3)通过instanceClient调用服务。
(4)关闭其中一个Eureka,观察是否任然可以调用成功。
(5)如果任然可用,则Eureka高可用配置成功。
4.7.1 修改实例instanceServer的application.properties文件
#指定实例名 spring.application.name=instanceServer #指定Eureka服务端访问路径,多个Eureka使用逗号隔开 eureka.client.service-url.defaultZone=http://eureka1:5121/eureka, http://eureka2:5122/eureka #指定实例端口 server.port=8080 |
4.7.2 修改实例instanceClient的application.properties文件
#指定实例名 spring.application.name=instanceClient #指定Eureka服务端访问路径,多个Eureka使用逗号隔开 eureka.client.service-url.defaultZone=http://eureka1:5121/eureka, http://eureka2:5122/eureka #指定实例端口 server.port=8081 |
4.7.3 修改实例instanceServer2的application.properties文件
#指定实例名 spring.application.name=instanceServer #指定Eureka服务端访问路径,多个Eureka使用逗号隔开 eureka.client.service-url.defaultZone=http://eureka1:5121/eureka, http://eureka2:5122/eureka #指定实例端口 server.port=8082 |
4.7.4 依次启动这三个实例
--启动实例instanceServer成功
|
--启动实例instanceClient成功
|
--启动实例instanceServer2成功
|
4.7.5 测试实例2调用远程服务
|
--测试成功。
4.7.6 测试Eureka高可用
--关闭Eureka1
|
--重新访问实例2
|
--测试成功。高可用配置成功!!!
5 Eureka安全认证
说明:访问Eureka时,需要指定用户名、密码进行身份认证。
配置步骤说明:(1)在Eureka服务端,开启安全认证
(2)在Eureka客户端,进行身份认证
5.1 第一部分:在Eureka服务端开启身份认证
5.1.1 第一步:添加身份认证依赖
--修改pom.xml文件
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> |
5.1.2 第二步:开启身份认证
--在Eureka服务端,修改application.properties文件,指定用户名、密码
#配置Eureka安全认证 security.basic.enabled=true security.user.name=root security.user.password=gzsxt |
说明:如果配置了Eureka高可用,Eureka之间相互访问时,需认证身份。
#1.配置端口 server.port=5121 #2.配置eureka主机名 eureka.instance.hostname=eureka1 #3.是否将自身注册为服务 false表示不注册 eureka.client.register-with-eureka=false #4.是否主动发现服务 false表示不发现 eureka.client.fetch-registry=false #5.对外提供的注册入口 eureka.client.service-url.defaultZone=http://root:gzsxt@eureka2:5122/eureka/ #配置Eureka安全认证 security.basic.enabled=true security.user.name=root security.user.password=gzsxt |
5.2 第二部分:在Eureka客户端进行身份认证
--在服务系统中,修改application.properties文件,进行身份认证
#指定Eureka服务端访问路径 eureka.client.service-url.defaultZone=http://root:gzsxt@eureka1:5121/eureka,http://root:gzsxt@eureka2:5122/eureka |
6 SpringBoot项目打包发布
说明:(1)SpringBoot项目推荐使用jar包的方式,来发布项目。
(2)如果是使用war方式创建的项目,则发布直接将war拷贝到tomcat 中。
步骤说明:(1)使用maven命令,将项目打成jar包
(2)上传jar到Linux服务器上
(3)编写启动文件,启动项目
6.1 第一步:使用Maven打包
说明:使用maven clean 以及install命令来打包。
项目最终打包在target目录下
|
6.2 第二步:上传到Linux环境
说明:使用xftp文件传输工具,将jar上传到linux上
|
6.3 第三步:编写启动文件
(1)创建start.sh文件 vim start.sh
#!/bin/bash java -jar eurekaServer-1.0.jar |
(2)修改启动文件的权限,添加一个可执行权限
[root@node0927 eureka]# chmod 744 start.sh |
(3)执行该文件,启动jar包程序
说明:使用nohup ./start.sh & 来启动项目。
好处:后台启动
nohup说明:Linux中,将当前的线程转为后台执行的命令
[root@node0823 eureka]# nohup ./start.sh & |
特别说明:当项目分布在多台机器上时,如果项目之间是通过主机名来发现的,那么要修改每一个机器的/etc/hosts文件,配置ip地址和主机名的关系。
192.168.4.253 eureka1 192.168.4.253 eureka2 |
(1)其中 192.168.4.253是主机的ip地址,eureka是其对应的主机名
(2)同一台机器的主机名可以配置多个。只要能对应上ip地址就行。
7 改造电商系统为springcloud分布式架构
思路:(1)在ego-project添加springcloud支持,锁定版本。
(2)改造ego-order、ego-rest等注册服务实例系统。(即提供服务)
(3)改造ego-portal,使用springcloud发现服务,并且调用服务。
7.1 第一步:改造ego-project为springcloud系统
--说明:修改pom.xml文件,添加springcloud支持,锁定版本
<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>cn.gzsxt.ego</groupId> <artifactId>ego-project</artifactId> <version>1.0</version> <packaging>pom</packaging>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.17.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>
<!-- 集中定义依赖版本号 --> <properties> <junit.version>4.12</junit.version> <spring.version>4.3.16.RELEASE</spring.version> <mybatis.plus.version>2.3</mybatis.plus.version> <mysql.version>5.1.40</mysql.version> <slf4j.version>1.6.4</slf4j.version> <jackson.version>2.9.5</jackson.version> <druid.version>1.0.9</druid.version> <httpclient.version>4.3.5</httpclient.version> <jstl.version>1.2</jstl.version> <servlet-api.version>2.5</servlet-api.version> <jsp-api.version>2.0</jsp-api.version> <joda-time.version>2.5</joda-time.version> <commons-lang3.version>3.3.2</commons-lang3.version> <commons-io.version>1.3.2</commons-io.version> <commons-net.version>3.3</commons-net.version> <commons-fileupload.version>1.3.1</commons-fileupload.version> <jedis.version>2.7.2</jedis.version> <solrj.version>4.10.3</solrj.version> <activemq.version>5.9.0</activemq.version> <java.version>1.8</java.version> <spring-cloud.version>Edgware.SR5</spring-cloud.version> </properties> <dependencyManagement> <dependencies> <!-- 时间操作组件 --> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>${joda-time.version}</version> </dependency> <!-- Apache工具组件 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>${commons-lang3.version}</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-io</artifactId> <version>${commons-io.version}</version> </dependency> <dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>${commons-net.version}</version> </dependency> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-all</artifactId> <version>${activemq.version}</version> </dependency> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-pool</artifactId> <version>${activemq.version}</version> </dependency> <!-- Jackson Json处理工具包 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.version}</version> </dependency> <!-- httpclient --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>${httpclient.version}</version> </dependency> <!-- 单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <!-- 日志处理 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> <!-- Mybatis --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>${mybatis.plus.version}</version> </dependency> <!-- MySql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!-- 连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <!-- Spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <!-- Spring-JMS插件相关jar包依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <!-- JSP相关 --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>${servlet-api.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>${jsp-api.version}</version> <scope>provided</scope> </dependency> <!-- 文件上传组件 --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>${commons-fileupload.version}</version> </dependency> <!-- Redis客户端 --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>${jedis.version}</version> </dependency> <!-- solr客户端 --> <dependency> <groupId>org.apache.solr</groupId> <artifactId>solr-solrj</artifactId> <version>${solrj.version}</version> </dependency> <!-- 锁定springcloud版本 --> <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>
<modules> <!-- <module>ego-base</module> --> <module>ego-manager</module> <module>ego-rest</module> <module>ego-portal</module> <module>ego-search</module> <module>ego-sso</module> <module>ego-order</module> </modules> </project> |
7.2 第二步:改造ego-order系统为注册服务实例系统
(1)添加eureka客户端依赖支持,修改pom.xml文件
<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.gzsxt.ego</groupId> <artifactId>ego-project</artifactId> <version>1.0</version> </parent> <artifactId>ego-order</artifactId> <packaging>war</packaging>
<dependencies> <!-- 添加ego-base公共系统依赖 --> <dependency> <groupId>cn.gzsxt.ego</groupId> <artifactId>ego-base</artifactId> <version>1.0</version> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatisplus-spring-boot-starter</artifactId> <version>1.0.4</version> </dependency>
<!-- 添加eureka客户端依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
<!-- 导入spring-jdbc包+事物 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> </dependency>
<!-- 导入切面依赖包 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </dependency>
<!-- 导入jdbc驱动+连接池 --> <!-- MySql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- 连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> </dependencies>
</project> |
(2)修改application.properties文件,配置eureka服务器地址
#配置数据源 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/ego spring.datasource.username=root spring.datasource.password=gzsxt #指定连接池的类型 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource #配置mybatis-plus mybatis-plus.type-aliases-package=cn.gzsxt.base.pojo #mybatis-plus.mapper-locations="clasapath:cn/gzsxt/base/mapper/*Mapper.xml" mybatis-plus.global-config.db-column-underline=true mybatis-plus.global-config.id-type=0 #配置server属性 server.port=8085 server.servlet-path=/order/* #配置当前实例系统的名称 spring.application.name=EgoOrderInstance #配置eureka注册中心的地址 eureka.client.service-url.defaultZone=http://root:gzsxt@eureka1:5121/eureka,http://root2:gzsxt2@eureka2:5122/eureka |
(3)修改启动类,添加eureka客户端注解依赖
package cn.gzsxt.order; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient //添加eureka客户端支持 public class EgoOrderApplication { public static void main(String[] args) { SpringApplication.run(EgoOrderApplication.class, args); } } |
(4)重启ego-order系统
|
(5)在eureka管理控制台,查看服务注册情况
|
ego-order工程改造成功!!!
7.3 第三步:改造ego-portal工程为发现服务实例系统
(1)添加eureka发现服务依赖,修改pom.xml文件
<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.gzsxt.ego</groupId> <artifactId>ego-project</artifactId> <version>1.0</version> </parent> <artifactId>ego-portal</artifactId> <packaging>war</packaging>
<dependencies> <!-- 添加ego-base公共系统依赖 --> <dependency> <groupId>cn.gzsxt.ego</groupId> <artifactId>ego-base</artifactId> <version>1.0</version> </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-feign</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency>
<!-- jsp视图依赖包 --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> </dependencies>
</project> |
(2)修改application.properties文件,配置eureka注册中心地址
#配置视图解析器 spring.mvc.view.prefix=/WEB-INF/jsp/ spring.mvc.view.suffix=.jsp #配置server属性 server.port=8082 server.servlet-path=*.html #配置实例名称 spring.application.name=EgoPotalInstance #配置eureka注册中心的地址 eureka.client.service-url.defaultZone=http://root:gzsxt@eureka1:5121/eureka,http://root2:gzsxt2@eureka2:5122/eureka |
(3)修改启动类,添加发现服务注解支持
package cn.gzsxt.portal; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.feign.EnableFeignClients; @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class EgoPortalApplication extends SpringBootServletInitializer{ @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { // TODO Auto-generated method stub return builder.sources(EgoPortalApplication.class); } public static void main(String[] args) { SpringApplication.run(EgoPortalApplication.class, args); } } |
(4)创建OrderServiceApi接口(interface),不需要实现。
package cn.gzsxt.portal.service; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.RequestMapping; import cn.gzsxt.base.vo.EgoResult; import cn.gzsxt.base.vo.OrderDetail; @FeignClient(value="EgoOrderInstance") public interface OrderServiceApi { @RequestMapping("/order/create") public EgoResult save(OrderDetail order); } |
(5)修改OrderController类,使用springcloud远程调用保单订单接口
package cn.gzsxt.portal.controller; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.List; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import cn.gzsxt.base.vo.CartItem; import cn.gzsxt.base.vo.EgoResult; import cn.gzsxt.base.vo.OrderDetail; import cn.gzsxt.portal.service.OrderService; import cn.gzsxt.portal.service.OrderServiceApi; @Controller @RequestMapping("/order") public class OrderController { @Autowired private OrderService orderService; @Autowired private OrderServiceApi orderServiceApi; @RequestMapping("/order-cart") public String showOrderCart(HttpServletRequest request){ List<CartItem> cart = orderService.getCart(request); request.setAttribute("cartList", cart); return "order-cart"; } @RequestMapping("/create") public String save(OrderDetail order,ModelMap map){ try { EgoResult result = orderServiceApi.save(order); if(200==result.getStatus()){ Long orderId = (Long) result.getData(); map.addAttribute("orderId", orderId); map.addAttribute("payment", order.getPayment()); //预计送货时间,下单三天之后。 //默认送到时间,在3天后 Calendar c=Calendar.getInstance(); SimpleDateFormat df=new SimpleDateFormat("yyyy/MM/dd/E"); c.add(Calendar.DATE, 3); System.out.println(df.format(c.getTime())); map.addAttribute("date", df.format(c.getTime())); return "success"; } } catch (Exception e) { e.printStackTrace(); } map.addAttribute("message", "服务器忙,请稍后再试!"); return "error/exception"; } } |
(6)重启ego-portal工程
|
(7)访问eureka管理控制台
|
改造ego-portal订单模块成功!!!