springboot + eureka集羣,實現註冊中心,實現負載均衡

搭建eureka集羣

- 新建一個boot項目

File-》new-》project
在這裏插入圖片描述如圖選擇-》next-》起名字如下
在這裏插入圖片描述->next -》finish

- 新建3個註冊中心
以三個註冊中心爲例,想多的自己加
項目名字上-》new-》module
在這裏插入圖片描述-》next-》起名字-》next
選擇依賴
Web —spring web////這個就別選了,截圖截多一個。選後兩個就行
Security ----Spring Security
Spring Cloud Discovery----Eureka Server
在這裏插入圖片描述修改pom.xml,解決java8版本的問題,後面每個服務都要改這個,我的idea默認jdk6,導致啓動失敗,加了這個就默認爲JDK1.8了

<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal><!--可以把依賴的包都打包到生成的Jar包中-->
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <!--指定jdk版本-->
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

配置application.yml
注意defaultZone,本例是三個註冊中心,中心1配置地址2、3,中心2配置地址3、1,中心3配置地址1、2。注意順序,
對於註冊中心eureka默認優先註冊到最前面那個,也就是1註冊到2,2註冊到3,3註冊到1.
當其中一個註冊中心死掉後,纔會註冊到其他地方。如2死掉了,1會註冊到第二個地址3上面,結果就成了1註冊到3,3註冊到1.

eureka:
  instance:
    hostname: localhost
  client:
    #  eureka.client.registerWithEureka:false   因爲自己是爲註冊中心,不需要自己註冊自己  集羣模式下改爲 ture,註冊到其他註冊中中心
    # 是否將該實例信息註冊到其他eureka server上;如果設置爲false,那麼該server無法被其他server發現,但是仍然可以發現其他server
    #  fetchRegistry:false來表明自己是一個eureka server.
    registerWithEureka: true
    #表示是否向eureka註冊服務,即在eureka中註冊自己,默認爲true,此處應該設置爲true,只有一個註冊中心時爲false;
    #是否允許該客戶端從eureka server上獲取註冊信息
    fetchRegistry: true
    serviceUrl:
      #    集羣模式:
      defaultZone: http://admin:admin2@${eureka.instance.hostname}:8762/eureka/,http://admin:admin3@${eureka.instance.hostname}:8763/eureka/
      #    單例模式:
	#defaultZone: http://admin:admin1${eureka.instance.hostname}:8761/eureka/
      #沒有密碼時,去掉security依賴,配置:    defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  server:
    #設爲false,關閉自我保護,即Eureka server在雲心光器件會去統計心跳失敗比例在15分鐘之內是否低於85%,如果低於85%,EurekaServer
    #會將這些事例保護起來,讓這些事例不會過期,但是在保護器內如果剛哈這個服務提供者非正常下線了,此時服務消費者會拿到一個無效的服務
    #實例,此時調用會失敗,對於這個問題需要服務消費者端有一些容錯機制,如重試、斷路器等;
    enable-self-preservation: false
    #掃描失效服務的間隔時間(單位是毫秒,摩恩是60*1000),即60s
    eviction-interval-timer-in-ms: 10000


server:
  #服務端口號
  port: 8761

spring:
  application:
    name: a-server1
#  #安全登入用戶設置   ####******** 用戶名密碼,三個項目建議不一樣
  security:
    user:
      name: admin
      password: admin1

其他兩個按這個配置,記得改defaultZone,和password
修改啓動類
加兩個註解就可以了。

@EnableEurekaServer
@SpringBootApplication
public class AiServer1Application {

    public static void main(String[] args) {
        SpringApplication.run(AiServer1Application.class, args);
    }

}

本來這樣就可以啓動了,但是我們配置了security安全驗證,
而新版(Spring Cloud 2.0 以上)的security默認啓用了csrf檢驗,要在eurekaServer端配置security的csrf檢驗爲false
新建一個類WebSecurityConfig,關閉csrf檢驗

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        super.configure(http);
    }
}

其他兩個按這個寫,到此一個簡單的eureka集羣就搭建完成了。
啓動會報錯,不用管,這個是註冊到其他註冊中心時沒掃描到,原因是啓動註冊中心1時2還沒啓動,總得有個先後,都啓動了就好了。

com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused: connect

登錄http://IP:8761/
登錄http://IP:8762/
登錄http://IP:8763/
本地啓動要輸入密碼
註冊1:註冊2註冊3可以看出,1註冊在2,2註冊在3,3註冊在1.
註冊中心完成。
可以嘗試關閉其中某個看看註冊情況。可能有時差大概30s。

搭建服務提供者client

筆者將上述註冊中心佈置到了服務器。所以服務提供者就按照服務器配置了,本地的話,把ip改爲localhost就行。
新建提供者1
項目名字-》new-》mudule-》next-》起名字-》next
選擇依賴(兩個)
Web —spring web
Spring Cloud Discovery----Eureka Server
配置application.yml

spring:
  application:
    name: ai-client1
server:
  port: 8769
eureka:
  instance:
  	# 服務提供者地址
    hostname: localhost
    # 註冊中心ip(根據實際,本地寫localhost)
    hostname1: 47.102.111.111
  client:
    serviceUrl:
      # 集羣時,其實只需要配置一個地址,當這個地址的註冊中心掛掉後,會自動註冊到其他註冊中心
      # 配置多個註冊中心地址的好處是:啓動之前,某個註冊中心掛掉了,會拋出異常,但是也會正常註冊到其他某個註冊中心
      defaultZone: http://admin:admin1@${eureka.instance.hostname1}:8761/eureka/,http://admin:admin2@${eureka.instance.hostname1}:8762/eureka/,http://admin:admin3@${eureka.instance.hostname1}:8763/eureka/

啓動類

@RestController
@EnableEurekaClient
@SpringBootApplication
public class AiClient1Application {

    public static void main(String[] args) {
        SpringApplication.run(AiClient1Application.class, args);
    }
    /**
     * 假如這個客戶端要提供一個getUser的方法
     * @return
     */
    @GetMapping(value = "/getUser")
    @ResponseBody
    public Map<String,Object> getUser(@RequestParam Integer id){
        Map<String,Object> data = new HashMap<String,Object>();
        data.put("id",id);
        data.put("userName","admin");
        data.put("from","provider-A");
        return data;
    }
}

新建提供者2
內容跟提供者1一樣。
爲了測試負載均衡,不要改服務名字,必須保持一致。
spring.application.name=ai-client1
修改一下端口號和輸出結果就行,不同輸出結果驗證是哪個服務處理的請求。
如data.put(“from”,“provider-B1111111111”);
能看出不同就行。

啓動提供者,發現3號註冊中心會有這兩個服務

搭建服務消費者customer

搭建一個消費者customer
新建流程通服務提供者。
application.yml配置如下

eureka:
  instance:
    # 服務提供者地址
    hostname: localhost
    # 註冊中心ip(根據實際,本地寫localhost)
    hostname1: 47.102.111.111
  client:
    serviceUrl: #註冊中心的註冊地址
#      defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/,http://localhost:8763/eureka/
      defaultZone: http://skyworth:skyworth1@${eureka.instance.hostname1}:8761/eureka/,http://skyworth:skyworth2@${eureka.instance.hostname1}:8762/eureka/,http://skyworth:skyworth3@${eureka.instance.hostname1}:8763/eureka/
server:
  port: 8759  #服務端口號
spring:
  application:
    name: service-consumer #服務名稱--調用的時候根據名稱來調用該服務的方法

修改啓動類

/**
 * Eureka客戶端-消費者
 */
@RestController
@EnableEurekaClient
@SpringBootApplication
public class AiConsumer1Application {

    @Autowired
    RestTemplate restTemplate;

    public static void main(String[] args) {
        SpringApplication.run(AiConsumer1Application.class, args);
    }

    /**
     * 實例化RestTemplate
     * @return
     */
    @LoadBalanced
    @Bean
    public RestTemplate rest() {
        return new RestTemplate();
    }

    /**
     * Rest服務端使用RestTemplate發起http請求,然後得到數據返回給前端----gotoUser是爲了區分getUser怕小夥伴暈頭
     * @param id
     * @return
     */
    @GetMapping(value = "/gotoUser")
    @ResponseBody
    public Map<String,Object> getUser(@RequestParam Integer id){
        Map<String,Object> data = new HashMap<String,Object>();
        /**
         * 小夥伴發現沒有,地址居然是http://service-provider
         * 居然不是http://127.0.0.1:8082/
         * 因爲他向註冊中心註冊了服務,服務名稱service-provider,我們訪問service-provider即可
         *
         * 注意要容錯,當發生錯誤時重新掉這個接口,防止發生某個服務掛掉,請求失敗的情況。
         */
        data = restTemplate.getForObject("http://ai-client1/getUser?id="+id, Map.class);
        return data;
    }
}

啓動消費者,發現3號註冊中心會有這個服務。

訪問地址:http:localhost:8759/gotoUser?id=1
多次訪問,發現會分別從服務1,服務2 返回結果。(服務1,2 返回結果要設置的不一樣,才能看出來的。)

總結幾個坑

1.解決java8版本的問題,後面每個服務都要改這個,我的idea默認jdk6,導致啓動失敗,加了這個就默認爲JDK1.8了
2.新版(Spring Cloud 2.0 以上)的security默認啓用了csrf檢驗,要在eurekaServer端配置security的csrf檢驗爲false
3.使用了安全驗證,註冊地址要加上username:password@,
http://username:password@${eureka.instance.hostname}:8762/eureka/
4.將註冊中心部署到服務器之後,如果服務要連接服務時,
要設置eureka.instance.hostname=localhost,如果寫成服務器ip,連接會成功,但是消費者會調用失敗,因爲跳轉的時候會跳轉到,服務器上的這個服務,而實際的服務在本地。

發佈了36 篇原創文章 · 獲贊 14 · 訪問量 8314
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章