本例子主要使用了eureka集群作為注冊中心來保證高可用,客戶端來做ribbon服務提供者的負載均衡。
負載均衡有兩種,第一種是nginx,F5這種集中式的LB,對所有的訪問按照某種策略分發。
第二種是客戶端知道所有的服務的地址,在客戶端做負載均衡,客戶端自己去發送。
github地址:https://github.com/linjiaqin/scdemo
一. eureka注冊中心的搭建
1.為了實現HA(高可用性),采用集群方式搭建,由mu01(192.168.0.100),cu01(192.168.0.1), cu02(192.168.0.2)三台機子組成
為了不寫ip地址而使用主機名表示,首先修改/etc/hosts文件,將對應的hostname和ip寫入該文件,然后source生效
2.idea新建一個module,spring assistant類型,選擇springcloud,web和eureka server兩個模板。
為其啟動類加上@EnableEurekaServer
package com.ljq;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
3.編寫配置文件
配置文件application-backone.properties
#服務名和服務暴露的接口 spring.application.name=backup_one server.port=8762 eureka.instance.hostname=cu01 #本項目是注冊中心所以不需要自己向自己注冊和檢索服務,如果是eureka集群就要 #eureka.client.register-with-eureka=false #eureka.client.fetch-registry=false #eureka.client.serviceUrl.defaultZone :設置與Eureka Server交互的地址,查詢服務和注冊服務都需要依賴這個地址。 # 默認是http://localhost:8761/eureka ;多個地址可使用 , 分隔。 eureka.client.serviceUrl.defaultZone=http://mu01:8761/,http://cu02:8763/
配置文件application-backtwo.properties
#服務名和服務暴露的接口 spring.application.name=backup_two server.port=8763 eureka.instance.hostname=cu02 #本項目是注冊中心所以不需要自己向自己注冊和檢索服務,如果是eureka集群就要 #eureka.client.register-with-eureka=false #eureka.client.fetch-registry=false #eureka.client.serviceUrl.defaultZone :設置與Eureka Server交互的地址,查詢服務和注冊服務都需要依賴這個地址。 # 默認是http://localhost:8761/eureka ;多個地址可使用 , 分隔。 eureka.client.serviceUrl.defaultZone=http://mu01:8761/,http://cu01:8762/
配置文件application-master.properties
#服務名和服務暴露的接口 spring.application.name=master server.port=8761 eureka.instance.hostname=mu01 #本項目是注冊中心所以不需要自己向自己注冊和檢索服務,如果是eureka集群就要 #eureka.client.register-with-eureka=false #eureka.client.fetch-registry=false #eureka.client.serviceUrl.defaultZone :設置與Eureka Server交互的地址,查詢服務和注冊服務都需要依賴這個地址。 # 默認是http://localhost:8761/eureka ;多個地址可使用 , 分隔。 eureka.client.serviceUrl.defaultZone=http://cu01:8762/,http://cu02:8763/
4.如果在本機模擬的話,在idea中打開3個terminal,分別執行下面的命令,開啟了eureka集群,后面那里不需要使用配置文件的全名
mvn spring-boot:run -Dspring.profiles.active=master mvn spring-boot:run -Dspring.profiles.active=backone mvn spring-boot:run -Dspring.profiles.active=backtwo
5.在集群中開啟的話,為了不每一次都登錄到多台機子上,寫一個一鍵啟動腳本,自動ssh到每台機子上去開啟。
這里bash腳本是linux腳本,sh腳本是unix腳本,雖然通用,但是語法有些不同。
因為是阻塞式進程,所以使用nohup ... > /dev/null,使得該進程能在后台執行。
同時ssh之后還要export javahome/bin,不知為什么這么玄學,ssh之后用的不是該用戶環境變量之中的java
#!/bin/bash
echo "start eureka server..."
num=0
server=("master" "backone" "backtwo")
for host in mu01 cu01 cu02
do
echo ${server[$num]}
ssh $host "export JAVA_HOME=/data/home/hadoop/jdk1.8.0_40;
CLASSPATH=.:$JAVA_HOMElib/tools.jar:$JAVA_HOME/lib/dt.jar;
export CLASSPATH;
PATH=$JAVA_HOME/bin:$PATH;
export PATH;
java -version;
cd /software/home/linjiaqing/eureka;
nohup java -jar server-0.0.1-SNAPSHOT.jar --spring.profiles.active=${server[$num]} > /dev/null"
num=$(($num+1))
done
打開瀏覽器,下面是效果圖,每個節點都能看到備份

二. 服務提供者
1.引導類加上注解EnableEurekaClient,說明他是一個服務提供者
package com.ljq;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
//服務提供者用這個注解
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
2.Controller
package com.ljq;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ljqController {
@Value("${server.port}")
String port;
@RequestMapping("/")
public String home(){
return "Hello world, port is:" + port;
}
}
3.配置文件
spring.application.name=eureka-client-service-provider server.port=20001 eureka.client.serviceUrl.defaultZone=http://mu01:8761/eureka,http://cu01:8762/eureka,http://cu02:8763/eureka
4.啟動,IDEA打開三個客戶端,分別使用命令mvn spring-boot:run -Dserver.port=20001,20002,20003如下圖可以看到它去eureka的某個節點上注冊了


5.HA的體現,將cu01的進程kill之后,發現服務會自動去mu01上注冊

三 服務消費者使用負載均衡
1.ljqConfig
這里是一個beanconfig,為了RestTemplate能夠被只用
package com.ljq;
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 ljqConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
2.ljqController
使用服務提供者的名字http://eureka-client-service-provider/,不用再使用地址
package com.ljq;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class ljqController {
@Autowired
private RestTemplate restTemplate;
//這里不寫eureka的注冊中心,而是寫服務提供者的應用名
@GetMapping(value = "/hello")
public String hello(){
return restTemplate.getForEntity("http://eureka-client-service-provider/", String.class).getBody();
}
}
3.引導類的EnableDiscoveryClient注解表明是消費者
package com.ljq;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
4.配置文件
spring.application.name=ribbon-consumer server.port=30001 eureka.client.serviceUrl.defaultZone=http://mu01:8761/eureka,http://cu01:8762/eureka,http://cu02:8763/eureka
5.消費者啟動后也去eureka中注冊了

可以看到已經有了ribbon負載均衡的效果

