onetsetsani kuti makope awiri a code yanu yopanga ("buluu" ndi "green") amagwira ntchito;
kuwongolera magalimoto onse ku chilengedwe cha buluu, i.e. kotero kuti ma URL opanga amaloze pamenepo;
tumizani ndikuyesa kusintha konse kwa ntchito pamalo obiriwira;
sinthani ma ulalo kuchokera ku buluu kupita ku malo obiriwira
Kutumiza kobiriwira kwa buluu ndi njira yomwe imakupatsani mwayi wowonetsa zatsopano popanda kudandaula za kusweka kwa kupanga. Izi ndichifukwa choti ngakhale zitachitika zinazake, mutha kubwereranso kumalo am'mbuyomu ndikungoyang'ana chosinthira.
Mutawerenga zonse zomwe zili pamwambapa, mutha kufunsa funso: Kodi zero downtime ikukhudzana bwanji ndi Blue green deployment?
Eya, ali ndi zambiri zofanana, popeza kusunga makope aŵiri a malo ofanana kumafuna khama loŵirikiza kaŵiri kuwasamalira. Ichi ndichifukwa chake matimu ena amati Martin Fowler, tsatirani kusiyanasiyana kwa njira iyi:
Njira ina ndikugwiritsa ntchito nkhokwe yomweyo, kupanga masiwichi obiriwira abuluu pa intaneti ndi magawo a domain. Mwanjira iyi, nkhokwe nthawi zambiri imakhala vuto, makamaka mukafunika kusintha schema yake kuti muthandizire pulogalamu yatsopano.
Ndipo apa tabwera ku vuto lalikulu m'nkhaniyi. Nawonsomba. Tiyeni tionenso mawuwa.
kusamutsa database.
Tsopano muyenera kudzifunsa funsoli - bwanji ngati kusintha kwa database sikukugwirizana ndi kumbuyo? Kodi mtundu wanga woyamba wa pulogalamuyi sutha? M'malo mwake, izi ndi zomwe zidzachitike ...
CREATE TABLE PERSON (
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
first_name varchar(255) not null,
last_name varchar(255) not null
);
insert into PERSON (first_name, last_name) values ('Dave', 'Syer');
Chilichonse chimadzifotokozera chokha: mutha kugwiritsa ntchito SQL kutanthauzira momwe database yanu iyenera kusinthidwa. Kuti mumve zambiri za Spring Boot ndi Flyway, onani Spring Boot Docs.
Pogwiritsa ntchito chida chowongolera magwero ndi Spring Boot, mumapeza zabwino ziwiri:
mumalekanitsa zosintha za database ndikusintha ma code
Kusamuka kwa database kumachitika limodzi ndi kutulutsidwa kwa pulogalamu yanu, i.e. ndondomeko yanu yotumizira idzakhala yosavuta
Kuthetsa mavuto a database
Mu gawo lotsatira la nkhaniyi, tiyang'ana pa kuyang'ana njira ziwiri zosinthira database.
Pulojekiti yathu yomwe tikhala tikugwirapo ikhala pulogalamu yosavuta ya Spring Boot Flyway yomwe ili nayo Person с first_name и last_name mu database (pafupifupi. kumasulira: Person ndi tebulo ndi first_name и last_name - awa ndi minda momwemo). Tikufuna kutchula dzina last_name в surname.
Kubweza kuyenera kuchitika kokha ngati kuli kofunikira. Ngati pali vuto mu mtundu wapano womwe suli wokonzeka kukhazikika, tiyenera kubwerera ku mtundu waposachedwa kwambiri. Tikuganiza kuti mtundu waposachedwa uwu ndi wam'mbuyo. Kusunga ma code ndi nkhokwe yogwirizana ndi kutulutsa kopitilira kumodzi kungakhale kovuta kwambiri komanso kokwera mtengo.
Kalata. Kuti muwerenge kwambiri, m'nkhaniyi tisintha mtundu waukulu wa pulogalamuyi.
Gawo 1: Dziko Loyamba
Mtundu wa App: 1.0.0
Mtundu wa DB: v1
ndemanga
Ichi chidzakhala chikhalidwe choyambirira cha ntchito.
Kusintha kwa database
DB ili ndi last_name.
CREATE TABLE PERSON (
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
first_name varchar(255) not null,
last_name varchar(255) not null
);
insert into PERSON (first_name, last_name) values ('Dave', 'Syer');
Kusintha kwa ma code
Pulogalamuyi imasunga data ya Munthu mkati last_name:
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.flyway;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Person {
@Id
@GeneratedValue
private Long id;
private String firstName;
private String lastName;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastname) {
this.lastName = lastname;
}
@Override
public String toString() {
return "Person [firstName=" + this.firstName + ", lastName=" + this.lastName
+ "]";
}
}
Kusinthana kwazambiri kosagwirizana
Tiyeni tiwone chitsanzo cha momwe mungasinthire dzina lazambiri:
Chisamaliro. Chitsanzo chotsatirachi chidzaphwanya zinthu mwadala. Tikuwonetsa izi kuti tiwonetse vuto la kuyanjana kwa database.
Mtundu wa App: 2.0.0.BAD
Mtundu wa DB: v2bad
ndemanga
Zosintha zomwe zasintha SAKUTIlola kuti tiziyendetsa zochitika ziwiri (zakale ndi zatsopano) nthawi imodzi. Choncho, kutumizidwa kwa zero kudzakhala kovuta kukwaniritsa (ngati zongoganizira zikuganiziridwa, sizingatheke).
Kuyesa kwa A/B
Zomwe zikuchitika pano ndikuti tili ndi mtundu wa pulogalamu 1.0.0, kutumizidwa mukupanga, ndi database v1. Tiyenera kugwiritsa ntchito chitsanzo chachiwiri cha pulogalamuyo, mtundu 2.0.0.BAD, ndikusintha database kuti v2bad.
Masitepe:
mawonekedwe atsopano a pulogalamu yamtunduwu atumizidwa 2.0.0.BADzomwe zimasintha database v2bad
mu nkhokwe v2bad ndime last_name kulibenso - idasinthidwa kukhala surname
Dongosolo la database ndi zosintha zamapulogalamu zidayenda bwino ndipo nthawi zina zikuyenda 1.0.0, ena - mkati 2.0.0.BAD. Chilichonse chikugwirizana ndi database v2bad
Monga mukuwonera, ngati tisintha m'mbuyo zosagwirizana ndi database ndi kugwiritsa ntchito, sitingathe kubwereranso ku mtundu wakale.
Zolemba za script
Backward incompatible scenario:
01) Run 1.0.0
02) Wait for the app (1.0.0) to boot
03) Generate a person by calling POST localhost:9991/person to version 1.0.0
04) Run 2.0.0.BAD
05) Wait for the app (2.0.0.BAD) to boot
06) Generate a person by calling POST localhost:9991/person to version 1.0.0 <-- this should fail
07) Generate a person by calling POST localhost:9992/person to version 2.0.0.BAD <-- this should pass
Starting app in version 1.0.0
Generate a person in version 1.0.0
Sending a post to 127.0.0.1:9991/person. This is the response:
{"firstName":"b73f639f-e176-4463-bf26-1135aace2f57","lastName":"b73f639f-e176-4463-bf26-1135aace2f57"}
Starting app in version 2.0.0.BAD
Generate a person in version 1.0.0
Sending a post to 127.0.0.1:9991/person. This is the response:
curl: (22) The requested URL returned error: 500 Internal Server Error
Generate a person in version 2.0.0.BAD
Sending a post to 127.0.0.1:9995/person. This is the response:
{"firstName":"e156be2e-06b6-4730-9c43-6e14cfcda125","surname":"e156be2e-06b6-4730-9c43-6e14cfcda125"}
Kusintha kwa database
Migration script yomwe imatchedwanso last_name в surname
Zolemba za Flyway:
CREATE TABLE PERSON (
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
first_name varchar(255) not null,
last_name varchar(255) not null
);
insert into PERSON (first_name, last_name) values ('Dave', 'Syer');
Script yomwe imatchedwanso last_name.
-- This change is backward incompatible - you can't do A/B testing
ALTER TABLE PERSON CHANGE last_name surname VARCHAR;
Izi ndizochitika zofala kwambiri zomwe tingakumane nazo. Tiyenera kupanga zobwerera mmbuyo zosagwirizana. Tatsimikizira kale kuti potumiza zero-downtime, sitiyenera kungogwiritsa ntchito kusamuka kwa database popanda njira zowonjezera. Mu gawo ili la nkhaniyi, tipanga ma deployments 3 a pulogalamuyo pamodzi ndi kusamuka kwa database kuti tikwaniritse zomwe mukufuna ndikusunga zobwerera m'mbuyo.
Kalata. Kumbukirani kuti tili ndi database ya mtundu v1. Lili ndi mizati first_name и last_name. Tiyenera kusintha last_name pa surname. Tilinso ndi mtundu wa pulogalamu 1.0.0, zomwe sizinagwiritsidwebe ntchito surname.
Gawo 2: Onjezani surname
Mtundu wa App: 2.0.0
Mtundu wa DB: v2
ndemanga
Powonjezera ndime yatsopano ndikukopera zomwe zili mkati mwake, timapanga zosinthika zobwerera m'mbuyo zomwe zimagwirizana. Nthawi yomweyo, ngati tibweza JAR kapena kukhala ndi JAR yakale yomwe ikuyenda, sichitha kuphedwa.
Tikutulutsa mtundu watsopano
Masitepe:
sinthani database kuti mupange gawo latsopano surname. Tsopano mtundu wanu wa DB v2
kukopera deta kuchokera last_name в surname. Samalanikuti ngati muli ndi zambiri izi, muyenera kuganizira kusamuka kwa batch!
lembani malamulo omwe agwiritsidwa ntchito ZOWIRI и новыйndi akale ndime. Tsopano mtundu wa pulogalamu yanu 2.0.0
werengani mtengo wagawolo surname, ngati sichoncho nullkapena ku last_namengati surname zomwe sizinafotokozedwe. Mutha kufufuta getLastName() kuchokera ku code, chifukwa idzatulutsa null pamene mukubweza pulogalamu yanu kuchokera 3.0.0 mpaka 2.0.0.
Zomwe zikuchitika pano ndikuti tili ndi mtundu wa pulogalamu 1.0.0, yotumizidwa pakupanga, ndi database mu v1. Tiyenera kuyikanso chitsanzo chachiwiri cha pulogalamuyo 2.0.0zomwe zidzasinthire database v2.
Masitepe:
mawonekedwe atsopano a pulogalamu yamtunduwu atumizidwa 2.0.0zomwe zimasintha database v2
Pakadali pano zopempha zina zidasinthidwa ndi mawonekedwe 1.0.0
kusinthidwa kunali kopambana ndipo muli ndi machitidwe angapo ogwiritsira ntchito mtunduwo 1.0.0 ndi Mabaibulo ena 2.0.0. Aliyense amalumikizana ndi database mu v2
Baibulo 1.0.0 sichigwiritsa ntchito gawo la surname mu database, koma mtunduwo 2.0.0 amagwiritsa. Sasokonezana, ndipo pasakhale zolakwa.
Malo osungirako zinthuwa ali ndi gawo lotchedwa last_name.
Flyway source script:
CREATE TABLE PERSON (
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
first_name varchar(255) not null,
last_name varchar(255) not null
);
insert into PERSON (first_name, last_name) values ('Dave', 'Syer');
-- NOTE: This field can't have the NOT NULL constraint cause if you rollback, the old version won't know about this field
-- and will always set it to NULL
ALTER TABLE PERSON ADD surname varchar(255);
-- WE'RE ASSUMING THAT IT'S A FAST MIGRATION - OTHERWISE WE WOULD HAVE TO MIGRATE IN BATCHES
UPDATE PERSON SET PERSON.surname = PERSON.last_name
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.flyway;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Person {
@Id
@GeneratedValue
private Long id;
private String firstName;
private String lastName;
private String surname;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
/**
* Reading from the new column if it's set. If not the from the old one.
*
* When migrating from version 1.0.0 -> 2.0.0 this can lead to a possibility that some data in
* the surname column is not up to date (during the migration process lastName could have been updated).
* In this case one can run yet another migration script after all applications have been deployed in the
* new version to ensure that the surname field is updated.
*
* However it makes sense since when looking at the migration from 2.0.0 -> 3.0.0. In 3.0.0 we no longer
* have a notion of lastName at all - so we don't update that column. If we rollback from 3.0.0 -> 2.0.0 if we
* would be reading from lastName, then we would have very old data (since not a single datum was inserted
* to lastName in version 3.0.0).
*/
public String getSurname() {
return this.surname != null ? this.surname : this.lastName;
}
/**
* Storing both FIRST_NAME and SURNAME entries
*/
public void setSurname(String surname) {
this.lastName = surname;
this.surname = surname;
}
@Override
public String toString() {
return "Person [firstName=" + this.firstName + ", lastName=" + this.lastName + ", surname=" + this.surname
+ "]";
}
}
Khwerero 3: Kuchotsa last_name pa code
Mtundu wa App: 3.0.0
Mtundu wa DB:v3
ndemanga
Zindikirani pa. last_name.
Powonjezera gawo latsopano ndikukopera zomwe zili mkati mwake, tidapanga zosintha zomwe zimagwirizana ndi database. Komanso, ngati tibweza JAR kapena kukhala ndi JAR yakale yomwe ikuyenda, sichitha kuphedwa.
Kubweza ntchito
Pano tili ndi mtundu wa pulogalamu 3.0.0 ndi database v3. Baibulo 3.0.0 sichisunga deta ku last_name. Izi zikutanthauza kuti mu surname zidziwitso zaposachedwa kwambiri zimasungidwa.
Masitepe:
bwezeretsani pulogalamu yanu kuti isinthe 2.0.0.
Baibulo 2.0.0 amagwiritsa ntchito ndi last_name и surname.
Baibulo 2.0.0 adzatenga surname, ngati si ziro, mwinamwake -last_name
Kusintha kwa database
Palibe zosintha zamapangidwe mu database. Malemba otsatirawa akuchitidwa kuti asamuke komaliza kwa data yakale:
-- WE'RE ASSUMING THAT IT'S A FAST MIGRATION - OTHERWISE WE WOULD HAVE TO MIGRATE IN BATCHES
-- ALSO WE'RE NOT CHECKING IF WE'RE NOT OVERRIDING EXISTING ENTRIES. WE WOULD HAVE TO COMPARE
-- ENTRY VERSIONS TO ENSURE THAT IF THERE IS ALREADY AN ENTRY WITH A HIGHER VERSION NUMBER
-- WE WILL NOT OVERRIDE IT.
UPDATE PERSON SET PERSON.surname = PERSON.last_name;
-- DROPPING THE NOT NULL CONSTRAINT; OTHERWISE YOU WILL TRY TO INSERT NULL VALUE OF THE LAST_NAME
-- WITH A NOT_NULL CONSTRAINT.
ALTER TABLE PERSON MODIFY COLUMN last_name varchar(255) NULL DEFAULT NULL;
Kusintha kwa ma code
Zindikirani pa.: Kufotokozera kwa chipikachi kunakoperanso molakwika ndi wolemba kuchokera pa sitepe 2. Mogwirizana ndi malingaliro a nkhaniyi, kusintha kwa code pa sitepe iyi kuyenera kukhala ndi cholinga chochotsamo zinthu zomwe zimagwira ntchito ndi gawoli. last_name.
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.flyway;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Person {
@Id
@GeneratedValue
private Long id;
private String firstName;
private String surname;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getSurname() {
return this.surname;
}
public void setSurname(String lastname) {
this.surname = lastname;
}
@Override
public String toString() {
return "Person [firstName=" + this.firstName + ", surname=" + this.surname
+ "]";
}
}
Khwerero 4: Kuchotsa last_name ku database
Mtundu wa App: 4.0.0
Mtundu wa DB: v4
ndemanga
Chifukwa chakuti Baibulo code 3.0.0 sanagwiritse ntchito ndime last_name, palibe choipa chomwe chidzachitike panthawi ya kuphedwa ngati tibwerera ku 3.0.0 mutachotsa mzati ku database.
Zolemba za script
We will do it in the following way:
01) Run 1.0.0
02) Wait for the app (1.0.0) to boot
03) Generate a person by calling POST localhost:9991/person to version 1.0.0
04) Run 2.0.0
05) Wait for the app (2.0.0) to boot
06) Generate a person by calling POST localhost:9991/person to version 1.0.0
07) Generate a person by calling POST localhost:9992/person to version 2.0.0
08) Kill app (1.0.0)
09) Run 3.0.0
10) Wait for the app (3.0.0) to boot
11) Generate a person by calling POST localhost:9992/person to version 2.0.0
12) Generate a person by calling POST localhost:9993/person to version 3.0.0
13) Kill app (3.0.0)
14) Run 4.0.0
15) Wait for the app (4.0.0) to boot
16) Generate a person by calling POST localhost:9993/person to version 3.0.0
17) Generate a person by calling POST localhost:9994/person to version 4.0.0
Starting app in version 1.0.0
Generate a person in version 1.0.0
Sending a post to 127.0.0.1:9991/person. This is the response:
{"firstName":"52b6e125-4a5c-429b-a47a-ef18bbc639d2","lastName":"52b6e125-4a5c-429b-a47a-ef18bbc639d2"}
Starting app in version 2.0.0
Generate a person in version 1.0.0
Sending a post to 127.0.0.1:9991/person. This is the response:
{"firstName":"e41ee756-4fa7-4737-b832-e28827a00deb","lastName":"e41ee756-4fa7-4737-b832-e28827a00deb"}
Generate a person in version 2.0.0
Sending a post to 127.0.0.1:9992/person. This is the response:
{"firstName":"0c1240f5-649a-4bc5-8aa9-cff855f3927f","lastName":"0c1240f5-649a-4bc5-8aa9-cff855f3927f","surname":"0c1240f5-649a-4bc5-8aa9-cff855f3927f"}
Killing app 1.0.0
Starting app in version 3.0.0
Generate a person in version 2.0.0
Sending a post to 127.0.0.1:9992/person. This is the response:
{"firstName":"74d84a9e-5f44-43b8-907c-148c6d26a71b","lastName":"74d84a9e-5f44-43b8-907c-148c6d26a71b","surname":"74d84a9e-5f44-43b8-907c-148c6d26a71b"}
Generate a person in version 3.0.0
Sending a post to 127.0.0.1:9993/person. This is the response:
{"firstName":"c6564dbe-9ab5-40ae-9077-8ae6668d5862","surname":"c6564dbe-9ab5-40ae-9077-8ae6668d5862"}
Killing app 2.0.0
Starting app in version 4.0.0
Generate a person in version 3.0.0
Sending a post to 127.0.0.1:9993/person. This is the response:
{"firstName":"cbe942fc-832e-45e9-a838-0fae25c10a51","surname":"cbe942fc-832e-45e9-a838-0fae25c10a51"}
Generate a person in version 4.0.0
Sending a post to 127.0.0.1:9994/person. This is the response:
{"firstName":"ff6857ce-9c41-413a-863e-358e2719bf88","surname":"ff6857ce-9c41-413a-863e-358e2719bf88"}
DB kusintha
Zochepa v3 timangochotsa mzati last_name ndi kuwonjezera zoletsa zomwe zikusowa.
-- REMOVE THE COLUMN
ALTER TABLE PERSON DROP last_name;
-- ADD CONSTRAINTS
UPDATE PERSON SET surname='' WHERE surname IS NULL;
ALTER TABLE PERSON ALTER COLUMN surname VARCHAR NOT NULL;
kutumizidwa kwa mtundu wa pulogalamu 1.0.0 с v1 schema database (dzina lazambiri = last_name)
kutumizidwa kwa mtundu wa pulogalamu 2.0.0, zomwe zimasunga data mkati last_name и surname. Pulogalamuyi ikuchokera last_name. Nawonso database ili mu mtundu v2okhala ndi mizati ngati last_name, ndi surname. surname ndi kopi last_name. (Dziwani: ndime iyi siyenera kukhala ndi choletsa chachabechabe)
kutumizidwa kwa mtundu wa pulogalamu 3.0.0, zomwe zimangosunga deta mkati surname ndipo amawerenga kuchokera ku surname. Ponena za database, kusamuka komaliza kukuchitika last_name в surname. Komanso malire OSAKHALA kuchotsedwa last_name. Nawonso database ili mu mtundu v3
kutumizidwa kwa mtundu wa pulogalamu 4.0.0 - palibe kusintha komwe kumapangidwa ku code. Kutumiza kwa database v4, zomwe zimachotsa last_name. Apa mutha kuwonjezera zopinga zilizonse zomwe zikusowa ku database.
├── boot-flyway-v1 - 1.0.0 version of the app with v1 of the schema
├── boot-flyway-v2 - 2.0.0 version of the app with v2 of the schema (backward-compatible - app can be rolled back)
├── boot-flyway-v2-bad - 2.0.0.BAD version of the app with v2bad of the schema (backward-incompatible - app cannot be rolled back)
├── boot-flyway-v3 - 3.0.0 version of the app with v3 of the schema (app can be rolled back)
└── boot-flyway-v4 - 4.0.0 version of the app with v4 of the schema (app can be rolled back)